Refactor Instrumenters into InstrumentationModules - R, S, T, V (#1576)

This commit is contained in:
Mateusz Rzeszutek 2020-11-10 03:48:52 +01:00 committed by GitHub
parent 087a9cbc4e
commit 9d2db827b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
49 changed files with 896 additions and 734 deletions

View File

@ -22,7 +22,6 @@ import static net.bytebuddy.matcher.ElementMatchers.not;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments; import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import com.google.auto.service.AutoService;
import com.rabbitmq.client.AMQP; import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel; import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Consumer; import com.rabbitmq.client.Consumer;
@ -34,7 +33,7 @@ import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope; import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
@ -44,12 +43,7 @@ import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class) final class RabbitChannelInstrumentation implements TypeInstrumentation {
public class RabbitChannelInstrumentation extends Instrumenter.Default {
public RabbitChannelInstrumentation() {
super("amqp", "rabbitmq");
}
@Override @Override
public ElementMatcher<ClassLoader> classLoaderMatcher() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
@ -62,17 +56,6 @@ public class RabbitChannelInstrumentation extends Instrumenter.Default {
return implementsInterface(named("com.rabbitmq.client.Channel")); return implementsInterface(named("com.rabbitmq.client.Channel"));
} }
@Override
public String[] helperClassNames() {
return new String[] {
packageName + ".RabbitTracer",
packageName + ".TextMapInjectAdapter",
packageName + ".TextMapExtractAdapter",
packageName + ".TracedDelegatingConsumer",
RabbitCommandInstrumentation.class.getName() + "$SpanHolder",
};
}
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
// We want the advice applied in a specific order, so use an ordered map. // We want the advice applied in a specific order, so use an ordered map.

View File

@ -13,22 +13,16 @@ import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isConstructor; import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import com.rabbitmq.client.Command; import com.rabbitmq.client.Command;
import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Span;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class) final class RabbitCommandInstrumentation implements TypeInstrumentation {
public class RabbitCommandInstrumentation extends Instrumenter.Default {
public RabbitCommandInstrumentation() {
super("amqp", "rabbitmq");
}
@Override @Override
public ElementMatcher<ClassLoader> classLoaderMatcher() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
@ -41,17 +35,6 @@ public class RabbitCommandInstrumentation extends Instrumenter.Default {
return implementsInterface(named("com.rabbitmq.client.Command")); return implementsInterface(named("com.rabbitmq.client.Command"));
} }
@Override
public String[] helperClassNames() {
return new String[] {
packageName + ".RabbitTracer",
// These are only used by muzzleCheck:
packageName + ".TextMapExtractAdapter",
packageName + ".TracedDelegatingConsumer",
RabbitCommandInstrumentation.class.getName() + "$SpanHolder"
};
}
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap( return singletonMap(
@ -72,14 +55,5 @@ public class RabbitCommandInstrumentation extends Instrumenter.Default {
tracer().onCommand(span, command); tracer().onCommand(span, command);
} }
} }
/**
* This instrumentation will match with 2.6, but the channel instrumentation only matches with
* 2.7 because of TracedDelegatingConsumer. This unused method is added to ensure consistent
* muzzle validation by preventing match with 2.6.
*/
public static void muzzleCheck(TracedDelegatingConsumer consumer) {
consumer.handleRecoverOk(null);
}
} }
} }

View File

@ -0,0 +1,36 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.rabbitmq.amqp;
import static java.util.Arrays.asList;
import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.List;
@AutoService(InstrumentationModule.class)
public class RabbitMqInstrumentationModule extends InstrumentationModule {
public RabbitMqInstrumentationModule() {
super("amqp", "rabbitmq");
}
@Override
public String[] helperClassNames() {
return new String[] {
packageName + ".RabbitTracer",
packageName + ".TextMapInjectAdapter",
packageName + ".TextMapExtractAdapter",
packageName + ".TracedDelegatingConsumer",
RabbitCommandInstrumentation.class.getName() + "$SpanHolder",
};
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return asList(new RabbitChannelInstrumentation(), new RabbitCommandInstrumentation());
}
}

View File

@ -12,22 +12,15 @@ import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
import ratpack.func.Block; import ratpack.func.Block;
import ratpack.path.PathBinding;
@AutoService(Instrumenter.class) final class ContinuationInstrumentation implements TypeInstrumentation {
public final class ContinuationInstrumentation extends Instrumenter.Default {
public ContinuationInstrumentation() {
super("ratpack");
}
@Override @Override
public ElementMatcher<ClassLoader> classLoaderMatcher() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
@ -41,11 +34,6 @@ public final class ContinuationInstrumentation extends Instrumenter.Default {
.<TypeDescription>and(implementsInterface(named("ratpack.exec.internal.Continuation"))); .<TypeDescription>and(implementsInterface(named("ratpack.exec.internal.Continuation")));
} }
@Override
public String[] helperClassNames() {
return new String[] {packageName + ".BlockWrapper"};
}
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap( return singletonMap(
@ -59,10 +47,5 @@ public final class ContinuationInstrumentation extends Instrumenter.Default {
public static void wrap(@Advice.Argument(value = 0, readOnly = false) Block block) { public static void wrap(@Advice.Argument(value = 0, readOnly = false) Block block) {
block = BlockWrapper.wrapIfNeeded(block); block = BlockWrapper.wrapIfNeeded(block);
} }
public void muzzleCheck(PathBinding binding) {
// This was added in 1.4. Added here to ensure consistency with other instrumentation.
binding.getDescription();
}
} }
} }

View File

@ -10,8 +10,7 @@ import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -19,25 +18,14 @@ import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
import ratpack.exec.internal.Continuation; import ratpack.exec.internal.Continuation;
import ratpack.func.Action; import ratpack.func.Action;
import ratpack.path.PathBinding;
@AutoService(Instrumenter.class) final class DefaultExecutionInstrumentation implements TypeInstrumentation {
public final class DefaultExecutionInstrumentation extends Instrumenter.Default {
public DefaultExecutionInstrumentation() {
super("ratpack");
}
@Override @Override
public ElementMatcher<? super TypeDescription> typeMatcher() { public ElementMatcher<? super TypeDescription> typeMatcher() {
return named("ratpack.exec.internal.DefaultExecution"); return named("ratpack.exec.internal.DefaultExecution");
} }
@Override
public String[] helperClassNames() {
return new String[] {packageName + ".ActionWrapper"};
}
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap( return singletonMap(
@ -56,10 +44,5 @@ public final class DefaultExecutionInstrumentation extends Instrumenter.Default
onError = ActionWrapper.wrapIfNeeded(onError); onError = ActionWrapper.wrapIfNeeded(onError);
segment = ActionWrapper.wrapIfNeeded(segment); segment = ActionWrapper.wrapIfNeeded(segment);
} }
public void muzzleCheck(PathBinding binding) {
// This was added in 1.4. Added here to ensure consistency with other instrumentation.
binding.getDescription();
}
} }
} }

View File

@ -0,0 +1,39 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.ratpack;
import static java.util.Arrays.asList;
import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.List;
@AutoService(InstrumentationModule.class)
public class RatpackInstrumentationModule extends InstrumentationModule {
public RatpackInstrumentationModule() {
super("ratpack");
}
@Override
public String[] helperClassNames() {
return new String[] {
packageName + ".ActionWrapper",
packageName + ".BlockWrapper",
packageName + ".RatpackTracer",
packageName + ".TracingHandler",
};
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return asList(
new ContinuationInstrumentation(),
new DefaultExecutionInstrumentation(),
new ServerErrorHandlerInstrumentation(),
new ServerRegistryInstrumentation());
}
}

View File

@ -13,19 +13,13 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.not; import static net.bytebuddy.matcher.ElementMatchers.not;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import java.util.Map; import java.util.Map;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class) final class ServerErrorHandlerInstrumentation implements TypeInstrumentation {
public class ServerErrorHandlerInstrumentation extends Instrumenter.Default {
public ServerErrorHandlerInstrumentation() {
super("ratpack");
}
@Override @Override
public ElementMatcher<ClassLoader> classLoaderMatcher() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
@ -38,19 +32,12 @@ public class ServerErrorHandlerInstrumentation extends Instrumenter.Default {
return not(isAbstract()).and(implementsInterface(named("ratpack.error.ServerErrorHandler"))); return not(isAbstract()).and(implementsInterface(named("ratpack.error.ServerErrorHandler")));
} }
@Override
public String[] helperClassNames() {
return new String[] {
packageName + ".RatpackTracer",
};
}
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap( return singletonMap(
named("error") named("error")
.and(takesArgument(0, named("ratpack.handling.Context"))) .and(takesArgument(0, named("ratpack.handling.Context")))
.and(takesArgument(1, Throwable.class)), .and(takesArgument(1, Throwable.class)),
packageName + ".ErrorHandlerAdvice"); ErrorHandlerAdvice.class.getName());
} }
} }

View File

@ -10,36 +10,23 @@ import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.isStatic; import static net.bytebuddy.matcher.ElementMatchers.isStatic;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import java.util.Map; import java.util.Map;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class) final class ServerRegistryInstrumentation implements TypeInstrumentation {
public class ServerRegistryInstrumentation extends Instrumenter.Default {
public ServerRegistryInstrumentation() {
super("ratpack");
}
@Override @Override
public ElementMatcher<TypeDescription> typeMatcher() { public ElementMatcher<TypeDescription> typeMatcher() {
return named("ratpack.server.internal.ServerRegistry"); return named("ratpack.server.internal.ServerRegistry");
} }
@Override
public String[] helperClassNames() {
return new String[] {
packageName + ".RatpackTracer", packageName + ".TracingHandler",
};
}
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap( return singletonMap(
isMethod().and(isStatic()).and(named("buildBaseRegistry")), isMethod().and(isStatic()).and(named("buildBaseRegistry")),
packageName + ".ServerRegistryAdvice"); ServerRegistryAdvice.class.getName());
} }
} }

View File

@ -1,45 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.reactor;
import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isTypeInitializer;
import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import java.util.Map;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class)
public final class ReactorHooksInstrumentation extends Instrumenter.Default {
public ReactorHooksInstrumentation() {
super("reactor-core");
}
@Override
public String[] helperClassNames() {
return new String[] {
"io.opentelemetry.instrumentation.reactor.TracingOperator$Lifter",
"io.opentelemetry.instrumentation.reactor.TracingOperator",
"io.opentelemetry.instrumentation.reactor.TracingSubscriber"
};
}
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return named("reactor.core.publisher.Hooks");
}
@Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap(
isTypeInitializer().or(named("resetOnEachOperator")), packageName + ".ReactorHooksAdvice");
}
}

View File

@ -0,0 +1,55 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.reactor;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isTypeInitializer;
import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.List;
import java.util.Map;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
@AutoService(InstrumentationModule.class)
public final class ReactorInstrumentationModule extends InstrumentationModule {
public ReactorInstrumentationModule() {
super("reactor-core");
}
@Override
public String[] helperClassNames() {
return new String[] {
"io.opentelemetry.instrumentation.reactor.TracingOperator$Lifter",
"io.opentelemetry.instrumentation.reactor.TracingOperator",
"io.opentelemetry.instrumentation.reactor.TracingSubscriber"
};
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new HooksInstrumentation());
}
private static final class HooksInstrumentation implements TypeInstrumentation {
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return named("reactor.core.publisher.Hooks");
}
@Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap(
isTypeInitializer().or(named("resetOnEachOperator")), ReactorHooksAdvice.class.getName());
}
}
}

View File

@ -9,6 +9,7 @@ import static io.opentelemetry.javaagent.instrumentation.rediscala.RediscalaClie
import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.safeHasSuperType; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.safeHasSuperType;
import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.isPublic;
@ -19,7 +20,9 @@ import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Scope; import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.List;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -31,13 +34,27 @@ import scala.concurrent.Future;
import scala.runtime.AbstractFunction1; import scala.runtime.AbstractFunction1;
import scala.util.Try; import scala.util.Try;
@AutoService(Instrumenter.class) @AutoService(InstrumentationModule.class)
public final class RediscalaInstrumentation extends Instrumenter.Default { public final class RediscalaInstrumentationModule extends InstrumentationModule {
public RediscalaInstrumentation() { public RediscalaInstrumentationModule() {
super("rediscala", "redis"); super("rediscala", "redis");
} }
@Override
public String[] helperClassNames() {
return new String[] {
RediscalaInstrumentationModule.class.getName() + "$OnCompleteHandler",
packageName + ".RediscalaClientTracer",
};
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new RequestInstrumentation());
}
private static final class RequestInstrumentation implements TypeInstrumentation {
@Override @Override
public ElementMatcher<ClassLoader> classLoaderMatcher() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
return hasClassesNamed("redis.Request"); return hasClassesNamed("redis.Request");
@ -53,14 +70,6 @@ public final class RediscalaInstrumentation extends Instrumenter.Default {
"redis.RoundRobinPoolRequest")); "redis.RoundRobinPoolRequest"));
} }
@Override
public String[] helperClassNames() {
return new String[] {
RediscalaInstrumentation.class.getName() + "$OnCompleteHandler",
packageName + ".RediscalaClientTracer",
};
}
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap( return singletonMap(
@ -69,14 +78,15 @@ public final class RediscalaInstrumentation extends Instrumenter.Default {
.and(named("send")) .and(named("send"))
.and(takesArgument(0, named("redis.RedisCommand"))) .and(takesArgument(0, named("redis.RedisCommand")))
.and(returns(named("scala.concurrent.Future"))), .and(returns(named("scala.concurrent.Future"))),
RediscalaInstrumentation.class.getName() + "$RediscalaAdvice"); RediscalaInstrumentationModule.class.getName() + "$RediscalaAdvice");
}
} }
public static class RediscalaAdvice { public static class RediscalaAdvice {
@Advice.OnMethodEnter(suppress = Throwable.class) @Advice.OnMethodEnter(suppress = Throwable.class)
public static void onEnter( public static void onEnter(
@Advice.Argument(0) RedisCommand cmd, @Advice.Argument(0) RedisCommand<?, ?> cmd,
@Advice.Local("otelSpan") Span span, @Advice.Local("otelSpan") Span span,
@Advice.Local("otelScope") Scope scope) { @Advice.Local("otelScope") Scope scope) {
span = tracer().startSpan(cmd, cmd); span = tracer().startSpan(cmd, cmd);

View File

@ -6,6 +6,7 @@
package io.opentelemetry.javaagent.instrumentation.redisson; package io.opentelemetry.javaagent.instrumentation.redisson;
import static io.opentelemetry.javaagent.instrumentation.redisson.RedissonClientTracer.tracer; import static io.opentelemetry.javaagent.instrumentation.redisson.RedissonClientTracer.tracer;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
@ -13,7 +14,9 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Scope; import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.List;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -21,27 +24,35 @@ import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
import org.redisson.client.RedisConnection; import org.redisson.client.RedisConnection;
@AutoService(Instrumenter.class) @AutoService(InstrumentationModule.class)
public final class RedissonInstrumentation extends Instrumenter.Default { public final class RedissonInstrumentation extends InstrumentationModule {
public RedissonInstrumentation() { public RedissonInstrumentation() {
super("redisson", "redis"); super("redisson", "redis");
} }
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return named("org.redisson.client.RedisConnection");
}
@Override @Override
public String[] helperClassNames() { public String[] helperClassNames() {
return new String[] {packageName + ".RedissonClientTracer"}; return new String[] {packageName + ".RedissonClientTracer"};
} }
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new RedisConnectionInstrumentation());
}
private static final class RedisConnectionInstrumentation implements TypeInstrumentation {
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return named("org.redisson.client.RedisConnection");
}
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap( return singletonMap(
isMethod().and(named("send")), RedissonInstrumentation.class.getName() + "$RedissonAdvice"); isMethod().and(named("send")),
RedissonInstrumentation.class.getName() + "$RedissonAdvice");
}
} }
public static class RedissonAdvice { public static class RedissonAdvice {

View File

@ -7,6 +7,7 @@ package io.opentelemetry.javaagent.instrumentation.rmi.client;
import static io.opentelemetry.javaagent.instrumentation.rmi.client.RmiClientTracer.tracer; import static io.opentelemetry.javaagent.instrumentation.rmi.client.RmiClientTracer.tracer;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
@ -16,31 +17,39 @@ import com.google.auto.service.AutoService;
import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Scope; import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.List;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class) @AutoService(InstrumentationModule.class)
public final class RmiClientInstrumentation extends Instrumenter.Default { public final class RmiClientInstrumentationModule extends InstrumentationModule {
public RmiClientInstrumentation() { public RmiClientInstrumentationModule() {
super("rmi", "rmi-client"); super("rmi", "rmi-client");
} }
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return extendsClass(named("sun.rmi.server.UnicastRef"));
}
@Override @Override
public String[] helperClassNames() { public String[] helperClassNames() {
return new String[] {packageName + ".RmiClientTracer"}; return new String[] {packageName + ".RmiClientTracer"};
} }
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new ClientInstrumentation());
}
private static final class ClientInstrumentation implements TypeInstrumentation {
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return extendsClass(named("sun.rmi.server.UnicastRef"));
}
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap( return singletonMap(
@ -48,7 +57,8 @@ public final class RmiClientInstrumentation extends Instrumenter.Default {
.and(named("invoke")) .and(named("invoke"))
.and(takesArgument(0, named("java.rmi.Remote"))) .and(takesArgument(0, named("java.rmi.Remote")))
.and(takesArgument(1, named("java.lang.reflect.Method"))), .and(takesArgument(1, named("java.lang.reflect.Method"))),
getClass().getName() + "$RmiClientAdvice"); RmiClientInstrumentationModule.class.getName() + "$RmiClientAdvice");
}
} }
public static class RmiClientAdvice { public static class RmiClientAdvice {

View File

@ -0,0 +1,47 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.rmi.context;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonMap;
import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.instrumentation.rmi.context.client.RmiClientContextInstrumentation;
import io.opentelemetry.javaagent.instrumentation.rmi.context.server.RmiServerContextInstrumentation;
import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.List;
import java.util.Map;
@AutoService(InstrumentationModule.class)
public class RmiContextPropagationInstrumentationModule extends InstrumentationModule {
public RmiContextPropagationInstrumentationModule() {
super("rmi", "rmi-context-propagator");
}
@Override
public String[] helperClassNames() {
return new String[] {
"io.opentelemetry.javaagent.instrumentation.rmi.context.ContextPayload$InjectAdapter",
"io.opentelemetry.javaagent.instrumentation.rmi.context.ContextPayload$ExtractAdapter",
"io.opentelemetry.javaagent.instrumentation.rmi.context.ContextPayload",
"io.opentelemetry.javaagent.instrumentation.rmi.context.ContextPropagator",
"io.opentelemetry.javaagent.instrumentation.rmi.context.server.ContextDispatcher",
"io.opentelemetry.javaagent.instrumentation.rmi.context.server.ContextDispatcher$NoopRemote"
};
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return asList(new RmiClientContextInstrumentation(), new RmiServerContextInstrumentation());
}
@Override
public Map<String, String> contextStore() {
// caching if a connection can support enhanced format
return singletonMap("sun.rmi.transport.Connection", "java.lang.Boolean");
}
}

View File

@ -12,12 +12,11 @@ import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService;
import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Span;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore; import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.rmi.server.ObjID; import java.rmi.server.ObjID;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
@ -47,34 +46,13 @@ import sun.rmi.transport.Connection;
* that instruction will essentially be garbage data and will cause the parsing loop to throw * that instruction will essentially be garbage data and will cause the parsing loop to throw
* exception and shutdown the connection which we do not want * exception and shutdown the connection which we do not want
*/ */
@AutoService(Instrumenter.class) public final class RmiClientContextInstrumentation implements TypeInstrumentation {
public class RmiClientContextInstrumentation extends Instrumenter.Default {
public RmiClientContextInstrumentation() {
super("rmi", "rmi-context-propagator", "rmi-client-context-propagator");
}
@Override @Override
public ElementMatcher<? super TypeDescription> typeMatcher() { public ElementMatcher<? super TypeDescription> typeMatcher() {
return extendsClass(named("sun.rmi.transport.StreamRemoteCall")); return extendsClass(named("sun.rmi.transport.StreamRemoteCall"));
} }
@Override
public Map<String, String> contextStore() {
// caching if a connection can support enhanced format
return singletonMap("sun.rmi.transport.Connection", "java.lang.Boolean");
}
@Override
public String[] helperClassNames() {
return new String[] {
"io.opentelemetry.javaagent.instrumentation.rmi.context.ContextPayload$InjectAdapter",
"io.opentelemetry.javaagent.instrumentation.rmi.context.ContextPayload$ExtractAdapter",
"io.opentelemetry.javaagent.instrumentation.rmi.context.ContextPayload",
"io.opentelemetry.javaagent.instrumentation.rmi.context.ContextPropagator"
};
}
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap( return singletonMap(

View File

@ -13,8 +13,7 @@ import static net.bytebuddy.matcher.ElementMatchers.isStatic;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -22,30 +21,13 @@ import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
import sun.rmi.transport.Target; import sun.rmi.transport.Target;
@AutoService(Instrumenter.class) public final class RmiServerContextInstrumentation implements TypeInstrumentation {
public class RmiServerContextInstrumentation extends Instrumenter.Default {
public RmiServerContextInstrumentation() {
super("rmi", "rmi-context-propagator", "rmi-server-context-propagator");
}
@Override @Override
public ElementMatcher<? super TypeDescription> typeMatcher() { public ElementMatcher<? super TypeDescription> typeMatcher() {
return extendsClass(named("sun.rmi.transport.ObjectTable")); return extendsClass(named("sun.rmi.transport.ObjectTable"));
} }
@Override
public String[] helperClassNames() {
return new String[] {
"io.opentelemetry.javaagent.instrumentation.rmi.context.ContextPayload$InjectAdapter",
"io.opentelemetry.javaagent.instrumentation.rmi.context.ContextPayload$ExtractAdapter",
"io.opentelemetry.javaagent.instrumentation.rmi.context.ContextPayload",
"io.opentelemetry.javaagent.instrumentation.rmi.context.ContextPropagator",
packageName + ".ContextDispatcher",
packageName + ".ContextDispatcher$NoopRemote"
};
}
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap( return singletonMap(

View File

@ -8,6 +8,7 @@ package io.opentelemetry.javaagent.instrumentation.rmi.server;
import static io.opentelemetry.javaagent.instrumentation.api.rmi.ThreadLocalContext.THREAD_LOCAL_CONTEXT; import static io.opentelemetry.javaagent.instrumentation.api.rmi.ThreadLocalContext.THREAD_LOCAL_CONTEXT;
import static io.opentelemetry.javaagent.instrumentation.rmi.server.RmiServerTracer.tracer; import static io.opentelemetry.javaagent.instrumentation.rmi.server.RmiServerTracer.tracer;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.isPublic;
@ -20,17 +21,19 @@ import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Context; import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope; import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.rmi.server.RemoteServer; import java.rmi.server.RemoteServer;
import java.util.List;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class) @AutoService(InstrumentationModule.class)
public final class RmiServerInstrumentation extends Instrumenter.Default { public final class RmiServerInstrumentation extends InstrumentationModule {
public RmiServerInstrumentation() { public RmiServerInstrumentation() {
super("rmi", "rmi-server"); super("rmi", "rmi-server");
@ -41,6 +44,12 @@ public final class RmiServerInstrumentation extends Instrumenter.Default {
return new String[] {packageName + ".RmiServerTracer"}; return new String[] {packageName + ".RmiServerTracer"};
} }
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new ServerInstrumentation());
}
private static final class ServerInstrumentation implements TypeInstrumentation {
@Override @Override
public ElementMatcher<TypeDescription> typeMatcher() { public ElementMatcher<TypeDescription> typeMatcher() {
return extendsClass(named("java.rmi.server.RemoteServer")); return extendsClass(named("java.rmi.server.RemoteServer"));
@ -49,7 +58,9 @@ public final class RmiServerInstrumentation extends Instrumenter.Default {
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap( return singletonMap(
isMethod().and(isPublic()).and(not(isStatic())), getClass().getName() + "$ServerAdvice"); isMethod().and(isPublic()).and(not(isStatic())),
RmiServerInstrumentation.class.getName() + "$ServerAdvice");
}
} }
public static class ServerAdvice { public static class ServerAdvice {

View File

@ -0,0 +1,40 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.scalaconcurrent;
import static io.opentelemetry.javaagent.instrumentation.scalaconcurrent.ScalaForkJoinTaskInstrumentation.TASK_CLASS_NAME;
import static java.util.Arrays.asList;
import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.instrumentation.api.concurrent.State;
import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
@AutoService(InstrumentationModule.class)
public class ScalaConcurrentInstrumentationModule extends InstrumentationModule {
public ScalaConcurrentInstrumentationModule() {
super("java_concurrent", "scala_concurrent");
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return asList(new ScalaForkJoinPoolInstrumentation(), new ScalaForkJoinTaskInstrumentation());
}
@Override
public Map<String, String> contextStore() {
Map<String, String> map = new HashMap<>();
map.put(Runnable.class.getName(), State.class.getName());
map.put(Callable.class.getName(), State.class.getName());
map.put(TASK_CLASS_NAME, State.class.getName());
return Collections.unmodifiableMap(map);
}
}

View File

@ -5,18 +5,16 @@
package io.opentelemetry.javaagent.instrumentation.scalaconcurrent; package io.opentelemetry.javaagent.instrumentation.scalaconcurrent;
import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.nameMatches; import static net.bytebuddy.matcher.ElementMatchers.nameMatches;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore; import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import io.opentelemetry.javaagent.instrumentation.api.concurrent.ExecutorInstrumentationUtils; import io.opentelemetry.javaagent.instrumentation.api.concurrent.ExecutorInstrumentationUtils;
import io.opentelemetry.javaagent.instrumentation.api.concurrent.State; import io.opentelemetry.javaagent.instrumentation.api.concurrent.State;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
@ -25,12 +23,7 @@ import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
import scala.concurrent.forkjoin.ForkJoinTask; import scala.concurrent.forkjoin.ForkJoinTask;
@AutoService(Instrumenter.class) final class ScalaForkJoinPoolInstrumentation implements TypeInstrumentation {
public final class ScalaForkJoinPoolInstrumentation extends Instrumenter.Default {
public ScalaForkJoinPoolInstrumentation() {
super("java_concurrent", "scala_concurrent");
}
@Override @Override
public ElementMatcher<TypeDescription> typeMatcher() { public ElementMatcher<TypeDescription> typeMatcher() {
@ -38,11 +31,6 @@ public final class ScalaForkJoinPoolInstrumentation extends Instrumenter.Default
return named("scala.concurrent.forkjoin.ForkJoinPool"); return named("scala.concurrent.forkjoin.ForkJoinPool");
} }
@Override
public Map<String, String> contextStore() {
return singletonMap(ScalaForkJoinTaskInstrumentation.TASK_CLASS_NAME, State.class.getName());
}
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
Map<ElementMatcher<? super MethodDescription>, String> transformers = new HashMap<>(); Map<ElementMatcher<? super MethodDescription>, String> transformers = new HashMap<>();
@ -65,7 +53,7 @@ public final class ScalaForkJoinPoolInstrumentation extends Instrumenter.Default
@Advice.OnMethodEnter(suppress = Throwable.class) @Advice.OnMethodEnter(suppress = Throwable.class)
public static State enterJobSubmit( public static State enterJobSubmit(
@Advice.Argument(value = 0, readOnly = false) ForkJoinTask task) { @Advice.Argument(value = 0, readOnly = false) ForkJoinTask<?> task) {
if (ExecutorInstrumentationUtils.shouldAttachStateToTask(task)) { if (ExecutorInstrumentationUtils.shouldAttachStateToTask(task)) {
ContextStore<ForkJoinTask, State> contextStore = ContextStore<ForkJoinTask, State> contextStore =
InstrumentationContext.get(ForkJoinTask.class, State.class); InstrumentationContext.get(ForkJoinTask.class, State.class);

View File

@ -13,15 +13,12 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.not; import static net.bytebuddy.matcher.ElementMatchers.not;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments; import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import com.google.auto.service.AutoService;
import io.opentelemetry.context.Scope; import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore; import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.concurrent.AdviceUtils; import io.opentelemetry.javaagent.instrumentation.api.concurrent.AdviceUtils;
import io.opentelemetry.javaagent.instrumentation.api.concurrent.State; import io.opentelemetry.javaagent.instrumentation.api.concurrent.State;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
@ -37,15 +34,10 @@ import scala.concurrent.forkjoin.ForkJoinTask;
* <p>Note: There are quite a few separate implementations of {@code ForkJoinTask}/{@code * <p>Note: There are quite a few separate implementations of {@code ForkJoinTask}/{@code
* ForkJoinPool}: JVM, Akka, Scala, Netty to name a few. This class handles Scala version. * ForkJoinPool}: JVM, Akka, Scala, Netty to name a few. This class handles Scala version.
*/ */
@AutoService(Instrumenter.class) final class ScalaForkJoinTaskInstrumentation implements TypeInstrumentation {
public final class ScalaForkJoinTaskInstrumentation extends Instrumenter.Default {
static final String TASK_CLASS_NAME = "scala.concurrent.forkjoin.ForkJoinTask"; static final String TASK_CLASS_NAME = "scala.concurrent.forkjoin.ForkJoinTask";
public ScalaForkJoinTaskInstrumentation() {
super("java_concurrent", "scala_concurrent");
}
@Override @Override
public ElementMatcher<ClassLoader> classLoaderMatcher() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
// Optimization for expensive typeMatcher. // Optimization for expensive typeMatcher.
@ -57,15 +49,6 @@ public final class ScalaForkJoinTaskInstrumentation extends Instrumenter.Default
return extendsClass(named(TASK_CLASS_NAME)); return extendsClass(named(TASK_CLASS_NAME));
} }
@Override
public Map<String, String> contextStore() {
Map<String, String> map = new HashMap<>();
map.put(Runnable.class.getName(), State.class.getName());
map.put(Callable.class.getName(), State.class.getName());
map.put(TASK_CLASS_NAME, State.class.getName());
return Collections.unmodifiableMap(map);
}
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap( return singletonMap(
@ -82,7 +65,7 @@ public final class ScalaForkJoinTaskInstrumentation extends Instrumenter.Default
* need to use that state. * need to use that state.
*/ */
@Advice.OnMethodEnter(suppress = Throwable.class) @Advice.OnMethodEnter(suppress = Throwable.class)
public static Scope enter(@Advice.This ForkJoinTask thiz) { public static Scope enter(@Advice.This ForkJoinTask<?> thiz) {
ContextStore<ForkJoinTask, State> contextStore = ContextStore<ForkJoinTask, State> contextStore =
InstrumentationContext.get(ForkJoinTask.class, State.class); InstrumentationContext.get(ForkJoinTask.class, State.class);
Scope scope = AdviceUtils.startTaskScope(contextStore, thiz); Scope scope = AdviceUtils.startTaskScope(contextStore, thiz);

View File

@ -59,16 +59,16 @@ Next, request passes several other methods from Servlet specification, such as
`protected void org.springframework.web.servlet.FrameworkServlet#doGet(HttpServletRequest, HttpServletResponse)`. `protected void org.springframework.web.servlet.FrameworkServlet#doGet(HttpServletRequest, HttpServletResponse)`.
They are the targets for `HttpServletInstrumentation`. They are the targets for `HttpServletInstrumentationModule`.
From the observability point of view nothing of interest usually happens inside these methods. From the observability point of view nothing of interest usually happens inside these methods.
Thus it usually does not make sense to create spans from them, as they would only add useless noise. Thus it usually does not make sense to create spans from them, as they would only add useless noise.
For this reason `HttpServletInstrumentation` is disabled by default. For this reason `HttpServletInstrumentationModule` is disabled by default.
In rare cases when you need it, you can enable it using configuration property `otel.integration.servlet-service.enabled`. In rare cases when you need it, you can enable it using configuration property `otel.instrumentation.servlet-service.enabled`.
In exactly the same situation are all other Servlet filters beyond the initial entry point. In exactly the same situation are all other Servlet filters beyond the initial entry point.
Usually unimportant, they may be sometimes of interest during troubleshooting. Usually unimportant, they may be sometimes of interest during troubleshooting.
They are instrumented by `FilterInstrumentation` which is also disabled by default. They are instrumented by `FilterInstrumentationModule` which is also disabled by default.
You can enable it with the configuration property `otel.integration.servlet-filter.enabled`. You can enable it with the configuration property `otel.instrumentation.servlet-filter.enabled`.
At last, request processing may reach the specific framework that your application uses. At last, request processing may reach the specific framework that your application uses.
In this case Spring MVC and `OwnerController.initCreationForm`. In this case Spring MVC and `OwnerController.initCreationForm`.
@ -88,10 +88,10 @@ Of course, still adhering to OpenTelemetry
[semantic conventions](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/http.md). [semantic conventions](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/http.md).
## Additional instrumentations ## Additional instrumentations
`RequestDispatcherInstrumentation` instruments `javax.servlet.RequestDispatcher.forward` and `RequestDispatcherInstrumentationModule` instruments `javax.servlet.RequestDispatcher.forward` and
`javax.servlet.RequestDispatcher.include` methods to create new `INTERNAL` spans around their `javax.servlet.RequestDispatcher.include` methods to create new `INTERNAL` spans around their
invocations. invocations.
`HttpServletResponseInstrumentation` instruments `javax.servlet.http.HttpServletResponse.sendError` `HttpServletResponseInstrumentationModule` instruments `javax.servlet.http.HttpServletResponse.sendError`
and `javax.servlet.http.HttpServletResponse.sendRedirect` methods to create new `INTERNAL` spans and `javax.servlet.http.HttpServletResponse.sendRedirect` methods to create new `INTERNAL` spans
around their invocations. around their invocations.

View File

@ -8,15 +8,12 @@ package io.opentelemetry.javaagent.instrumentation.servlet.v2_2;
import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.safeHasSuperType; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.safeHasSuperType;
import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf;
import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.not;
import com.google.auto.service.AutoService;
import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Scope; import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import javax.servlet.ServletRequest; import javax.servlet.ServletRequest;
@ -38,16 +35,10 @@ import net.bytebuddy.matcher.ElementMatcher;
* ServletResponse, Throwable, Span, Scope)} can get it from context and set required span * ServletResponse, Throwable, Span, Scope)} can get it from context and set required span
* attribute. * attribute.
*/ */
@AutoService(Instrumenter.class) final class HttpServletResponseInstrumentation implements TypeInstrumentation {
public final class Servlet2ResponseStatusInstrumentation extends Instrumenter.Default {
public Servlet2ResponseStatusInstrumentation() {
super("servlet", "servlet-2");
}
// this is required to make sure servlet 2 instrumentation won't apply to servlet 3
@Override @Override
public ElementMatcher<ClassLoader> classLoaderMatcher() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
return not(hasClassesNamed("javax.servlet.AsyncEvent", "javax.servlet.AsyncListener")); return hasClassesNamed("javax.servlet.http.HttpServletResponse");
} }
@Override @Override
@ -55,20 +46,15 @@ public final class Servlet2ResponseStatusInstrumentation extends Instrumenter.De
return safeHasSuperType(named("javax.servlet.http.HttpServletResponse")); return safeHasSuperType(named("javax.servlet.http.HttpServletResponse"));
} }
@Override
public Map<String, String> contextStore() {
return singletonMap("javax.servlet.ServletResponse", Integer.class.getName());
}
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
Map<ElementMatcher<? super MethodDescription>, String> transformers = new HashMap<>(); Map<ElementMatcher<? super MethodDescription>, String> transformers = new HashMap<>();
transformers.put( transformers.put(
namedOneOf("sendError", "setStatus"), namedOneOf("sendError", "setStatus"),
Servlet2ResponseStatusInstrumentation.class.getName() + "$Servlet2ResponseStatusAdvice"); HttpServletResponseInstrumentation.class.getName() + "$Servlet2ResponseStatusAdvice");
transformers.put( transformers.put(
named("sendRedirect"), named("sendRedirect"),
Servlet2ResponseStatusInstrumentation.class.getName() + "$Servlet2ResponseRedirectAdvice"); HttpServletResponseInstrumentation.class.getName() + "$Servlet2ResponseRedirectAdvice");
return transformers; return transformers;
} }

View File

@ -0,0 +1,52 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.servlet.v2_2;
import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed;
import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.not;
import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import net.bytebuddy.matcher.ElementMatcher;
@AutoService(InstrumentationModule.class)
public class Servlet2InstrumentationModule extends InstrumentationModule {
public Servlet2InstrumentationModule() {
super("servlet", "servlet-2");
}
// this is required to make sure servlet 2 instrumentation won't apply to servlet 3
@Override
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
return not(hasClassesNamed("javax.servlet.AsyncEvent", "javax.servlet.AsyncListener"));
}
@Override
public String[] helperClassNames() {
return new String[] {
"io.opentelemetry.instrumentation.servlet.ServletHttpServerTracer",
"io.opentelemetry.instrumentation.servlet.HttpServletRequestGetter",
packageName + ".ResponseWithStatus",
packageName + ".Servlet2HttpServerTracer"
};
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return Arrays.asList(
new HttpServletResponseInstrumentation(), new ServletAndFilterChainInstrumentation());
}
@Override
public Map<String, String> contextStore() {
return singletonMap("javax.servlet.ServletResponse", Integer.class.getName());
}
}

View File

@ -11,29 +11,20 @@ import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.not;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import java.util.Map; import java.util.Map;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class) final class ServletAndFilterChainInstrumentation implements TypeInstrumentation {
public final class Servlet2Instrumentation extends Instrumenter.Default {
public Servlet2Instrumentation() {
super("servlet", "servlet-2");
}
// this is required to make sure servlet 2 instrumentation won't apply to servlet 3
@Override @Override
public ElementMatcher<ClassLoader> classLoaderMatcher() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
// Optimization for expensive typeMatcher. // Optimization for expensive typeMatcher.
return hasClassesNamed("javax.servlet.http.HttpServlet") return hasClassesNamed("javax.servlet.http.HttpServlet");
.and(not(hasClassesNamed("javax.servlet.AsyncEvent", "javax.servlet.AsyncListener")));
} }
@Override @Override
@ -41,22 +32,6 @@ public final class Servlet2Instrumentation extends Instrumenter.Default {
return safeHasSuperType( return safeHasSuperType(
namedOneOf("javax.servlet.FilterChain", "javax.servlet.http.HttpServlet")); namedOneOf("javax.servlet.FilterChain", "javax.servlet.http.HttpServlet"));
} }
@Override
public Map<String, String> contextStore() {
return singletonMap("javax.servlet.ServletResponse", Integer.class.getName());
}
@Override
public String[] helperClassNames() {
return new String[] {
"io.opentelemetry.instrumentation.servlet.ServletHttpServerTracer",
"io.opentelemetry.instrumentation.servlet.HttpServletRequestGetter",
packageName + ".ResponseWithStatus",
packageName + ".Servlet2HttpServerTracer"
};
}
/** /**
* Here we are instrumenting the public method for HttpServlet. This should ensure that this * Here we are instrumenting the public method for HttpServlet. This should ensure that this
* advice is always called before HttpServletInstrumentation which is instrumenting the protected * advice is always called before HttpServletInstrumentation which is instrumenting the protected
@ -69,6 +44,6 @@ public final class Servlet2Instrumentation extends Instrumenter.Default {
.and(takesArgument(0, named("javax.servlet.ServletRequest"))) .and(takesArgument(0, named("javax.servlet.ServletRequest")))
.and(takesArgument(1, named("javax.servlet.ServletResponse"))) .and(takesArgument(1, named("javax.servlet.ServletResponse")))
.and(isPublic()), .and(isPublic()),
packageName + ".Servlet2Advice"); Servlet2Advice.class.getName());
} }
} }

View File

@ -13,12 +13,11 @@ import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Context; import io.opentelemetry.context.Context;
import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Map; import java.util.Map;
import javax.servlet.AsyncContext; import javax.servlet.AsyncContext;
import javax.servlet.ServletRequest; import javax.servlet.ServletRequest;
@ -27,20 +26,7 @@ import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class) final class AsyncContextInstrumentation implements TypeInstrumentation {
public final class AsyncContextInstrumentation extends Instrumenter.Default {
public AsyncContextInstrumentation() {
super("servlet", "servlet-3");
}
@Override
public String[] helperClassNames() {
return new String[] {
"io.opentelemetry.instrumentation.servlet.HttpServletRequestGetter",
"io.opentelemetry.instrumentation.servlet.ServletHttpServerTracer",
};
}
@Override @Override
public ElementMatcher<ClassLoader> classLoaderMatcher() { public ElementMatcher<ClassLoader> classLoaderMatcher() {

View File

@ -0,0 +1,36 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.servlet.v3_0;
import static java.util.Arrays.asList;
import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.List;
@AutoService(InstrumentationModule.class)
public class Servlet3InstrumentationModule extends InstrumentationModule {
public Servlet3InstrumentationModule() {
super("servlet", "servlet-3");
}
@Override
public String[] helperClassNames() {
return new String[] {
"io.opentelemetry.instrumentation.servlet.HttpServletRequestGetter",
"io.opentelemetry.instrumentation.servlet.ServletHttpServerTracer",
packageName + ".Servlet3Advice",
packageName + ".Servlet3HttpServerTracer",
packageName + ".TagSettingAsyncListener"
};
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return asList(new AsyncContextInstrumentation(), new ServletAndFilterChainInstrumentation());
}
}

View File

@ -13,19 +13,13 @@ import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import java.util.Map; import java.util.Map;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class) final class ServletAndFilterChainInstrumentation implements TypeInstrumentation {
public final class Servlet3Instrumentation extends Instrumenter.Default {
public Servlet3Instrumentation() {
super("servlet", "servlet-3");
}
@Override @Override
public ElementMatcher<ClassLoader> classLoaderMatcher() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
// Optimization for expensive typeMatcher. // Optimization for expensive typeMatcher.
@ -38,17 +32,6 @@ public final class Servlet3Instrumentation extends Instrumenter.Default {
namedOneOf("javax.servlet.FilterChain", "javax.servlet.http.HttpServlet")); namedOneOf("javax.servlet.FilterChain", "javax.servlet.http.HttpServlet"));
} }
@Override
public String[] helperClassNames() {
return new String[] {
"io.opentelemetry.instrumentation.servlet.HttpServletRequestGetter",
"io.opentelemetry.instrumentation.servlet.ServletHttpServerTracer",
packageName + ".Servlet3Advice",
packageName + ".Servlet3HttpServerTracer",
packageName + ".TagSettingAsyncListener"
};
}
/** /**
* Here we are instrumenting the public method for HttpServlet. This should ensure that this * Here we are instrumenting the public method for HttpServlet. This should ensure that this
* advice is always called before HttpServletInstrumentation which is instrumenting the protected * advice is always called before HttpServletInstrumentation which is instrumenting the protected
@ -61,6 +44,6 @@ public final class Servlet3Instrumentation extends Instrumenter.Default {
.and(takesArgument(0, named("javax.servlet.ServletRequest"))) .and(takesArgument(0, named("javax.servlet.ServletRequest")))
.and(takesArgument(1, named("javax.servlet.ServletResponse"))) .and(takesArgument(1, named("javax.servlet.ServletResponse")))
.and(isPublic()), .and(isPublic()),
packageName + ".Servlet3Advice"); Servlet3Advice.class.getName());
} }
} }

View File

@ -4,7 +4,12 @@ muzzle {
pass { pass {
group = "javax.servlet" group = "javax.servlet"
module = "servlet-api" module = "servlet-api"
versions = "[2.2,)" versions = "(0,)"
}
pass {
group = "javax.servlet"
module = 'javax.servlet-api'
versions = "[3.0,)"
assertInverse = true assertInverse = true
} }
} }

View File

@ -10,6 +10,7 @@ import static io.opentelemetry.javaagent.instrumentation.servlet.dispatcher.Requ
import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface;
import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
@ -22,8 +23,10 @@ import io.opentelemetry.api.trace.SpanContext;
import io.opentelemetry.context.Context; import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope; import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.List;
import java.util.Map; import java.util.Map;
import javax.servlet.RequestDispatcher; import javax.servlet.RequestDispatcher;
import javax.servlet.ServletRequest; import javax.servlet.ServletRequest;
@ -32,12 +35,30 @@ import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class) @AutoService(InstrumentationModule.class)
public final class RequestDispatcherInstrumentation extends Instrumenter.Default { public final class RequestDispatcherInstrumentationModule extends InstrumentationModule {
public RequestDispatcherInstrumentation() { public RequestDispatcherInstrumentationModule() {
super("servlet", "servlet-dispatcher"); super("servlet", "servlet-dispatcher");
} }
@Override
public String[] helperClassNames() {
return new String[] {
packageName + ".RequestDispatcherTracer",
};
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new RequestDispatcherInstrumentation());
}
@Override
public Map<String, String> contextStore() {
return singletonMap("javax.servlet.RequestDispatcher", String.class.getName());
}
private static final class RequestDispatcherInstrumentation implements TypeInstrumentation {
@Override @Override
public ElementMatcher<ClassLoader> classLoaderMatcher() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
// Optimization for expensive typeMatcher. // Optimization for expensive typeMatcher.
@ -49,18 +70,6 @@ public final class RequestDispatcherInstrumentation extends Instrumenter.Default
return implementsInterface(named("javax.servlet.RequestDispatcher")); return implementsInterface(named("javax.servlet.RequestDispatcher"));
} }
@Override
public String[] helperClassNames() {
return new String[] {
packageName + ".RequestDispatcherTracer",
};
}
@Override
public Map<String, String> contextStore() {
return singletonMap("javax.servlet.RequestDispatcher", String.class.getName());
}
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap( return singletonMap(
@ -69,7 +78,8 @@ public final class RequestDispatcherInstrumentation extends Instrumenter.Default
.and(takesArgument(0, named("javax.servlet.ServletRequest"))) .and(takesArgument(0, named("javax.servlet.ServletRequest")))
.and(takesArgument(1, named("javax.servlet.ServletResponse"))) .and(takesArgument(1, named("javax.servlet.ServletResponse")))
.and(isPublic()), .and(isPublic()),
getClass().getName() + "$RequestDispatcherAdvice"); RequestDispatcherInstrumentationModule.class.getName() + "$RequestDispatcherAdvice");
}
} }
public static class RequestDispatcherAdvice { public static class RequestDispatcherAdvice {

View File

@ -8,6 +8,7 @@ package io.opentelemetry.javaagent.instrumentation.servlet.filter;
import static io.opentelemetry.javaagent.instrumentation.servlet.filter.FilterTracer.tracer; import static io.opentelemetry.javaagent.instrumentation.servlet.filter.FilterTracer.tracer;
import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
@ -18,7 +19,9 @@ import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Span.Kind; import io.opentelemetry.api.trace.Span.Kind;
import io.opentelemetry.context.Scope; import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.List;
import java.util.Map; import java.util.Map;
import javax.servlet.Filter; import javax.servlet.Filter;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
@ -31,9 +34,9 @@ import net.bytebuddy.matcher.ElementMatcher;
* *
* <p>See README.md for more information about different servlet instrumentations. * <p>See README.md for more information about different servlet instrumentations.
*/ */
@AutoService(Instrumenter.class) @AutoService(InstrumentationModule.class)
public final class FilterInstrumentation extends Instrumenter.Default { public final class FilterInstrumentationModule extends InstrumentationModule {
public FilterInstrumentation() { public FilterInstrumentationModule() {
super("servlet-filter"); super("servlet-filter");
} }
@ -42,18 +45,6 @@ public final class FilterInstrumentation extends Instrumenter.Default {
return false; return false;
} }
@Override
public ElementMatcher<ClassLoader> classLoaderMatcher() {
// Optimization for expensive typeMatcher.
// return hasClassesNamed("javax.servlet.Filter"); // Not available in 2.2
return hasClassesNamed("javax.servlet.http.HttpServlet");
}
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return implementsInterface(named("javax.servlet.Filter"));
}
@Override @Override
public String[] helperClassNames() { public String[] helperClassNames() {
return new String[] { return new String[] {
@ -61,6 +52,23 @@ public final class FilterInstrumentation extends Instrumenter.Default {
}; };
} }
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new FilterInstrumentation());
}
private static final class FilterInstrumentation implements TypeInstrumentation {
@Override
public ElementMatcher<ClassLoader> classLoaderMatcher() {
// Optimization for expensive typeMatcher.
return hasClassesNamed("javax.servlet.Filter");
}
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return implementsInterface(named("javax.servlet.Filter"));
}
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap( return singletonMap(
@ -68,7 +76,8 @@ public final class FilterInstrumentation extends Instrumenter.Default {
.and(takesArgument(0, named("javax.servlet.ServletRequest"))) .and(takesArgument(0, named("javax.servlet.ServletRequest")))
.and(takesArgument(1, named("javax.servlet.ServletResponse"))) .and(takesArgument(1, named("javax.servlet.ServletResponse")))
.and(isPublic()), .and(isPublic()),
getClass().getName() + "$FilterAdvice"); FilterInstrumentationModule.class.getName() + "$FilterAdvice");
}
} }
public static class FilterAdvice { public static class FilterAdvice {

View File

@ -8,6 +8,7 @@ package io.opentelemetry.javaagent.instrumentation.servlet.http;
import static io.opentelemetry.javaagent.instrumentation.servlet.http.HttpServletTracer.tracer; import static io.opentelemetry.javaagent.instrumentation.servlet.http.HttpServletTracer.tracer;
import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isProtected; import static net.bytebuddy.matcher.ElementMatchers.isProtected;
import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.isPublic;
@ -19,18 +20,21 @@ import com.google.auto.service.AutoService;
import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Scope; import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.List;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
// Please read README.md of this subproject to understand what is this instrumentation. // Please read README.md of this subproject to understand what this instrumentation is and why it
@AutoService(Instrumenter.class) // requires a separate module.
public final class HttpServletInstrumentation extends Instrumenter.Default { @AutoService(InstrumentationModule.class)
public HttpServletInstrumentation() { public final class HttpServletInstrumentationModule extends InstrumentationModule {
public HttpServletInstrumentationModule() {
super("servlet-service"); super("servlet-service");
} }
@ -39,6 +43,19 @@ public final class HttpServletInstrumentation extends Instrumenter.Default {
return false; return false;
} }
@Override
public String[] helperClassNames() {
return new String[] {
packageName + ".HttpServletTracer",
};
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new HttpServletInstrumentation());
}
private static final class HttpServletInstrumentation implements TypeInstrumentation {
@Override @Override
public ElementMatcher<ClassLoader> classLoaderMatcher() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
// Optimization for expensive typeMatcher. // Optimization for expensive typeMatcher.
@ -50,16 +67,10 @@ public final class HttpServletInstrumentation extends Instrumenter.Default {
return extendsClass(named("javax.servlet.http.HttpServlet")); return extendsClass(named("javax.servlet.http.HttpServlet"));
} }
@Override
public String[] helperClassNames() {
return new String[] {
packageName + ".HttpServletTracer",
};
}
/** /**
* Here we are instrumenting the protected method for HttpServlet. This should ensure that this * Here we are instrumenting the protected method for HttpServlet. This should ensure that this
* advice is always called after Servlet3Instrumentation which is instrumenting the public method. * advice is always called after Servlet3Instrumentation which is instrumenting the public
* method.
*/ */
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
@ -69,7 +80,8 @@ public final class HttpServletInstrumentation extends Instrumenter.Default {
.and(takesArgument(0, named("javax.servlet.http.HttpServletRequest"))) .and(takesArgument(0, named("javax.servlet.http.HttpServletRequest")))
.and(takesArgument(1, named("javax.servlet.http.HttpServletResponse"))) .and(takesArgument(1, named("javax.servlet.http.HttpServletResponse")))
.and(isProtected().or(isPublic())), .and(isProtected().or(isPublic())),
getClass().getName() + "$HttpServletAdvice"); HttpServletInstrumentationModule.class.getName() + "$HttpServletAdvice");
}
} }
public static class HttpServletAdvice { public static class HttpServletAdvice {

View File

@ -9,6 +9,7 @@ import static io.opentelemetry.javaagent.instrumentation.servlet.http.HttpServle
import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface;
import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
@ -18,8 +19,10 @@ import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap;
import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap.Depth; import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap.Depth;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.List;
import java.util.Map; import java.util.Map;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
@ -27,12 +30,25 @@ import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class) @AutoService(InstrumentationModule.class)
public final class HttpServletResponseInstrumentation extends Instrumenter.Default { public final class HttpServletResponseInstrumentationModule extends InstrumentationModule {
public HttpServletResponseInstrumentation() { public HttpServletResponseInstrumentationModule() {
super("servlet", "servlet-response"); super("servlet", "servlet-response");
} }
@Override
public String[] helperClassNames() {
return new String[] {
packageName + ".HttpServletResponseTracer",
};
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new HttpServletResponseInstrumentation());
}
private static final class HttpServletResponseInstrumentation implements TypeInstrumentation {
@Override @Override
public ElementMatcher<ClassLoader> classLoaderMatcher() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
// Optimization for expensive typeMatcher. // Optimization for expensive typeMatcher.
@ -44,17 +60,11 @@ public final class HttpServletResponseInstrumentation extends Instrumenter.Defau
return implementsInterface(named("javax.servlet.http.HttpServletResponse")); return implementsInterface(named("javax.servlet.http.HttpServletResponse"));
} }
@Override
public String[] helperClassNames() {
return new String[] {
packageName + ".HttpServletResponseTracer",
};
}
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap(namedOneOf("sendError", "sendRedirect"), SendAdvice.class.getName()); return singletonMap(namedOneOf("sendError", "sendRedirect"), SendAdvice.class.getName());
} }
}
public static class SendAdvice { public static class SendAdvice {

View File

@ -5,6 +5,7 @@
package io.opentelemetry.javaagent.instrumentation.sparkjava; package io.opentelemetry.javaagent.instrumentation.sparkjava;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
@ -12,11 +13,11 @@ import static net.bytebuddy.matcher.ElementMatchers.returns;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.List;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -24,23 +25,22 @@ import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
import spark.routematch.RouteMatch; import spark.routematch.RouteMatch;
@AutoService(Instrumenter.class) @AutoService(InstrumentationModule.class)
public class RoutesInstrumentation extends Instrumenter.Default { public class SparkInstrumentationModule extends InstrumentationModule {
public RoutesInstrumentation() { public SparkInstrumentationModule() {
super("sparkjava", "sparkjava-2.4"); super("sparkjava", "sparkjava-2.4");
} }
@Override @Override
public ElementMatcher<TypeDescription> typeMatcher() { public List<TypeInstrumentation> typeInstrumentations() {
return named("spark.route.Routes"); return singletonList(new RoutesInstrumentation());
} }
private static final class RoutesInstrumentation implements TypeInstrumentation {
@Override @Override
public String[] helperClassNames() { public ElementMatcher<TypeDescription> typeMatcher() {
return new String[] { return named("spark.route.Routes");
RoutesInstrumentation.class.getName() + "$TracerHolder",
};
} }
@Override @Override
@ -50,15 +50,7 @@ public class RoutesInstrumentation extends Instrumenter.Default {
.and(takesArgument(0, named("spark.route.HttpMethod"))) .and(takesArgument(0, named("spark.route.HttpMethod")))
.and(returns(named("spark.routematch.RouteMatch"))) .and(returns(named("spark.routematch.RouteMatch")))
.and(isPublic()), .and(isPublic()),
RoutesInstrumentation.class.getName() + "$RoutesAdvice"); SparkInstrumentationModule.class.getName() + "$RoutesAdvice");
}
public static class TracerHolder {
private static final Tracer TRACER =
OpenTelemetry.getGlobalTracer("io.opentelemetry.auto.sparkjava-2.3");
public static Tracer tracer() {
return TRACER;
} }
} }

View File

@ -6,6 +6,7 @@
package io.opentelemetry.javaagent.instrumentation.spring.data; package io.opentelemetry.javaagent.instrumentation.spring.data;
import static io.opentelemetry.javaagent.instrumentation.spring.data.SpringDataTracer.tracer; import static io.opentelemetry.javaagent.instrumentation.spring.data.SpringDataTracer.tracer;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isConstructor; import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
@ -13,8 +14,10 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Scope; import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.List;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -28,18 +31,13 @@ import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.repository.core.support.RepositoryFactorySupport; import org.springframework.data.repository.core.support.RepositoryFactorySupport;
import org.springframework.data.repository.core.support.RepositoryProxyPostProcessor; import org.springframework.data.repository.core.support.RepositoryProxyPostProcessor;
@AutoService(Instrumenter.class) @AutoService(InstrumentationModule.class)
public final class SpringRepositoryInstrumentation extends Instrumenter.Default { public final class SpringDataInstrumentationModule extends InstrumentationModule {
public SpringRepositoryInstrumentation() { public SpringDataInstrumentationModule() {
super("spring-data"); super("spring-data");
} }
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return named("org.springframework.data.repository.core.support.RepositoryFactorySupport");
}
@Override @Override
public String[] helperClassNames() { public String[] helperClassNames() {
return new String[] { return new String[] {
@ -49,11 +47,24 @@ public final class SpringRepositoryInstrumentation extends Instrumenter.Default
}; };
} }
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new RepositoryFactorySupportInstrumentation());
}
private static final class RepositoryFactorySupportInstrumentation
implements TypeInstrumentation {
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return named("org.springframework.data.repository.core.support.RepositoryFactorySupport");
}
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap( return singletonMap(
isConstructor(), isConstructor(),
SpringRepositoryInstrumentation.class.getName() + "$RepositoryFactorySupportAdvice"); SpringDataInstrumentationModule.class.getName() + "$RepositoryFactorySupportAdvice");
}
} }
public static class RepositoryFactorySupportAdvice { public static class RepositoryFactorySupportAdvice {

View File

@ -5,31 +5,29 @@
package io.opentelemetry.javaagent.instrumentation.spring.scheduling; package io.opentelemetry.javaagent.instrumentation.spring.scheduling;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isConstructor; import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.List;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class) @AutoService(InstrumentationModule.class)
public final class SpringSchedulingInstrumentation extends Instrumenter.Default { public final class SpringSchedulingInstrumentationModule extends InstrumentationModule {
public SpringSchedulingInstrumentation() { public SpringSchedulingInstrumentationModule() {
super("spring-scheduling"); super("spring-scheduling");
} }
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return named("org.springframework.scheduling.config.Task");
}
@Override @Override
public String[] helperClassNames() { public String[] helperClassNames() {
return new String[] { return new String[] {
@ -37,11 +35,23 @@ public final class SpringSchedulingInstrumentation extends Instrumenter.Default
}; };
} }
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new TaskInstrumentation());
}
private static final class TaskInstrumentation implements TypeInstrumentation {
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return named("org.springframework.scheduling.config.Task");
}
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap( return singletonMap(
isConstructor().and(takesArgument(0, Runnable.class)), isConstructor().and(takesArgument(0, Runnable.class)),
SpringSchedulingInstrumentation.class.getName() + "$SpringSchedulingAdvice"); SpringSchedulingInstrumentationModule.class.getName() + "$SpringSchedulingAdvice");
}
} }
public static class SpringSchedulingAdvice { public static class SpringSchedulingAdvice {

View File

@ -7,31 +7,28 @@ package io.opentelemetry.javaagent.instrumentation.spring.webflux.client;
import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.List;
import java.util.Map; import java.util.Map;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class) @AutoService(InstrumentationModule.class)
public class WebClientFilterInstrumentation extends Instrumenter.Default { public class WebfluxClientInstrumentationModule extends InstrumentationModule {
public WebClientFilterInstrumentation() { public WebfluxClientInstrumentationModule() {
super("spring-webflux", "spring-webflux-client"); super("spring-webflux", "spring-webflux-client");
} }
@Override
public ElementMatcher<ClassLoader> classLoaderMatcher() {
// Optimization for expensive typeMatcher.
return hasClassesNamed("org.springframework.web.reactive.function.client.WebClient");
}
@Override @Override
public String[] helperClassNames() { public String[] helperClassNames() {
return new String[] { return new String[] {
@ -43,6 +40,18 @@ public class WebClientFilterInstrumentation extends Instrumenter.Default {
}; };
} }
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new WebClientBuilderInstrumentation());
}
private static final class WebClientBuilderInstrumentation implements TypeInstrumentation {
@Override
public ElementMatcher<ClassLoader> classLoaderMatcher() {
// Optimization for expensive typeMatcher.
return hasClassesNamed("org.springframework.web.reactive.function.client.WebClient");
}
@Override @Override
public ElementMatcher<? super TypeDescription> typeMatcher() { public ElementMatcher<? super TypeDescription> typeMatcher() {
return implementsInterface( return implementsInterface(
@ -52,6 +61,7 @@ public class WebClientFilterInstrumentation extends Instrumenter.Default {
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap( return singletonMap(
isMethod().and(isPublic()).and(named("build")), packageName + ".WebClientFilterAdvice"); isMethod().and(isPublic()).and(named("build")), WebClientFilterAdvice.class.getName());
}
} }
} }

View File

@ -1,25 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.spring.webflux.server;
import io.opentelemetry.javaagent.tooling.Instrumenter;
public abstract class AbstractWebfluxInstrumentation extends Instrumenter.Default {
public AbstractWebfluxInstrumentation(String... additionalNames) {
super("spring-webflux", additionalNames);
}
@Override
public String[] helperClassNames() {
return new String[] {
packageName + ".SpringWebfluxHttpServerTracer",
packageName + ".AdviceUtils",
packageName + ".AdviceUtils$SpanFinishingSubscriber",
packageName + ".RouteOnSuccessOrError"
};
}
}

View File

@ -12,15 +12,13 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments; import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import java.util.Map; import java.util.Map;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class) final class DispatcherHandlerInstrumentation implements TypeInstrumentation {
public final class DispatcherHandlerInstrumentation extends AbstractWebfluxInstrumentation {
@Override @Override
public ElementMatcher<TypeDescription> typeMatcher() { public ElementMatcher<TypeDescription> typeMatcher() {
@ -35,7 +33,6 @@ public final class DispatcherHandlerInstrumentation extends AbstractWebfluxInstr
.and(named("handle")) .and(named("handle"))
.and(takesArgument(0, named("org.springframework.web.server.ServerWebExchange"))) .and(takesArgument(0, named("org.springframework.web.server.ServerWebExchange")))
.and(takesArguments(1)), .and(takesArguments(1)),
// Cannot reference class directly here because it would lead to class load failure on Java7 DispatcherHandlerAdvice.class.getName());
packageName + ".DispatcherHandlerAdvice");
} }
} }

View File

@ -16,15 +16,13 @@ import static net.bytebuddy.matcher.ElementMatchers.not;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments; import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import java.util.Map; import java.util.Map;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class) final class HandlerAdapterInstrumentation implements TypeInstrumentation {
public final class HandlerAdapterInstrumentation extends AbstractWebfluxInstrumentation {
@Override @Override
public ElementMatcher<ClassLoader> classLoaderMatcher() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
@ -47,7 +45,6 @@ public final class HandlerAdapterInstrumentation extends AbstractWebfluxInstrume
.and(takesArgument(0, named("org.springframework.web.server.ServerWebExchange"))) .and(takesArgument(0, named("org.springframework.web.server.ServerWebExchange")))
.and(takesArgument(1, named("java.lang.Object"))) .and(takesArgument(1, named("java.lang.Object")))
.and(takesArguments(2)), .and(takesArguments(2)),
// Cannot reference class directly here because it would lead to class load failure on Java7 HandlerAdapterAdvice.class.getName());
packageName + ".HandlerAdapterAdvice");
} }
} }

View File

@ -16,19 +16,13 @@ import static net.bytebuddy.matcher.ElementMatchers.not;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments; import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import java.util.Map; import java.util.Map;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class) final class RouterFunctionInstrumentation implements TypeInstrumentation {
public final class RouterFunctionInstrumentation extends AbstractWebfluxInstrumentation {
public RouterFunctionInstrumentation() {
super("spring-webflux-functional");
}
@Override @Override
public ElementMatcher<ClassLoader> classLoaderMatcher() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
@ -56,7 +50,6 @@ public final class RouterFunctionInstrumentation extends AbstractWebfluxInstrume
takesArgument( takesArgument(
0, named("org.springframework.web.reactive.function.server.ServerRequest"))) 0, named("org.springframework.web.reactive.function.server.ServerRequest")))
.and(takesArguments(1)), .and(takesArguments(1)),
// Cannot reference class directly here because it would lead to class load failure on Java7 RouterFunctionAdvice.class.getName());
packageName + ".RouterFunctionAdvice");
} }
} }

View File

@ -0,0 +1,39 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.spring.webflux.server;
import static java.util.Arrays.asList;
import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.List;
@AutoService(InstrumentationModule.class)
public class WebfluxServerInstrumentationModule extends InstrumentationModule {
public WebfluxServerInstrumentationModule() {
super("spring-webflux", "spring-webflux-server");
}
@Override
public String[] helperClassNames() {
return new String[] {
packageName + ".SpringWebfluxHttpServerTracer",
packageName + ".AdviceUtils",
packageName + ".AdviceUtils$SpanFinishingSubscriber",
packageName + ".RouteOnSuccessOrError"
};
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return asList(
new DispatcherHandlerInstrumentation(),
new HandlerAdapterInstrumentation(),
new RouterFunctionInstrumentation());
}
}

View File

@ -6,6 +6,7 @@
package io.opentelemetry.javaagent.instrumentation.spymemcached; package io.opentelemetry.javaagent.instrumentation.spymemcached;
import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf;
import static java.util.Collections.singletonList;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
@ -14,8 +15,10 @@ import static net.bytebuddy.matcher.ElementMatchers.returns;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -26,20 +29,13 @@ import net.spy.memcached.internal.BulkFuture;
import net.spy.memcached.internal.GetFuture; import net.spy.memcached.internal.GetFuture;
import net.spy.memcached.internal.OperationFuture; import net.spy.memcached.internal.OperationFuture;
@AutoService(Instrumenter.class) @AutoService(InstrumentationModule.class)
public final class MemcachedClientInstrumentation extends Instrumenter.Default { public final class SpymemcachedInstrumentationModule extends InstrumentationModule {
private static final String MEMCACHED_PACKAGE = "net.spy.memcached"; public SpymemcachedInstrumentationModule() {
public MemcachedClientInstrumentation() {
super("spymemcached"); super("spymemcached");
} }
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return named(MEMCACHED_PACKAGE + ".MemcachedClient");
}
@Override @Override
public String[] helperClassNames() { public String[] helperClassNames() {
return new String[] { return new String[] {
@ -52,30 +48,42 @@ public final class MemcachedClientInstrumentation extends Instrumenter.Default {
}; };
} }
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new MemcachedClientInstrumentation());
}
private static final class MemcachedClientInstrumentation implements TypeInstrumentation {
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return named("net.spy.memcached.MemcachedClient");
}
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
Map<ElementMatcher<? super MethodDescription>, String> transformers = new HashMap<>(); Map<ElementMatcher<? super MethodDescription>, String> transformers = new HashMap<>();
transformers.put( transformers.put(
isMethod() isMethod()
.and(isPublic()) .and(isPublic())
.and(returns(named(MEMCACHED_PACKAGE + ".internal.OperationFuture"))) .and(returns(named("net.spy.memcached.internal.OperationFuture")))
/* /*
Flush seems to have a bug when listeners may not be always called. Flush seems to have a bug when listeners may not be always called.
Also tracing flush is probably of a very limited value. Also tracing flush is probably of a very limited value.
*/ */
.and(not(named("flush"))), .and(not(named("flush"))),
MemcachedClientInstrumentation.class.getName() + "$AsyncOperationAdvice"); SpymemcachedInstrumentationModule.class.getName() + "$AsyncOperationAdvice");
transformers.put( transformers.put(
isMethod().and(isPublic()).and(returns(named(MEMCACHED_PACKAGE + ".internal.GetFuture"))), isMethod().and(isPublic()).and(returns(named("net.spy.memcached.internal.GetFuture"))),
MemcachedClientInstrumentation.class.getName() + "$AsyncGetAdvice"); SpymemcachedInstrumentationModule.class.getName() + "$AsyncGetAdvice");
transformers.put( transformers.put(
isMethod().and(isPublic()).and(returns(named(MEMCACHED_PACKAGE + ".internal.BulkFuture"))), isMethod().and(isPublic()).and(returns(named("net.spy.memcached.internal.BulkFuture"))),
MemcachedClientInstrumentation.class.getName() + "$AsyncBulkAdvice"); SpymemcachedInstrumentationModule.class.getName() + "$AsyncBulkAdvice");
transformers.put( transformers.put(
isMethod().and(isPublic()).and(namedOneOf("incr", "decr")), isMethod().and(isPublic()).and(namedOneOf("incr", "decr")),
MemcachedClientInstrumentation.class.getName() + "$SyncOperationAdvice"); SpymemcachedInstrumentationModule.class.getName() + "$SyncOperationAdvice");
return transformers; return transformers;
} }
}
public static class AsyncOperationAdvice { public static class AsyncOperationAdvice {
@ -89,7 +97,7 @@ public final class MemcachedClientInstrumentation extends Instrumenter.Default {
@Advice.Enter int callDepth, @Advice.Enter int callDepth,
@Advice.This MemcachedClient client, @Advice.This MemcachedClient client,
@Advice.Origin("#m") String methodName, @Advice.Origin("#m") String methodName,
@Advice.Return OperationFuture future) { @Advice.Return OperationFuture<?> future) {
if (callDepth > 0) { if (callDepth > 0) {
return; return;
} }
@ -115,7 +123,7 @@ public final class MemcachedClientInstrumentation extends Instrumenter.Default {
@Advice.Enter int callDepth, @Advice.Enter int callDepth,
@Advice.This MemcachedClient client, @Advice.This MemcachedClient client,
@Advice.Origin("#m") String methodName, @Advice.Origin("#m") String methodName,
@Advice.Return GetFuture future) { @Advice.Return GetFuture<?> future) {
if (callDepth > 0) { if (callDepth > 0) {
return; return;
} }
@ -141,7 +149,7 @@ public final class MemcachedClientInstrumentation extends Instrumenter.Default {
@Advice.Enter int callDepth, @Advice.Enter int callDepth,
@Advice.This MemcachedClient client, @Advice.This MemcachedClient client,
@Advice.Origin("#m") String methodName, @Advice.Origin("#m") String methodName,
@Advice.Return BulkFuture future) { @Advice.Return BulkFuture<?> future) {
if (callDepth > 0) { if (callDepth > 0) {
return; return;
} }

View File

@ -19,7 +19,6 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.not; import static net.bytebuddy.matcher.ElementMatchers.not;
import static net.bytebuddy.matcher.ElementMatchers.returns; import static net.bytebuddy.matcher.ElementMatchers.returns;
import com.google.auto.service.AutoService;
import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
@ -27,19 +26,14 @@ import com.twilio.Twilio;
import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Span;
import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap;
import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
/** Instrument the Twilio SDK to identify calls as a seperate service. */ /** Instrument the Twilio SDK to identify calls as a separate service. */
@AutoService(Instrumenter.class) final class TwilioAsyncInstrumentation implements TypeInstrumentation {
public class TwilioAsyncInstrumentation extends Instrumenter.Default {
public TwilioAsyncInstrumentation() {
super("twilio-sdk");
}
@Override @Override
public ElementMatcher<ClassLoader> classLoaderMatcher() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
@ -59,15 +53,6 @@ public class TwilioAsyncInstrumentation extends Instrumenter.Default {
"com.twilio.base.Updater")); "com.twilio.base.Updater"));
} }
/** Return the helper classes which will be available for use in instrumentation. */
@Override
public String[] helperClassNames() {
return new String[] {
packageName + ".TwilioClientDecorator",
packageName + ".TwilioAsyncInstrumentation$SpanFinishingCallback",
};
}
/** Return bytebuddy transformers for instrumenting the Twilio SDK. */ /** Return bytebuddy transformers for instrumenting the Twilio SDK. */
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
@ -122,7 +107,7 @@ public class TwilioAsyncInstrumentation extends Instrumenter.Default {
public static void methodExit( public static void methodExit(
@Advice.Enter SpanWithScope spanWithScope, @Advice.Enter SpanWithScope spanWithScope,
@Advice.Thrown Throwable throwable, @Advice.Thrown Throwable throwable,
@Advice.Return ListenableFuture response) { @Advice.Return ListenableFuture<?> response) {
if (spanWithScope == null) { if (spanWithScope == null) {
return; return;
} }
@ -142,7 +127,7 @@ public class TwilioAsyncInstrumentation extends Instrumenter.Default {
// We're calling an async operation, we still need to finish the span when it's // We're calling an async operation, we still need to finish the span when it's
// complete and report the results; set an appropriate callback // complete and report the results; set an appropriate callback
Futures.addCallback( Futures.addCallback(
response, new SpanFinishingCallback(span), Twilio.getExecutorService()); response, new SpanFinishingCallback<>(span), Twilio.getExecutorService());
} }
} finally { } finally {
spanWithScope.closeScope(); spanWithScope.closeScope();
@ -155,7 +140,7 @@ public class TwilioAsyncInstrumentation extends Instrumenter.Default {
* FutureCallback, which automatically finishes the span and annotates with any appropriate * FutureCallback, which automatically finishes the span and annotates with any appropriate
* metadata on a potential failure. * metadata on a potential failure.
*/ */
public static class SpanFinishingCallback implements FutureCallback { public static class SpanFinishingCallback<T> implements FutureCallback<T> {
/** Span that we should finish and annotate when the future is complete. */ /** Span that we should finish and annotate when the future is complete. */
private final Span span; private final Span span;

View File

@ -0,0 +1,33 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.twilio;
import static java.util.Arrays.asList;
import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.List;
@AutoService(InstrumentationModule.class)
public class TwilioInstrumentationModule extends InstrumentationModule {
public TwilioInstrumentationModule() {
super("twilio-sdk");
}
@Override
public String[] helperClassNames() {
return new String[] {
packageName + ".TwilioClientDecorator",
packageName + ".TwilioAsyncInstrumentation$SpanFinishingCallback",
};
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return asList(new TwilioAsyncInstrumentation(), new TwilioSyncInstrumentation());
}
}

View File

@ -17,24 +17,18 @@ import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.not; import static net.bytebuddy.matcher.ElementMatchers.not;
import com.google.auto.service.AutoService;
import com.twilio.Twilio; import com.twilio.Twilio;
import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Span;
import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap;
import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
/** Instrument the Twilio SDK to identify calls as a seperate service. */ /** Instrument the Twilio SDK to identify calls as a separate service. */
@AutoService(Instrumenter.class) final class TwilioSyncInstrumentation implements TypeInstrumentation {
public class TwilioSyncInstrumentation extends Instrumenter.Default {
public TwilioSyncInstrumentation() {
super("twilio-sdk");
}
@Override @Override
public ElementMatcher<ClassLoader> classLoaderMatcher() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
@ -56,14 +50,6 @@ public class TwilioSyncInstrumentation extends Instrumenter.Default {
"com.twilio.base.Updater")); "com.twilio.base.Updater"));
} }
/** Return the helper classes which will be available for use in instrumentation. */
@Override
public String[] helperClassNames() {
return new String[] {
packageName + ".TwilioClientDecorator",
};
}
/** Return bytebuddy transformers for instrumenting the Twilio SDK. */ /** Return bytebuddy transformers for instrumenting the Twilio SDK. */
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {

View File

@ -7,6 +7,7 @@ package io.opentelemetry.javaagent.instrumentation.vertx;
import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.safeHasSuperType; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.safeHasSuperType;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isInterface; import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
@ -15,22 +16,37 @@ import static net.bytebuddy.matcher.ElementMatchers.not;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import io.vertx.core.Handler; import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext; import io.vertx.ext.web.RoutingContext;
import java.util.List;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class) @AutoService(InstrumentationModule.class)
public final class RouteInstrumentation extends Instrumenter.Default { public final class VertxInstrumentationModule extends InstrumentationModule {
public RouteInstrumentation() { public VertxInstrumentationModule() {
super("vertx"); super("vertx");
} }
@Override
public String[] helperClassNames() {
return new String[] {
packageName + ".RoutingContextHandlerWrapper", packageName + ".VertxTracer",
};
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new RouteInstrumentation());
}
private static final class RouteInstrumentation implements TypeInstrumentation {
@Override @Override
public ElementMatcher<ClassLoader> classLoaderMatcher() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
return hasClassesNamed("io.vertx.ext.web.Route"); return hasClassesNamed("io.vertx.ext.web.Route");
@ -41,18 +57,12 @@ public final class RouteInstrumentation extends Instrumenter.Default {
return not(isInterface()).and(safeHasSuperType(named("io.vertx.ext.web.Route"))); return not(isInterface()).and(safeHasSuperType(named("io.vertx.ext.web.Route")));
} }
@Override
public String[] helperClassNames() {
return new String[] {
packageName + ".RoutingContextHandlerWrapper", packageName + ".VertxTracer",
};
}
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap( return singletonMap(
isMethod().and(named("handler")).and(takesArgument(0, named("io.vertx.core.Handler"))), isMethod().and(named("handler")).and(takesArgument(0, named("io.vertx.core.Handler"))),
RouteInstrumentation.class.getName() + "$RouteAdvice"); VertxInstrumentationModule.class.getName() + "$RouteAdvice");
}
} }
public static class RouteAdvice { public static class RouteAdvice {

View File

@ -2,9 +2,9 @@
* The majority of monitoring needs of Vert.x application is covered by generic instrumentations. * The majority of monitoring needs of Vert.x application is covered by generic instrumentations.
* Such as those of netty or JDBC. * Such as those of netty or JDBC.
* *
* <p>{@link io.opentelemetry.javaagent.instrumentation.vertx.RouteInstrumentation} wraps all Vert.x * <p>{@link io.opentelemetry.javaagent.instrumentation.vertx.VertxInstrumentationModule} wraps all
* route handlers in order to update the name of the currently active SERVER span with the name of * Vert.x route handlers in order to update the name of the currently active SERVER span with the
* route. This is, arguably, a much more user-friendly name that defaults provided by HTTP server * name of route. This is, arguably, a much more user-friendly name that defaults provided by HTTP
* instrumentations. * server instrumentations.
*/ */
package io.opentelemetry.javaagent.instrumentation.vertx; package io.opentelemetry.javaagent.instrumentation.vertx;

View File

@ -6,16 +6,19 @@
package io.opentelemetry.javaagent.instrumentation.vertx.reactive; package io.opentelemetry.javaagent.instrumentation.vertx.reactive;
import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed;
import static java.util.Collections.singletonList;
import static net.bytebuddy.matcher.ElementMatchers.isConstructor; import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import io.vertx.core.AsyncResult; import io.vertx.core.AsyncResult;
import io.vertx.core.Handler; import io.vertx.core.Handler;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Consumer; import java.util.function.Consumer;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
@ -24,13 +27,26 @@ import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
/** This instrumentation allows span context propagation across Vert.x reactive executions. */ /** This instrumentation allows span context propagation across Vert.x reactive executions. */
@AutoService(Instrumenter.class) @AutoService(InstrumentationModule.class)
public class VertxRxInstrumentation extends Instrumenter.Default { public class VertxRxInstrumentationModule extends InstrumentationModule {
public VertxRxInstrumentation() { public VertxRxInstrumentationModule() {
super("vertx"); super("vertx");
} }
@Override
public String[] helperClassNames() {
return new String[] {
packageName + ".AsyncResultConsumerWrapper", packageName + ".AsyncResultHandlerWrapper"
};
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new AsyncResultSingleInstrumentation());
}
private static final class AsyncResultSingleInstrumentation implements TypeInstrumentation {
@Override @Override
public ElementMatcher<ClassLoader> classLoaderMatcher() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
// Different versions of Vert.x has this class in different packages // Different versions of Vert.x has this class in different packages
@ -44,24 +60,18 @@ public class VertxRxInstrumentation extends Instrumenter.Default {
.or(named("io.vertx.reactivex.impl.AsyncResultSingle")); .or(named("io.vertx.reactivex.impl.AsyncResultSingle"));
} }
@Override
public String[] helperClassNames() {
return new String[] {
packageName + ".AsyncResultConsumerWrapper", packageName + ".AsyncResultHandlerWrapper"
};
}
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
Map<ElementMatcher<? super MethodDescription>, String> result = new HashMap<>(); Map<ElementMatcher<? super MethodDescription>, String> result = new HashMap<>();
result.put( result.put(
isConstructor().and(takesArgument(0, named("io.vertx.core.Handler"))), isConstructor().and(takesArgument(0, named("io.vertx.core.Handler"))),
this.getClass().getName() + "$AsyncResultSingleHandlerAdvice"); VertxRxInstrumentationModule.class.getName() + "$AsyncResultSingleHandlerAdvice");
result.put( result.put(
isConstructor().and(takesArgument(0, named("java.util.function.Consumer"))), isConstructor().and(takesArgument(0, named("java.util.function.Consumer"))),
this.getClass().getName() + "$AsyncResultSingleConsumerAdvice"); VertxRxInstrumentationModule.class.getName() + "$AsyncResultSingleConsumerAdvice");
return result; return result;
} }
}
public static class AsyncResultSingleHandlerAdvice { public static class AsyncResultSingleHandlerAdvice {

View File

@ -2,8 +2,8 @@
* The majority of monitoring needs of Vert.x application is covered by generic instrumentations. * The majority of monitoring needs of Vert.x application is covered by generic instrumentations.
* Such as those of netty or JDBC. * Such as those of netty or JDBC.
* *
* <p>{@link io.opentelemetry.javaagent.instrumentation.vertx.reactive.VertxRxInstrumentation} wraps * <p>{@link io.opentelemetry.javaagent.instrumentation.vertx.reactive.VertxRxInstrumentationModule}
* {code AsyncResultSingle} classes from Vert.x RxJava library to ensure proper span context * wraps {code AsyncResultSingle} classes from Vert.x RxJava library to ensure proper span context
* propagation in reactive Vert.x applications. * propagation in reactive Vert.x applications.
*/ */
package io.opentelemetry.javaagent.instrumentation.vertx.reactive; package io.opentelemetry.javaagent.instrumentation.vertx.reactive;