diff --git a/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/amqp/RabbitChannelInstrumentation.java b/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/amqp/RabbitChannelInstrumentation.java index fe99807c81..36cfb2fabc 100644 --- a/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/amqp/RabbitChannelInstrumentation.java +++ b/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/amqp/RabbitChannelInstrumentation.java @@ -22,7 +22,6 @@ import static net.bytebuddy.matcher.ElementMatchers.not; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArguments; -import com.google.auto.service.AutoService; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Consumer; @@ -34,7 +33,7 @@ import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; 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.util.HashMap; import java.util.LinkedHashMap; @@ -44,12 +43,7 @@ import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; -@AutoService(Instrumenter.class) -public class RabbitChannelInstrumentation extends Instrumenter.Default { - - public RabbitChannelInstrumentation() { - super("amqp", "rabbitmq"); - } +final class RabbitChannelInstrumentation implements TypeInstrumentation { @Override public ElementMatcher classLoaderMatcher() { @@ -62,17 +56,6 @@ public class RabbitChannelInstrumentation extends Instrumenter.Default { 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 public Map, String> transformers() { // We want the advice applied in a specific order, so use an ordered map. diff --git a/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/amqp/RabbitCommandInstrumentation.java b/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/amqp/RabbitCommandInstrumentation.java index 7984f920ce..b524966c6c 100644 --- a/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/amqp/RabbitCommandInstrumentation.java +++ b/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/amqp/RabbitCommandInstrumentation.java @@ -13,22 +13,16 @@ import static java.util.Collections.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.isConstructor; import static net.bytebuddy.matcher.ElementMatchers.named; -import com.google.auto.service.AutoService; import com.rabbitmq.client.Command; import io.opentelemetry.api.trace.Span; -import io.opentelemetry.javaagent.tooling.Instrumenter; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.Map; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; -@AutoService(Instrumenter.class) -public class RabbitCommandInstrumentation extends Instrumenter.Default { - - public RabbitCommandInstrumentation() { - super("amqp", "rabbitmq"); - } +final class RabbitCommandInstrumentation implements TypeInstrumentation { @Override public ElementMatcher classLoaderMatcher() { @@ -41,17 +35,6 @@ public class RabbitCommandInstrumentation extends Instrumenter.Default { 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 public Map, String> transformers() { return singletonMap( @@ -72,14 +55,5 @@ public class RabbitCommandInstrumentation extends Instrumenter.Default { 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); - } } } diff --git a/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/amqp/RabbitMqInstrumentationModule.java b/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/amqp/RabbitMqInstrumentationModule.java new file mode 100644 index 0000000000..85a378e814 --- /dev/null +++ b/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/amqp/RabbitMqInstrumentationModule.java @@ -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 typeInstrumentations() { + return asList(new RabbitChannelInstrumentation(), new RabbitCommandInstrumentation()); + } +} diff --git a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ContinuationInstrumentation.java b/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ContinuationInstrumentation.java index 973737d943..294ce5048c 100644 --- a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ContinuationInstrumentation.java +++ b/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ContinuationInstrumentation.java @@ -12,22 +12,15 @@ import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.Instrumenter; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.Map; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; import ratpack.func.Block; -import ratpack.path.PathBinding; -@AutoService(Instrumenter.class) -public final class ContinuationInstrumentation extends Instrumenter.Default { - - public ContinuationInstrumentation() { - super("ratpack"); - } +final class ContinuationInstrumentation implements TypeInstrumentation { @Override public ElementMatcher classLoaderMatcher() { @@ -41,11 +34,6 @@ public final class ContinuationInstrumentation extends Instrumenter.Default { .and(implementsInterface(named("ratpack.exec.internal.Continuation"))); } - @Override - public String[] helperClassNames() { - return new String[] {packageName + ".BlockWrapper"}; - } - @Override public Map, String> transformers() { 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) { 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(); - } } } diff --git a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/DefaultExecutionInstrumentation.java b/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/DefaultExecutionInstrumentation.java index 6a66d4a08a..543bcef2c1 100644 --- a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/DefaultExecutionInstrumentation.java +++ b/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/DefaultExecutionInstrumentation.java @@ -10,8 +10,7 @@ import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.Instrumenter; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.Map; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; @@ -19,25 +18,14 @@ import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; import ratpack.exec.internal.Continuation; import ratpack.func.Action; -import ratpack.path.PathBinding; -@AutoService(Instrumenter.class) -public final class DefaultExecutionInstrumentation extends Instrumenter.Default { - - public DefaultExecutionInstrumentation() { - super("ratpack"); - } +final class DefaultExecutionInstrumentation implements TypeInstrumentation { @Override public ElementMatcher typeMatcher() { return named("ratpack.exec.internal.DefaultExecution"); } - @Override - public String[] helperClassNames() { - return new String[] {packageName + ".ActionWrapper"}; - } - @Override public Map, String> transformers() { return singletonMap( @@ -56,10 +44,5 @@ public final class DefaultExecutionInstrumentation extends Instrumenter.Default onError = ActionWrapper.wrapIfNeeded(onError); 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(); - } } } diff --git a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/RatpackInstrumentationModule.java b/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/RatpackInstrumentationModule.java new file mode 100644 index 0000000000..bac13c37dc --- /dev/null +++ b/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/RatpackInstrumentationModule.java @@ -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 typeInstrumentations() { + return asList( + new ContinuationInstrumentation(), + new DefaultExecutionInstrumentation(), + new ServerErrorHandlerInstrumentation(), + new ServerRegistryInstrumentation()); + } +} diff --git a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ServerErrorHandlerInstrumentation.java b/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ServerErrorHandlerInstrumentation.java index a545f39620..cb392db48a 100644 --- a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ServerErrorHandlerInstrumentation.java +++ b/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ServerErrorHandlerInstrumentation.java @@ -13,19 +13,13 @@ import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.not; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.Instrumenter; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; 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 class ServerErrorHandlerInstrumentation extends Instrumenter.Default { - - public ServerErrorHandlerInstrumentation() { - super("ratpack"); - } +final class ServerErrorHandlerInstrumentation implements TypeInstrumentation { @Override public ElementMatcher classLoaderMatcher() { @@ -38,19 +32,12 @@ public class ServerErrorHandlerInstrumentation extends Instrumenter.Default { return not(isAbstract()).and(implementsInterface(named("ratpack.error.ServerErrorHandler"))); } - @Override - public String[] helperClassNames() { - return new String[] { - packageName + ".RatpackTracer", - }; - } - @Override public Map, String> transformers() { return singletonMap( named("error") .and(takesArgument(0, named("ratpack.handling.Context"))) .and(takesArgument(1, Throwable.class)), - packageName + ".ErrorHandlerAdvice"); + ErrorHandlerAdvice.class.getName()); } } diff --git a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ServerRegistryInstrumentation.java b/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ServerRegistryInstrumentation.java index 9c7e517b02..a791e07fa7 100644 --- a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ServerRegistryInstrumentation.java +++ b/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ServerRegistryInstrumentation.java @@ -10,36 +10,23 @@ import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isStatic; import static net.bytebuddy.matcher.ElementMatchers.named; -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.Instrumenter; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; 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 class ServerRegistryInstrumentation extends Instrumenter.Default { - - public ServerRegistryInstrumentation() { - super("ratpack"); - } +final class ServerRegistryInstrumentation implements TypeInstrumentation { @Override public ElementMatcher typeMatcher() { return named("ratpack.server.internal.ServerRegistry"); } - @Override - public String[] helperClassNames() { - return new String[] { - packageName + ".RatpackTracer", packageName + ".TracingHandler", - }; - } - @Override public Map, String> transformers() { return singletonMap( isMethod().and(isStatic()).and(named("buildBaseRegistry")), - packageName + ".ServerRegistryAdvice"); + ServerRegistryAdvice.class.getName()); } } diff --git a/instrumentation/reactor-3.1/src/main/java/io/opentelemetry/javaagent/instrumentation/reactor/ReactorHooksInstrumentation.java b/instrumentation/reactor-3.1/src/main/java/io/opentelemetry/javaagent/instrumentation/reactor/ReactorHooksInstrumentation.java deleted file mode 100644 index 3c08a7b9b9..0000000000 --- a/instrumentation/reactor-3.1/src/main/java/io/opentelemetry/javaagent/instrumentation/reactor/ReactorHooksInstrumentation.java +++ /dev/null @@ -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 typeMatcher() { - return named("reactor.core.publisher.Hooks"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isTypeInitializer().or(named("resetOnEachOperator")), packageName + ".ReactorHooksAdvice"); - } -} diff --git a/instrumentation/reactor-3.1/src/main/java/io/opentelemetry/javaagent/instrumentation/reactor/ReactorInstrumentationModule.java b/instrumentation/reactor-3.1/src/main/java/io/opentelemetry/javaagent/instrumentation/reactor/ReactorInstrumentationModule.java new file mode 100644 index 0000000000..136131586a --- /dev/null +++ b/instrumentation/reactor-3.1/src/main/java/io/opentelemetry/javaagent/instrumentation/reactor/ReactorInstrumentationModule.java @@ -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 typeInstrumentations() { + return singletonList(new HooksInstrumentation()); + } + + private static final class HooksInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher typeMatcher() { + return named("reactor.core.publisher.Hooks"); + } + + @Override + public Map, String> transformers() { + return singletonMap( + isTypeInitializer().or(named("resetOnEachOperator")), ReactorHooksAdvice.class.getName()); + } + } +} diff --git a/instrumentation/rediscala-1.8/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RediscalaInstrumentation.java b/instrumentation/rediscala-1.8/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RediscalaInstrumentationModule.java similarity index 65% rename from instrumentation/rediscala-1.8/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RediscalaInstrumentation.java rename to instrumentation/rediscala-1.8/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RediscalaInstrumentationModule.java index 37375cbd30..95c4ccb785 100644 --- a/instrumentation/rediscala-1.8/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RediscalaInstrumentation.java +++ b/instrumentation/rediscala-1.8/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RediscalaInstrumentationModule.java @@ -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.bytebuddy.matcher.AgentElementMatchers.safeHasSuperType; import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; +import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.isMethod; 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 io.opentelemetry.api.trace.Span; 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 net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; @@ -31,52 +34,59 @@ import scala.concurrent.Future; import scala.runtime.AbstractFunction1; import scala.util.Try; -@AutoService(Instrumenter.class) -public final class RediscalaInstrumentation extends Instrumenter.Default { +@AutoService(InstrumentationModule.class) +public final class RediscalaInstrumentationModule extends InstrumentationModule { - public RediscalaInstrumentation() { + public RediscalaInstrumentationModule() { super("rediscala", "redis"); } - @Override - public ElementMatcher classLoaderMatcher() { - return hasClassesNamed("redis.Request"); - } - - @Override - public ElementMatcher typeMatcher() { - return safeHasSuperType( - namedOneOf( - "redis.ActorRequest", - "redis.Request", - "redis.BufferedRequest", - "redis.RoundRobinPoolRequest")); - } - @Override public String[] helperClassNames() { return new String[] { - RediscalaInstrumentation.class.getName() + "$OnCompleteHandler", + RediscalaInstrumentationModule.class.getName() + "$OnCompleteHandler", packageName + ".RediscalaClientTracer", }; } @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(isPublic()) - .and(named("send")) - .and(takesArgument(0, named("redis.RedisCommand"))) - .and(returns(named("scala.concurrent.Future"))), - RediscalaInstrumentation.class.getName() + "$RediscalaAdvice"); + public List typeInstrumentations() { + return singletonList(new RequestInstrumentation()); + } + + private static final class RequestInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher classLoaderMatcher() { + return hasClassesNamed("redis.Request"); + } + + @Override + public ElementMatcher typeMatcher() { + return safeHasSuperType( + namedOneOf( + "redis.ActorRequest", + "redis.Request", + "redis.BufferedRequest", + "redis.RoundRobinPoolRequest")); + } + + @Override + public Map, String> transformers() { + return singletonMap( + isMethod() + .and(isPublic()) + .and(named("send")) + .and(takesArgument(0, named("redis.RedisCommand"))) + .and(returns(named("scala.concurrent.Future"))), + RediscalaInstrumentationModule.class.getName() + "$RediscalaAdvice"); + } } public static class RediscalaAdvice { @Advice.OnMethodEnter(suppress = Throwable.class) public static void onEnter( - @Advice.Argument(0) RedisCommand cmd, + @Advice.Argument(0) RedisCommand cmd, @Advice.Local("otelSpan") Span span, @Advice.Local("otelScope") Scope scope) { span = tracer().startSpan(cmd, cmd); diff --git a/instrumentation/redisson-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/RedissonInstrumentation.java b/instrumentation/redisson-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/RedissonInstrumentation.java index abc141c573..7992a7a675 100644 --- a/instrumentation/redisson-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/RedissonInstrumentation.java +++ b/instrumentation/redisson-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/RedissonInstrumentation.java @@ -6,6 +6,7 @@ package io.opentelemetry.javaagent.instrumentation.redisson; import static io.opentelemetry.javaagent.instrumentation.redisson.RedissonClientTracer.tracer; +import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.isMethod; 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 io.opentelemetry.api.trace.Span; 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 net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; @@ -21,27 +24,35 @@ import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; import org.redisson.client.RedisConnection; -@AutoService(Instrumenter.class) -public final class RedissonInstrumentation extends Instrumenter.Default { +@AutoService(InstrumentationModule.class) +public final class RedissonInstrumentation extends InstrumentationModule { public RedissonInstrumentation() { super("redisson", "redis"); } - @Override - public ElementMatcher typeMatcher() { - return named("org.redisson.client.RedisConnection"); - } - @Override public String[] helperClassNames() { return new String[] {packageName + ".RedissonClientTracer"}; } @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(named("send")), RedissonInstrumentation.class.getName() + "$RedissonAdvice"); + public List typeInstrumentations() { + return singletonList(new RedisConnectionInstrumentation()); + } + + private static final class RedisConnectionInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher typeMatcher() { + return named("org.redisson.client.RedisConnection"); + } + + @Override + public Map, String> transformers() { + return singletonMap( + isMethod().and(named("send")), + RedissonInstrumentation.class.getName() + "$RedissonAdvice"); + } } public static class RedissonAdvice { diff --git a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/client/RmiClientInstrumentation.java b/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/client/RmiClientInstrumentationModule.java similarity index 65% rename from instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/client/RmiClientInstrumentation.java rename to instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/client/RmiClientInstrumentationModule.java index 2c8c4dada7..a14e26cfc0 100644 --- a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/client/RmiClientInstrumentation.java +++ b/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/client/RmiClientInstrumentationModule.java @@ -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.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; +import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.named; @@ -16,39 +17,48 @@ import com.google.auto.service.AutoService; import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Scope; 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.util.List; import java.util.Map; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; -@AutoService(Instrumenter.class) -public final class RmiClientInstrumentation extends Instrumenter.Default { +@AutoService(InstrumentationModule.class) +public final class RmiClientInstrumentationModule extends InstrumentationModule { - public RmiClientInstrumentation() { + public RmiClientInstrumentationModule() { super("rmi", "rmi-client"); } - @Override - public ElementMatcher typeMatcher() { - return extendsClass(named("sun.rmi.server.UnicastRef")); - } - @Override public String[] helperClassNames() { return new String[] {packageName + ".RmiClientTracer"}; } @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(named("invoke")) - .and(takesArgument(0, named("java.rmi.Remote"))) - .and(takesArgument(1, named("java.lang.reflect.Method"))), - getClass().getName() + "$RmiClientAdvice"); + public List typeInstrumentations() { + return singletonList(new ClientInstrumentation()); + } + + private static final class ClientInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher typeMatcher() { + return extendsClass(named("sun.rmi.server.UnicastRef")); + } + + @Override + public Map, String> transformers() { + return singletonMap( + isMethod() + .and(named("invoke")) + .and(takesArgument(0, named("java.rmi.Remote"))) + .and(takesArgument(1, named("java.lang.reflect.Method"))), + RmiClientInstrumentationModule.class.getName() + "$RmiClientAdvice"); + } } public static class RmiClientAdvice { diff --git a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/RmiContextPropagationInstrumentationModule.java b/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/RmiContextPropagationInstrumentationModule.java new file mode 100644 index 0000000000..7d835ac06b --- /dev/null +++ b/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/RmiContextPropagationInstrumentationModule.java @@ -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 typeInstrumentations() { + return asList(new RmiClientContextInstrumentation(), new RmiServerContextInstrumentation()); + } + + @Override + public Map contextStore() { + // caching if a connection can support enhanced format + return singletonMap("sun.rmi.transport.Connection", "java.lang.Boolean"); + } +} diff --git a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/client/RmiClientContextInstrumentation.java b/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/client/RmiClientContextInstrumentation.java index aebdada985..3c54164124 100644 --- a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/client/RmiClientContextInstrumentation.java +++ b/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/client/RmiClientContextInstrumentation.java @@ -12,12 +12,11 @@ import static net.bytebuddy.matcher.ElementMatchers.isConstructor; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import com.google.auto.service.AutoService; import io.opentelemetry.api.trace.Span; import io.opentelemetry.javaagent.instrumentation.api.ContextStore; import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; 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.util.Map; 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 * exception and shutdown the connection which we do not want */ -@AutoService(Instrumenter.class) -public class RmiClientContextInstrumentation extends Instrumenter.Default { - - public RmiClientContextInstrumentation() { - super("rmi", "rmi-context-propagator", "rmi-client-context-propagator"); - } +public final class RmiClientContextInstrumentation implements TypeInstrumentation { @Override public ElementMatcher typeMatcher() { return extendsClass(named("sun.rmi.transport.StreamRemoteCall")); } - @Override - public Map 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 public Map, String> transformers() { return singletonMap( diff --git a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/server/RmiServerContextInstrumentation.java b/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/server/RmiServerContextInstrumentation.java index 6ccc0c041f..b1c818adcc 100644 --- a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/server/RmiServerContextInstrumentation.java +++ b/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/server/RmiServerContextInstrumentation.java @@ -13,8 +13,7 @@ import static net.bytebuddy.matcher.ElementMatchers.isStatic; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.Instrumenter; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.Map; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; @@ -22,30 +21,13 @@ import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; import sun.rmi.transport.Target; -@AutoService(Instrumenter.class) -public class RmiServerContextInstrumentation extends Instrumenter.Default { - - public RmiServerContextInstrumentation() { - super("rmi", "rmi-context-propagator", "rmi-server-context-propagator"); - } +public final class RmiServerContextInstrumentation implements TypeInstrumentation { @Override public ElementMatcher typeMatcher() { 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 public Map, String> transformers() { return singletonMap( diff --git a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/server/RmiServerInstrumentation.java b/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/server/RmiServerInstrumentation.java index 20bc31942d..2a687428ed 100644 --- a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/server/RmiServerInstrumentation.java +++ b/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/server/RmiServerInstrumentation.java @@ -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.rmi.server.RmiServerTracer.tracer; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; +import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.isMethod; 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.Scope; 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.rmi.server.RemoteServer; +import java.util.List; import java.util.Map; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; -@AutoService(Instrumenter.class) -public final class RmiServerInstrumentation extends Instrumenter.Default { +@AutoService(InstrumentationModule.class) +public final class RmiServerInstrumentation extends InstrumentationModule { public RmiServerInstrumentation() { super("rmi", "rmi-server"); @@ -42,14 +45,22 @@ public final class RmiServerInstrumentation extends Instrumenter.Default { } @Override - public ElementMatcher typeMatcher() { - return extendsClass(named("java.rmi.server.RemoteServer")); + public List typeInstrumentations() { + return singletonList(new ServerInstrumentation()); } - @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(isPublic()).and(not(isStatic())), getClass().getName() + "$ServerAdvice"); + private static final class ServerInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher typeMatcher() { + return extendsClass(named("java.rmi.server.RemoteServer")); + } + + @Override + public Map, String> transformers() { + return singletonMap( + isMethod().and(isPublic()).and(not(isStatic())), + RmiServerInstrumentation.class.getName() + "$ServerAdvice"); + } } public static class ServerAdvice { diff --git a/instrumentation/scala-concurrent/src/main/java/io/opentelemetry/javaagent/instrumentation/scalaconcurrent/ScalaConcurrentInstrumentationModule.java b/instrumentation/scala-concurrent/src/main/java/io/opentelemetry/javaagent/instrumentation/scalaconcurrent/ScalaConcurrentInstrumentationModule.java new file mode 100644 index 0000000000..ab39664986 --- /dev/null +++ b/instrumentation/scala-concurrent/src/main/java/io/opentelemetry/javaagent/instrumentation/scalaconcurrent/ScalaConcurrentInstrumentationModule.java @@ -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 typeInstrumentations() { + return asList(new ScalaForkJoinPoolInstrumentation(), new ScalaForkJoinTaskInstrumentation()); + } + + @Override + public Map contextStore() { + Map 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); + } +} diff --git a/instrumentation/scala-concurrent/src/main/java/io/opentelemetry/javaagent/instrumentation/scalaconcurrent/ScalaForkJoinPoolInstrumentation.java b/instrumentation/scala-concurrent/src/main/java/io/opentelemetry/javaagent/instrumentation/scalaconcurrent/ScalaForkJoinPoolInstrumentation.java index a1b75355d1..d101e9ff96 100644 --- a/instrumentation/scala-concurrent/src/main/java/io/opentelemetry/javaagent/instrumentation/scalaconcurrent/ScalaForkJoinPoolInstrumentation.java +++ b/instrumentation/scala-concurrent/src/main/java/io/opentelemetry/javaagent/instrumentation/scalaconcurrent/ScalaForkJoinPoolInstrumentation.java @@ -5,18 +5,16 @@ 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.named; 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.InstrumentationContext; import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; import io.opentelemetry.javaagent.instrumentation.api.concurrent.ExecutorInstrumentationUtils; 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.Map; import net.bytebuddy.asm.Advice; @@ -25,12 +23,7 @@ import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; import scala.concurrent.forkjoin.ForkJoinTask; -@AutoService(Instrumenter.class) -public final class ScalaForkJoinPoolInstrumentation extends Instrumenter.Default { - - public ScalaForkJoinPoolInstrumentation() { - super("java_concurrent", "scala_concurrent"); - } +final class ScalaForkJoinPoolInstrumentation implements TypeInstrumentation { @Override public ElementMatcher typeMatcher() { @@ -38,11 +31,6 @@ public final class ScalaForkJoinPoolInstrumentation extends Instrumenter.Default return named("scala.concurrent.forkjoin.ForkJoinPool"); } - @Override - public Map contextStore() { - return singletonMap(ScalaForkJoinTaskInstrumentation.TASK_CLASS_NAME, State.class.getName()); - } - @Override public Map, String> transformers() { Map, String> transformers = new HashMap<>(); @@ -65,7 +53,7 @@ public final class ScalaForkJoinPoolInstrumentation extends Instrumenter.Default @Advice.OnMethodEnter(suppress = Throwable.class) public static State enterJobSubmit( - @Advice.Argument(value = 0, readOnly = false) ForkJoinTask task) { + @Advice.Argument(value = 0, readOnly = false) ForkJoinTask task) { if (ExecutorInstrumentationUtils.shouldAttachStateToTask(task)) { ContextStore contextStore = InstrumentationContext.get(ForkJoinTask.class, State.class); diff --git a/instrumentation/scala-concurrent/src/main/java/io/opentelemetry/javaagent/instrumentation/scalaconcurrent/ScalaForkJoinTaskInstrumentation.java b/instrumentation/scala-concurrent/src/main/java/io/opentelemetry/javaagent/instrumentation/scalaconcurrent/ScalaForkJoinTaskInstrumentation.java index 20bb13aa74..0eb6e89326 100644 --- a/instrumentation/scala-concurrent/src/main/java/io/opentelemetry/javaagent/instrumentation/scalaconcurrent/ScalaForkJoinTaskInstrumentation.java +++ b/instrumentation/scala-concurrent/src/main/java/io/opentelemetry/javaagent/instrumentation/scalaconcurrent/ScalaForkJoinTaskInstrumentation.java @@ -13,15 +13,12 @@ import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.not; import static net.bytebuddy.matcher.ElementMatchers.takesArguments; -import com.google.auto.service.AutoService; import io.opentelemetry.context.Scope; import io.opentelemetry.javaagent.instrumentation.api.ContextStore; import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; import io.opentelemetry.javaagent.instrumentation.api.concurrent.AdviceUtils; import io.opentelemetry.javaagent.instrumentation.api.concurrent.State; -import io.opentelemetry.javaagent.tooling.Instrumenter; -import java.util.Collections; -import java.util.HashMap; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.Map; import java.util.concurrent.Callable; import net.bytebuddy.asm.Advice; @@ -37,15 +34,10 @@ import scala.concurrent.forkjoin.ForkJoinTask; *

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. */ -@AutoService(Instrumenter.class) -public final class ScalaForkJoinTaskInstrumentation extends Instrumenter.Default { +final class ScalaForkJoinTaskInstrumentation implements TypeInstrumentation { static final String TASK_CLASS_NAME = "scala.concurrent.forkjoin.ForkJoinTask"; - public ScalaForkJoinTaskInstrumentation() { - super("java_concurrent", "scala_concurrent"); - } - @Override public ElementMatcher classLoaderMatcher() { // Optimization for expensive typeMatcher. @@ -57,15 +49,6 @@ public final class ScalaForkJoinTaskInstrumentation extends Instrumenter.Default return extendsClass(named(TASK_CLASS_NAME)); } - @Override - public Map contextStore() { - Map 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 public Map, String> transformers() { return singletonMap( @@ -82,7 +65,7 @@ public final class ScalaForkJoinTaskInstrumentation extends Instrumenter.Default * need to use that state. */ @Advice.OnMethodEnter(suppress = Throwable.class) - public static Scope enter(@Advice.This ForkJoinTask thiz) { + public static Scope enter(@Advice.This ForkJoinTask thiz) { ContextStore contextStore = InstrumentationContext.get(ForkJoinTask.class, State.class); Scope scope = AdviceUtils.startTaskScope(contextStore, thiz); diff --git a/instrumentation/servlet/README.md b/instrumentation/servlet/README.md index 585db09103..f512049cf0 100644 --- a/instrumentation/servlet/README.md +++ b/instrumentation/servlet/README.md @@ -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)`. -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. 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. -In rare cases when you need it, you can enable it using configuration property `otel.integration.servlet-service.enabled`. +For this reason `HttpServletInstrumentationModule` is disabled by default. +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. Usually unimportant, they may be sometimes of interest during troubleshooting. -They are instrumented by `FilterInstrumentation` which is also disabled by default. -You can enable it with the configuration property `otel.integration.servlet-filter.enabled`. +They are instrumented by `FilterInstrumentationModule` which is also disabled by default. +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. 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). ## 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 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 around their invocations. diff --git a/instrumentation/servlet/servlet-2.2/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v2_2/Servlet2ResponseStatusInstrumentation.java b/instrumentation/servlet/servlet-2.2/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v2_2/HttpServletResponseInstrumentation.java similarity index 75% rename from instrumentation/servlet/servlet-2.2/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v2_2/Servlet2ResponseStatusInstrumentation.java rename to instrumentation/servlet/servlet-2.2/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v2_2/HttpServletResponseInstrumentation.java index 00ccafed04..c80e1f4097 100644 --- a/instrumentation/servlet/servlet-2.2/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v2_2/Servlet2ResponseStatusInstrumentation.java +++ b/instrumentation/servlet/servlet-2.2/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v2_2/HttpServletResponseInstrumentation.java @@ -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.bytebuddy.matcher.AgentElementMatchers.safeHasSuperType; 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.not; -import com.google.auto.service.AutoService; import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Scope; 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.Map; 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 * attribute. */ -@AutoService(Instrumenter.class) -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 +final class HttpServletResponseInstrumentation implements TypeInstrumentation { @Override public ElementMatcher classLoaderMatcher() { - return not(hasClassesNamed("javax.servlet.AsyncEvent", "javax.servlet.AsyncListener")); + return hasClassesNamed("javax.servlet.http.HttpServletResponse"); } @Override @@ -55,20 +46,15 @@ public final class Servlet2ResponseStatusInstrumentation extends Instrumenter.De return safeHasSuperType(named("javax.servlet.http.HttpServletResponse")); } - @Override - public Map contextStore() { - return singletonMap("javax.servlet.ServletResponse", Integer.class.getName()); - } - @Override public Map, String> transformers() { Map, String> transformers = new HashMap<>(); transformers.put( namedOneOf("sendError", "setStatus"), - Servlet2ResponseStatusInstrumentation.class.getName() + "$Servlet2ResponseStatusAdvice"); + HttpServletResponseInstrumentation.class.getName() + "$Servlet2ResponseStatusAdvice"); transformers.put( named("sendRedirect"), - Servlet2ResponseStatusInstrumentation.class.getName() + "$Servlet2ResponseRedirectAdvice"); + HttpServletResponseInstrumentation.class.getName() + "$Servlet2ResponseRedirectAdvice"); return transformers; } diff --git a/instrumentation/servlet/servlet-2.2/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v2_2/Servlet2InstrumentationModule.java b/instrumentation/servlet/servlet-2.2/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v2_2/Servlet2InstrumentationModule.java new file mode 100644 index 0000000000..404dcf11ab --- /dev/null +++ b/instrumentation/servlet/servlet-2.2/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v2_2/Servlet2InstrumentationModule.java @@ -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 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 typeInstrumentations() { + return Arrays.asList( + new HttpServletResponseInstrumentation(), new ServletAndFilterChainInstrumentation()); + } + + @Override + public Map contextStore() { + return singletonMap("javax.servlet.ServletResponse", Integer.class.getName()); + } +} diff --git a/instrumentation/servlet/servlet-2.2/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v2_2/Servlet2Instrumentation.java b/instrumentation/servlet/servlet-2.2/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v2_2/ServletAndFilterChainInstrumentation.java similarity index 61% rename from instrumentation/servlet/servlet-2.2/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v2_2/Servlet2Instrumentation.java rename to instrumentation/servlet/servlet-2.2/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v2_2/ServletAndFilterChainInstrumentation.java index 37a1e8c72a..619682320a 100644 --- a/instrumentation/servlet/servlet-2.2/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v2_2/Servlet2Instrumentation.java +++ b/instrumentation/servlet/servlet-2.2/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v2_2/ServletAndFilterChainInstrumentation.java @@ -11,29 +11,20 @@ import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf import static java.util.Collections.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.not; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.Instrumenter; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; 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 Servlet2Instrumentation extends Instrumenter.Default { +final class ServletAndFilterChainInstrumentation implements TypeInstrumentation { - public Servlet2Instrumentation() { - super("servlet", "servlet-2"); - } - - // this is required to make sure servlet 2 instrumentation won't apply to servlet 3 @Override public ElementMatcher classLoaderMatcher() { // Optimization for expensive typeMatcher. - return hasClassesNamed("javax.servlet.http.HttpServlet") - .and(not(hasClassesNamed("javax.servlet.AsyncEvent", "javax.servlet.AsyncListener"))); + return hasClassesNamed("javax.servlet.http.HttpServlet"); } @Override @@ -41,22 +32,6 @@ public final class Servlet2Instrumentation extends Instrumenter.Default { return safeHasSuperType( namedOneOf("javax.servlet.FilterChain", "javax.servlet.http.HttpServlet")); } - - @Override - public Map 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 * 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(1, named("javax.servlet.ServletResponse"))) .and(isPublic()), - packageName + ".Servlet2Advice"); + Servlet2Advice.class.getName()); } } diff --git a/instrumentation/servlet/servlet-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v3_0/AsyncContextInstrumentation.java b/instrumentation/servlet/servlet-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v3_0/AsyncContextInstrumentation.java index 6538fd3f92..a155bcad2f 100644 --- a/instrumentation/servlet/servlet-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v3_0/AsyncContextInstrumentation.java +++ b/instrumentation/servlet/servlet-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v3_0/AsyncContextInstrumentation.java @@ -13,12 +13,11 @@ import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.named; -import com.google.auto.service.AutoService; import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Context; import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.tooling.Instrumenter; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.Map; import javax.servlet.AsyncContext; import javax.servlet.ServletRequest; @@ -27,20 +26,7 @@ import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; -@AutoService(Instrumenter.class) -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", - }; - } +final class AsyncContextInstrumentation implements TypeInstrumentation { @Override public ElementMatcher classLoaderMatcher() { diff --git a/instrumentation/servlet/servlet-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v3_0/Servlet3InstrumentationModule.java b/instrumentation/servlet/servlet-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v3_0/Servlet3InstrumentationModule.java new file mode 100644 index 0000000000..e616e9e562 --- /dev/null +++ b/instrumentation/servlet/servlet-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v3_0/Servlet3InstrumentationModule.java @@ -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 typeInstrumentations() { + return asList(new AsyncContextInstrumentation(), new ServletAndFilterChainInstrumentation()); + } +} diff --git a/instrumentation/servlet/servlet-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v3_0/Servlet3Instrumentation.java b/instrumentation/servlet/servlet-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v3_0/ServletAndFilterChainInstrumentation.java similarity index 71% rename from instrumentation/servlet/servlet-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v3_0/Servlet3Instrumentation.java rename to instrumentation/servlet/servlet-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v3_0/ServletAndFilterChainInstrumentation.java index affcfe26a4..9639e1cc09 100644 --- a/instrumentation/servlet/servlet-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v3_0/Servlet3Instrumentation.java +++ b/instrumentation/servlet/servlet-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v3_0/ServletAndFilterChainInstrumentation.java @@ -13,19 +13,13 @@ import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.Instrumenter; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; 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 Servlet3Instrumentation extends Instrumenter.Default { - public Servlet3Instrumentation() { - super("servlet", "servlet-3"); - } - +final class ServletAndFilterChainInstrumentation implements TypeInstrumentation { @Override public ElementMatcher classLoaderMatcher() { // Optimization for expensive typeMatcher. @@ -38,17 +32,6 @@ public final class Servlet3Instrumentation extends Instrumenter.Default { 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 * 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(1, named("javax.servlet.ServletResponse"))) .and(isPublic()), - packageName + ".Servlet3Advice"); + Servlet3Advice.class.getName()); } } diff --git a/instrumentation/servlet/servlet-common/servlet-common.gradle b/instrumentation/servlet/servlet-common/servlet-common.gradle index de90aecb0c..ed6d181150 100644 --- a/instrumentation/servlet/servlet-common/servlet-common.gradle +++ b/instrumentation/servlet/servlet-common/servlet-common.gradle @@ -4,7 +4,12 @@ muzzle { pass { group = "javax.servlet" module = "servlet-api" - versions = "[2.2,)" + versions = "(0,)" + } + pass { + group = "javax.servlet" + module = 'javax.servlet-api' + versions = "[3.0,)" assertInverse = true } } diff --git a/instrumentation/servlet/servlet-common/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/dispatcher/RequestDispatcherInstrumentation.java b/instrumentation/servlet/servlet-common/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/dispatcher/RequestDispatcherInstrumentationModule.java similarity index 77% rename from instrumentation/servlet/servlet-common/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/dispatcher/RequestDispatcherInstrumentation.java rename to instrumentation/servlet/servlet-common/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/dispatcher/RequestDispatcherInstrumentationModule.java index f4a4f04e8a..1185d1a0ec 100644 --- a/instrumentation/servlet/servlet-common/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/dispatcher/RequestDispatcherInstrumentation.java +++ b/instrumentation/servlet/servlet-common/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/dispatcher/RequestDispatcherInstrumentationModule.java @@ -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.bytebuddy.matcher.AgentElementMatchers.implementsInterface; import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; +import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.isPublic; 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.Scope; 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.util.List; import java.util.Map; import javax.servlet.RequestDispatcher; import javax.servlet.ServletRequest; @@ -32,23 +35,12 @@ import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; -@AutoService(Instrumenter.class) -public final class RequestDispatcherInstrumentation extends Instrumenter.Default { - public RequestDispatcherInstrumentation() { +@AutoService(InstrumentationModule.class) +public final class RequestDispatcherInstrumentationModule extends InstrumentationModule { + public RequestDispatcherInstrumentationModule() { super("servlet", "servlet-dispatcher"); } - @Override - public ElementMatcher classLoaderMatcher() { - // Optimization for expensive typeMatcher. - return hasClassesNamed("javax.servlet.RequestDispatcher"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("javax.servlet.RequestDispatcher")); - } - @Override public String[] helperClassNames() { return new String[] { @@ -56,20 +48,38 @@ public final class RequestDispatcherInstrumentation extends Instrumenter.Default }; } + @Override + public List typeInstrumentations() { + return singletonList(new RequestDispatcherInstrumentation()); + } + @Override public Map contextStore() { return singletonMap("javax.servlet.RequestDispatcher", String.class.getName()); } - @Override - public Map, String> transformers() { - return singletonMap( - namedOneOf("forward", "include") - .and(takesArguments(2)) - .and(takesArgument(0, named("javax.servlet.ServletRequest"))) - .and(takesArgument(1, named("javax.servlet.ServletResponse"))) - .and(isPublic()), - getClass().getName() + "$RequestDispatcherAdvice"); + private static final class RequestDispatcherInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher classLoaderMatcher() { + // Optimization for expensive typeMatcher. + return hasClassesNamed("javax.servlet.RequestDispatcher"); + } + + @Override + public ElementMatcher typeMatcher() { + return implementsInterface(named("javax.servlet.RequestDispatcher")); + } + + @Override + public Map, String> transformers() { + return singletonMap( + namedOneOf("forward", "include") + .and(takesArguments(2)) + .and(takesArgument(0, named("javax.servlet.ServletRequest"))) + .and(takesArgument(1, named("javax.servlet.ServletResponse"))) + .and(isPublic()), + RequestDispatcherInstrumentationModule.class.getName() + "$RequestDispatcherAdvice"); + } } public static class RequestDispatcherAdvice { diff --git a/instrumentation/servlet/servlet-common/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/filter/FilterInstrumentation.java b/instrumentation/servlet/servlet-common/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/filter/FilterInstrumentationModule.java similarity index 66% rename from instrumentation/servlet/servlet-common/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/filter/FilterInstrumentation.java rename to instrumentation/servlet/servlet-common/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/filter/FilterInstrumentationModule.java index 1aa193b280..5688a7c0b1 100644 --- a/instrumentation/servlet/servlet-common/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/filter/FilterInstrumentation.java +++ b/instrumentation/servlet/servlet-common/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/filter/FilterInstrumentationModule.java @@ -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.tooling.ClassLoaderMatcher.hasClassesNamed; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; +import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.isPublic; 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.context.Scope; 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 javax.servlet.Filter; import net.bytebuddy.asm.Advice; @@ -31,9 +34,9 @@ import net.bytebuddy.matcher.ElementMatcher; * *

See README.md for more information about different servlet instrumentations. */ -@AutoService(Instrumenter.class) -public final class FilterInstrumentation extends Instrumenter.Default { - public FilterInstrumentation() { +@AutoService(InstrumentationModule.class) +public final class FilterInstrumentationModule extends InstrumentationModule { + public FilterInstrumentationModule() { super("servlet-filter"); } @@ -42,18 +45,6 @@ public final class FilterInstrumentation extends Instrumenter.Default { return false; } - @Override - public ElementMatcher classLoaderMatcher() { - // Optimization for expensive typeMatcher. - // return hasClassesNamed("javax.servlet.Filter"); // Not available in 2.2 - return hasClassesNamed("javax.servlet.http.HttpServlet"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("javax.servlet.Filter")); - } - @Override public String[] helperClassNames() { return new String[] { @@ -62,13 +53,31 @@ public final class FilterInstrumentation extends Instrumenter.Default { } @Override - public Map, String> transformers() { - return singletonMap( - named("doFilter") - .and(takesArgument(0, named("javax.servlet.ServletRequest"))) - .and(takesArgument(1, named("javax.servlet.ServletResponse"))) - .and(isPublic()), - getClass().getName() + "$FilterAdvice"); + public List typeInstrumentations() { + return singletonList(new FilterInstrumentation()); + } + + private static final class FilterInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher classLoaderMatcher() { + // Optimization for expensive typeMatcher. + return hasClassesNamed("javax.servlet.Filter"); + } + + @Override + public ElementMatcher typeMatcher() { + return implementsInterface(named("javax.servlet.Filter")); + } + + @Override + public Map, String> transformers() { + return singletonMap( + named("doFilter") + .and(takesArgument(0, named("javax.servlet.ServletRequest"))) + .and(takesArgument(1, named("javax.servlet.ServletResponse"))) + .and(isPublic()), + FilterInstrumentationModule.class.getName() + "$FilterAdvice"); + } } public static class FilterAdvice { diff --git a/instrumentation/servlet/servlet-common/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/http/HttpServletInstrumentation.java b/instrumentation/servlet/servlet-common/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/http/HttpServletInstrumentationModule.java similarity index 57% rename from instrumentation/servlet/servlet-common/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/http/HttpServletInstrumentation.java rename to instrumentation/servlet/servlet-common/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/http/HttpServletInstrumentationModule.java index 8fe776df71..c64c3ec587 100644 --- a/instrumentation/servlet/servlet-common/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/http/HttpServletInstrumentation.java +++ b/instrumentation/servlet/servlet-common/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/http/HttpServletInstrumentationModule.java @@ -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.tooling.ClassLoaderMatcher.hasClassesNamed; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; +import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.isProtected; 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.context.Scope; 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.util.List; import java.util.Map; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; -// Please read README.md of this subproject to understand what is this instrumentation. -@AutoService(Instrumenter.class) -public final class HttpServletInstrumentation extends Instrumenter.Default { - public HttpServletInstrumentation() { +// Please read README.md of this subproject to understand what this instrumentation is and why it +// requires a separate module. +@AutoService(InstrumentationModule.class) +public final class HttpServletInstrumentationModule extends InstrumentationModule { + public HttpServletInstrumentationModule() { super("servlet-service"); } @@ -39,17 +43,6 @@ public final class HttpServletInstrumentation extends Instrumenter.Default { return false; } - @Override - public ElementMatcher classLoaderMatcher() { - // Optimization for expensive typeMatcher. - return hasClassesNamed("javax.servlet.http.HttpServlet"); - } - - @Override - public ElementMatcher typeMatcher() { - return extendsClass(named("javax.servlet.http.HttpServlet")); - } - @Override public String[] helperClassNames() { return new String[] { @@ -57,19 +50,38 @@ public final class HttpServletInstrumentation extends Instrumenter.Default { }; } - /** - * 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. - */ @Override - public Map, String> transformers() { - return singletonMap( - named("service") - .or(nameStartsWith("do")) // doGet, doPost, etc - .and(takesArgument(0, named("javax.servlet.http.HttpServletRequest"))) - .and(takesArgument(1, named("javax.servlet.http.HttpServletResponse"))) - .and(isProtected().or(isPublic())), - getClass().getName() + "$HttpServletAdvice"); + public List typeInstrumentations() { + return singletonList(new HttpServletInstrumentation()); + } + + private static final class HttpServletInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher classLoaderMatcher() { + // Optimization for expensive typeMatcher. + return hasClassesNamed("javax.servlet.http.HttpServlet"); + } + + @Override + public ElementMatcher typeMatcher() { + return extendsClass(named("javax.servlet.http.HttpServlet")); + } + + /** + * 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. + */ + @Override + public Map, String> transformers() { + return singletonMap( + named("service") + .or(nameStartsWith("do")) // doGet, doPost, etc + .and(takesArgument(0, named("javax.servlet.http.HttpServletRequest"))) + .and(takesArgument(1, named("javax.servlet.http.HttpServletResponse"))) + .and(isProtected().or(isPublic())), + HttpServletInstrumentationModule.class.getName() + "$HttpServletAdvice"); + } } public static class HttpServletAdvice { diff --git a/instrumentation/servlet/servlet-common/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/http/HttpServletResponseInstrumentation.java b/instrumentation/servlet/servlet-common/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/http/HttpServletResponseInstrumentationModule.java similarity index 70% rename from instrumentation/servlet/servlet-common/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/http/HttpServletResponseInstrumentation.java rename to instrumentation/servlet/servlet-common/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/http/HttpServletResponseInstrumentationModule.java index 159f025c95..88b95b574b 100644 --- a/instrumentation/servlet/servlet-common/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/http/HttpServletResponseInstrumentation.java +++ b/instrumentation/servlet/servlet-common/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/http/HttpServletResponseInstrumentationModule.java @@ -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.bytebuddy.matcher.AgentElementMatchers.implementsInterface; import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; +import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; 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.Depth; 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.util.List; import java.util.Map; import javax.servlet.http.HttpServletResponse; import net.bytebuddy.asm.Advice; @@ -27,23 +30,12 @@ import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; -@AutoService(Instrumenter.class) -public final class HttpServletResponseInstrumentation extends Instrumenter.Default { - public HttpServletResponseInstrumentation() { +@AutoService(InstrumentationModule.class) +public final class HttpServletResponseInstrumentationModule extends InstrumentationModule { + public HttpServletResponseInstrumentationModule() { super("servlet", "servlet-response"); } - @Override - public ElementMatcher classLoaderMatcher() { - // Optimization for expensive typeMatcher. - return hasClassesNamed("javax.servlet.http.HttpServletResponse"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("javax.servlet.http.HttpServletResponse")); - } - @Override public String[] helperClassNames() { return new String[] { @@ -52,8 +44,26 @@ public final class HttpServletResponseInstrumentation extends Instrumenter.Defau } @Override - public Map, String> transformers() { - return singletonMap(namedOneOf("sendError", "sendRedirect"), SendAdvice.class.getName()); + public List typeInstrumentations() { + return singletonList(new HttpServletResponseInstrumentation()); + } + + private static final class HttpServletResponseInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher classLoaderMatcher() { + // Optimization for expensive typeMatcher. + return hasClassesNamed("javax.servlet.http.HttpServletResponse"); + } + + @Override + public ElementMatcher typeMatcher() { + return implementsInterface(named("javax.servlet.http.HttpServletResponse")); + } + + @Override + public Map, String> transformers() { + return singletonMap(namedOneOf("sendError", "sendRedirect"), SendAdvice.class.getName()); + } } public static class SendAdvice { diff --git a/instrumentation/spark-web-framework-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/sparkjava/RoutesInstrumentation.java b/instrumentation/spark-web-framework-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/sparkjava/SparkInstrumentationModule.java similarity index 53% rename from instrumentation/spark-web-framework-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/sparkjava/RoutesInstrumentation.java rename to instrumentation/spark-web-framework-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/sparkjava/SparkInstrumentationModule.java index 773e6fb845..5af96ca2a5 100644 --- a/instrumentation/spark-web-framework-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/sparkjava/RoutesInstrumentation.java +++ b/instrumentation/spark-web-framework-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/sparkjava/SparkInstrumentationModule.java @@ -5,6 +5,7 @@ package io.opentelemetry.javaagent.instrumentation.sparkjava; +import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.isPublic; 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 com.google.auto.service.AutoService; -import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.Tracer; 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 net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; @@ -24,41 +25,32 @@ import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; import spark.routematch.RouteMatch; -@AutoService(Instrumenter.class) -public class RoutesInstrumentation extends Instrumenter.Default { +@AutoService(InstrumentationModule.class) +public class SparkInstrumentationModule extends InstrumentationModule { - public RoutesInstrumentation() { + public SparkInstrumentationModule() { super("sparkjava", "sparkjava-2.4"); } @Override - public ElementMatcher typeMatcher() { - return named("spark.route.Routes"); + public List typeInstrumentations() { + return singletonList(new RoutesInstrumentation()); } - @Override - public String[] helperClassNames() { - return new String[] { - RoutesInstrumentation.class.getName() + "$TracerHolder", - }; - } + private static final class RoutesInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher typeMatcher() { + return named("spark.route.Routes"); + } - @Override - public Map, String> transformers() { - return singletonMap( - named("find") - .and(takesArgument(0, named("spark.route.HttpMethod"))) - .and(returns(named("spark.routematch.RouteMatch"))) - .and(isPublic()), - RoutesInstrumentation.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; + @Override + public Map, String> transformers() { + return singletonMap( + named("find") + .and(takesArgument(0, named("spark.route.HttpMethod"))) + .and(returns(named("spark.routematch.RouteMatch"))) + .and(isPublic()), + SparkInstrumentationModule.class.getName() + "$RoutesAdvice"); } } diff --git a/instrumentation/spring/spring-data-1.8/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/data/SpringRepositoryInstrumentation.java b/instrumentation/spring/spring-data-1.8/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/data/SpringDataInstrumentationModule.java similarity index 79% rename from instrumentation/spring/spring-data-1.8/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/data/SpringRepositoryInstrumentation.java rename to instrumentation/spring/spring-data-1.8/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/data/SpringDataInstrumentationModule.java index 156508fdd8..49122e9b5f 100644 --- a/instrumentation/spring/spring-data-1.8/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/data/SpringRepositoryInstrumentation.java +++ b/instrumentation/spring/spring-data-1.8/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/data/SpringDataInstrumentationModule.java @@ -6,6 +6,7 @@ package io.opentelemetry.javaagent.instrumentation.spring.data; import static io.opentelemetry.javaagent.instrumentation.spring.data.SpringDataTracer.tracer; +import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.isConstructor; 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 io.opentelemetry.api.trace.Span; 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.util.List; import java.util.Map; import net.bytebuddy.asm.Advice; 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.RepositoryProxyPostProcessor; -@AutoService(Instrumenter.class) -public final class SpringRepositoryInstrumentation extends Instrumenter.Default { +@AutoService(InstrumentationModule.class) +public final class SpringDataInstrumentationModule extends InstrumentationModule { - public SpringRepositoryInstrumentation() { + public SpringDataInstrumentationModule() { super("spring-data"); } - @Override - public ElementMatcher typeMatcher() { - return named("org.springframework.data.repository.core.support.RepositoryFactorySupport"); - } - @Override public String[] helperClassNames() { return new String[] { @@ -50,10 +48,23 @@ public final class SpringRepositoryInstrumentation extends Instrumenter.Default } @Override - public Map, String> transformers() { - return singletonMap( - isConstructor(), - SpringRepositoryInstrumentation.class.getName() + "$RepositoryFactorySupportAdvice"); + public List typeInstrumentations() { + return singletonList(new RepositoryFactorySupportInstrumentation()); + } + + private static final class RepositoryFactorySupportInstrumentation + implements TypeInstrumentation { + @Override + public ElementMatcher typeMatcher() { + return named("org.springframework.data.repository.core.support.RepositoryFactorySupport"); + } + + @Override + public Map, String> transformers() { + return singletonMap( + isConstructor(), + SpringDataInstrumentationModule.class.getName() + "$RepositoryFactorySupportAdvice"); + } } public static class RepositoryFactorySupportAdvice { diff --git a/instrumentation/spring/spring-scheduling-3.1/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/scheduling/SpringSchedulingInstrumentation.java b/instrumentation/spring/spring-scheduling-3.1/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/scheduling/SpringSchedulingInstrumentationModule.java similarity index 54% rename from instrumentation/spring/spring-scheduling-3.1/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/scheduling/SpringSchedulingInstrumentation.java rename to instrumentation/spring/spring-scheduling-3.1/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/scheduling/SpringSchedulingInstrumentationModule.java index d9eb021f98..0565d28eb5 100644 --- a/instrumentation/spring/spring-scheduling-3.1/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/scheduling/SpringSchedulingInstrumentation.java +++ b/instrumentation/spring/spring-scheduling-3.1/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/scheduling/SpringSchedulingInstrumentationModule.java @@ -5,31 +5,29 @@ package io.opentelemetry.javaagent.instrumentation.spring.scheduling; +import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.isConstructor; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; 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 net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; -@AutoService(Instrumenter.class) -public final class SpringSchedulingInstrumentation extends Instrumenter.Default { +@AutoService(InstrumentationModule.class) +public final class SpringSchedulingInstrumentationModule extends InstrumentationModule { - public SpringSchedulingInstrumentation() { + public SpringSchedulingInstrumentationModule() { super("spring-scheduling"); } - @Override - public ElementMatcher typeMatcher() { - return named("org.springframework.scheduling.config.Task"); - } - @Override public String[] helperClassNames() { return new String[] { @@ -38,10 +36,22 @@ public final class SpringSchedulingInstrumentation extends Instrumenter.Default } @Override - public Map, String> transformers() { - return singletonMap( - isConstructor().and(takesArgument(0, Runnable.class)), - SpringSchedulingInstrumentation.class.getName() + "$SpringSchedulingAdvice"); + public List typeInstrumentations() { + return singletonList(new TaskInstrumentation()); + } + + private static final class TaskInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher typeMatcher() { + return named("org.springframework.scheduling.config.Task"); + } + + @Override + public Map, String> transformers() { + return singletonMap( + isConstructor().and(takesArgument(0, Runnable.class)), + SpringSchedulingInstrumentationModule.class.getName() + "$SpringSchedulingAdvice"); + } } public static class SpringSchedulingAdvice { diff --git a/instrumentation/spring/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/client/WebClientFilterInstrumentation.java b/instrumentation/spring/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/client/WebfluxClientInstrumentationModule.java similarity index 53% rename from instrumentation/spring/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/client/WebClientFilterInstrumentation.java rename to instrumentation/spring/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/client/WebfluxClientInstrumentationModule.java index 296cbffee1..853d798035 100644 --- a/instrumentation/spring/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/client/WebClientFilterInstrumentation.java +++ b/instrumentation/spring/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/client/WebfluxClientInstrumentationModule.java @@ -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.bytebuddy.matcher.AgentElementMatchers.implementsInterface; +import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.named; 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 net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; -@AutoService(Instrumenter.class) -public class WebClientFilterInstrumentation extends Instrumenter.Default { +@AutoService(InstrumentationModule.class) +public class WebfluxClientInstrumentationModule extends InstrumentationModule { - public WebClientFilterInstrumentation() { + public WebfluxClientInstrumentationModule() { super("spring-webflux", "spring-webflux-client"); } - @Override - public ElementMatcher classLoaderMatcher() { - // Optimization for expensive typeMatcher. - return hasClassesNamed("org.springframework.web.reactive.function.client.WebClient"); - } - @Override public String[] helperClassNames() { return new String[] { @@ -44,14 +41,27 @@ public class WebClientFilterInstrumentation extends Instrumenter.Default { } @Override - public ElementMatcher typeMatcher() { - return implementsInterface( - named("org.springframework.web.reactive.function.client.WebClient$Builder")); + public List typeInstrumentations() { + return singletonList(new WebClientBuilderInstrumentation()); } - @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(isPublic()).and(named("build")), packageName + ".WebClientFilterAdvice"); + private static final class WebClientBuilderInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher classLoaderMatcher() { + // Optimization for expensive typeMatcher. + return hasClassesNamed("org.springframework.web.reactive.function.client.WebClient"); + } + + @Override + public ElementMatcher typeMatcher() { + return implementsInterface( + named("org.springframework.web.reactive.function.client.WebClient$Builder")); + } + + @Override + public Map, String> transformers() { + return singletonMap( + isMethod().and(isPublic()).and(named("build")), WebClientFilterAdvice.class.getName()); + } } } diff --git a/instrumentation/spring/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/server/AbstractWebfluxInstrumentation.java b/instrumentation/spring/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/server/AbstractWebfluxInstrumentation.java deleted file mode 100644 index 4866e0c130..0000000000 --- a/instrumentation/spring/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/server/AbstractWebfluxInstrumentation.java +++ /dev/null @@ -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" - }; - } -} diff --git a/instrumentation/spring/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/server/DispatcherHandlerInstrumentation.java b/instrumentation/spring/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/server/DispatcherHandlerInstrumentation.java index eb4dbd2fb5..0845fd963f 100644 --- a/instrumentation/spring/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/server/DispatcherHandlerInstrumentation.java +++ b/instrumentation/spring/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/server/DispatcherHandlerInstrumentation.java @@ -12,15 +12,13 @@ import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArguments; -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.Instrumenter; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; 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 DispatcherHandlerInstrumentation extends AbstractWebfluxInstrumentation { +final class DispatcherHandlerInstrumentation implements TypeInstrumentation { @Override public ElementMatcher typeMatcher() { @@ -35,7 +33,6 @@ public final class DispatcherHandlerInstrumentation extends AbstractWebfluxInstr .and(named("handle")) .and(takesArgument(0, named("org.springframework.web.server.ServerWebExchange"))) .and(takesArguments(1)), - // Cannot reference class directly here because it would lead to class load failure on Java7 - packageName + ".DispatcherHandlerAdvice"); + DispatcherHandlerAdvice.class.getName()); } } diff --git a/instrumentation/spring/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/server/HandlerAdapterInstrumentation.java b/instrumentation/spring/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/server/HandlerAdapterInstrumentation.java index eccce4a064..dbd57e19ad 100644 --- a/instrumentation/spring/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/server/HandlerAdapterInstrumentation.java +++ b/instrumentation/spring/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/server/HandlerAdapterInstrumentation.java @@ -16,15 +16,13 @@ import static net.bytebuddy.matcher.ElementMatchers.not; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArguments; -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.Instrumenter; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; 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 HandlerAdapterInstrumentation extends AbstractWebfluxInstrumentation { +final class HandlerAdapterInstrumentation implements TypeInstrumentation { @Override public ElementMatcher classLoaderMatcher() { @@ -47,7 +45,6 @@ public final class HandlerAdapterInstrumentation extends AbstractWebfluxInstrume .and(takesArgument(0, named("org.springframework.web.server.ServerWebExchange"))) .and(takesArgument(1, named("java.lang.Object"))) .and(takesArguments(2)), - // Cannot reference class directly here because it would lead to class load failure on Java7 - packageName + ".HandlerAdapterAdvice"); + HandlerAdapterAdvice.class.getName()); } } diff --git a/instrumentation/spring/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/server/RouterFunctionInstrumentation.java b/instrumentation/spring/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/server/RouterFunctionInstrumentation.java index 305e8daff9..a78f96bde5 100644 --- a/instrumentation/spring/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/server/RouterFunctionInstrumentation.java +++ b/instrumentation/spring/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/server/RouterFunctionInstrumentation.java @@ -16,19 +16,13 @@ import static net.bytebuddy.matcher.ElementMatchers.not; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArguments; -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.Instrumenter; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; 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 RouterFunctionInstrumentation extends AbstractWebfluxInstrumentation { - - public RouterFunctionInstrumentation() { - super("spring-webflux-functional"); - } +final class RouterFunctionInstrumentation implements TypeInstrumentation { @Override public ElementMatcher classLoaderMatcher() { @@ -56,7 +50,6 @@ public final class RouterFunctionInstrumentation extends AbstractWebfluxInstrume takesArgument( 0, named("org.springframework.web.reactive.function.server.ServerRequest"))) .and(takesArguments(1)), - // Cannot reference class directly here because it would lead to class load failure on Java7 - packageName + ".RouterFunctionAdvice"); + RouterFunctionAdvice.class.getName()); } } diff --git a/instrumentation/spring/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/server/WebfluxServerInstrumentationModule.java b/instrumentation/spring/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/server/WebfluxServerInstrumentationModule.java new file mode 100644 index 0000000000..6e574aac13 --- /dev/null +++ b/instrumentation/spring/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/server/WebfluxServerInstrumentationModule.java @@ -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 typeInstrumentations() { + return asList( + new DispatcherHandlerInstrumentation(), + new HandlerAdapterInstrumentation(), + new RouterFunctionInstrumentation()); + } +} diff --git a/instrumentation/spymemcached-2.12/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/MemcachedClientInstrumentation.java b/instrumentation/spymemcached-2.12/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/SpymemcachedInstrumentationModule.java similarity index 68% rename from instrumentation/spymemcached-2.12/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/MemcachedClientInstrumentation.java rename to instrumentation/spymemcached-2.12/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/SpymemcachedInstrumentationModule.java index cc5f18977e..c296e6bef4 100644 --- a/instrumentation/spymemcached-2.12/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/MemcachedClientInstrumentation.java +++ b/instrumentation/spymemcached-2.12/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/SpymemcachedInstrumentationModule.java @@ -6,6 +6,7 @@ package io.opentelemetry.javaagent.instrumentation.spymemcached; 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.isPublic; 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 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.List; import java.util.Map; import net.bytebuddy.asm.Advice; 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.OperationFuture; -@AutoService(Instrumenter.class) -public final class MemcachedClientInstrumentation extends Instrumenter.Default { +@AutoService(InstrumentationModule.class) +public final class SpymemcachedInstrumentationModule extends InstrumentationModule { - private static final String MEMCACHED_PACKAGE = "net.spy.memcached"; - - public MemcachedClientInstrumentation() { + public SpymemcachedInstrumentationModule() { super("spymemcached"); } - @Override - public ElementMatcher typeMatcher() { - return named(MEMCACHED_PACKAGE + ".MemcachedClient"); - } - @Override public String[] helperClassNames() { return new String[] { @@ -53,28 +49,40 @@ public final class MemcachedClientInstrumentation extends Instrumenter.Default { } @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - transformers.put( - isMethod() - .and(isPublic()) - .and(returns(named(MEMCACHED_PACKAGE + ".internal.OperationFuture"))) - /* - Flush seems to have a bug when listeners may not be always called. - Also tracing flush is probably of a very limited value. - */ - .and(not(named("flush"))), - MemcachedClientInstrumentation.class.getName() + "$AsyncOperationAdvice"); - transformers.put( - isMethod().and(isPublic()).and(returns(named(MEMCACHED_PACKAGE + ".internal.GetFuture"))), - MemcachedClientInstrumentation.class.getName() + "$AsyncGetAdvice"); - transformers.put( - isMethod().and(isPublic()).and(returns(named(MEMCACHED_PACKAGE + ".internal.BulkFuture"))), - MemcachedClientInstrumentation.class.getName() + "$AsyncBulkAdvice"); - transformers.put( - isMethod().and(isPublic()).and(namedOneOf("incr", "decr")), - MemcachedClientInstrumentation.class.getName() + "$SyncOperationAdvice"); - return transformers; + public List typeInstrumentations() { + return singletonList(new MemcachedClientInstrumentation()); + } + + private static final class MemcachedClientInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher typeMatcher() { + return named("net.spy.memcached.MemcachedClient"); + } + + @Override + public Map, String> transformers() { + Map, String> transformers = new HashMap<>(); + transformers.put( + isMethod() + .and(isPublic()) + .and(returns(named("net.spy.memcached.internal.OperationFuture"))) + /* + Flush seems to have a bug when listeners may not be always called. + Also tracing flush is probably of a very limited value. + */ + .and(not(named("flush"))), + SpymemcachedInstrumentationModule.class.getName() + "$AsyncOperationAdvice"); + transformers.put( + isMethod().and(isPublic()).and(returns(named("net.spy.memcached.internal.GetFuture"))), + SpymemcachedInstrumentationModule.class.getName() + "$AsyncGetAdvice"); + transformers.put( + isMethod().and(isPublic()).and(returns(named("net.spy.memcached.internal.BulkFuture"))), + SpymemcachedInstrumentationModule.class.getName() + "$AsyncBulkAdvice"); + transformers.put( + isMethod().and(isPublic()).and(namedOneOf("incr", "decr")), + SpymemcachedInstrumentationModule.class.getName() + "$SyncOperationAdvice"); + return transformers; + } } public static class AsyncOperationAdvice { @@ -89,7 +97,7 @@ public final class MemcachedClientInstrumentation extends Instrumenter.Default { @Advice.Enter int callDepth, @Advice.This MemcachedClient client, @Advice.Origin("#m") String methodName, - @Advice.Return OperationFuture future) { + @Advice.Return OperationFuture future) { if (callDepth > 0) { return; } @@ -115,7 +123,7 @@ public final class MemcachedClientInstrumentation extends Instrumenter.Default { @Advice.Enter int callDepth, @Advice.This MemcachedClient client, @Advice.Origin("#m") String methodName, - @Advice.Return GetFuture future) { + @Advice.Return GetFuture future) { if (callDepth > 0) { return; } @@ -141,7 +149,7 @@ public final class MemcachedClientInstrumentation extends Instrumenter.Default { @Advice.Enter int callDepth, @Advice.This MemcachedClient client, @Advice.Origin("#m") String methodName, - @Advice.Return BulkFuture future) { + @Advice.Return BulkFuture future) { if (callDepth > 0) { return; } diff --git a/instrumentation/twilio-6.6/src/main/java/io/opentelemetry/javaagent/instrumentation/twilio/TwilioAsyncInstrumentation.java b/instrumentation/twilio-6.6/src/main/java/io/opentelemetry/javaagent/instrumentation/twilio/TwilioAsyncInstrumentation.java index 0af9e06005..94a622d4d8 100644 --- a/instrumentation/twilio-6.6/src/main/java/io/opentelemetry/javaagent/instrumentation/twilio/TwilioAsyncInstrumentation.java +++ b/instrumentation/twilio-6.6/src/main/java/io/opentelemetry/javaagent/instrumentation/twilio/TwilioAsyncInstrumentation.java @@ -19,7 +19,6 @@ import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.not; 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.Futures; import com.google.common.util.concurrent.ListenableFuture; @@ -27,19 +26,14 @@ import com.twilio.Twilio; import io.opentelemetry.api.trace.Span; import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import io.opentelemetry.javaagent.tooling.Instrumenter; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.Map; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.matcher.ElementMatcher; -/** Instrument the Twilio SDK to identify calls as a seperate service. */ -@AutoService(Instrumenter.class) -public class TwilioAsyncInstrumentation extends Instrumenter.Default { - - public TwilioAsyncInstrumentation() { - super("twilio-sdk"); - } +/** Instrument the Twilio SDK to identify calls as a separate service. */ +final class TwilioAsyncInstrumentation implements TypeInstrumentation { @Override public ElementMatcher classLoaderMatcher() { @@ -59,15 +53,6 @@ public class TwilioAsyncInstrumentation extends Instrumenter.Default { "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. */ @Override public Map, String> transformers() { @@ -122,7 +107,7 @@ public class TwilioAsyncInstrumentation extends Instrumenter.Default { public static void methodExit( @Advice.Enter SpanWithScope spanWithScope, @Advice.Thrown Throwable throwable, - @Advice.Return ListenableFuture response) { + @Advice.Return ListenableFuture response) { if (spanWithScope == null) { 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 // complete and report the results; set an appropriate callback Futures.addCallback( - response, new SpanFinishingCallback(span), Twilio.getExecutorService()); + response, new SpanFinishingCallback<>(span), Twilio.getExecutorService()); } } finally { spanWithScope.closeScope(); @@ -155,7 +140,7 @@ public class TwilioAsyncInstrumentation extends Instrumenter.Default { * FutureCallback, which automatically finishes the span and annotates with any appropriate * metadata on a potential failure. */ - public static class SpanFinishingCallback implements FutureCallback { + public static class SpanFinishingCallback implements FutureCallback { /** Span that we should finish and annotate when the future is complete. */ private final Span span; diff --git a/instrumentation/twilio-6.6/src/main/java/io/opentelemetry/javaagent/instrumentation/twilio/TwilioInstrumentationModule.java b/instrumentation/twilio-6.6/src/main/java/io/opentelemetry/javaagent/instrumentation/twilio/TwilioInstrumentationModule.java new file mode 100644 index 0000000000..74f56ba8e4 --- /dev/null +++ b/instrumentation/twilio-6.6/src/main/java/io/opentelemetry/javaagent/instrumentation/twilio/TwilioInstrumentationModule.java @@ -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 typeInstrumentations() { + return asList(new TwilioAsyncInstrumentation(), new TwilioSyncInstrumentation()); + } +} diff --git a/instrumentation/twilio-6.6/src/main/java/io/opentelemetry/javaagent/instrumentation/twilio/TwilioSyncInstrumentation.java b/instrumentation/twilio-6.6/src/main/java/io/opentelemetry/javaagent/instrumentation/twilio/TwilioSyncInstrumentation.java index b1e42548dd..1b9710e2ce 100644 --- a/instrumentation/twilio-6.6/src/main/java/io/opentelemetry/javaagent/instrumentation/twilio/TwilioSyncInstrumentation.java +++ b/instrumentation/twilio-6.6/src/main/java/io/opentelemetry/javaagent/instrumentation/twilio/TwilioSyncInstrumentation.java @@ -17,24 +17,18 @@ import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.not; -import com.google.auto.service.AutoService; import com.twilio.Twilio; import io.opentelemetry.api.trace.Span; import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import io.opentelemetry.javaagent.tooling.Instrumenter; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.Map; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.matcher.ElementMatcher; -/** Instrument the Twilio SDK to identify calls as a seperate service. */ -@AutoService(Instrumenter.class) -public class TwilioSyncInstrumentation extends Instrumenter.Default { - - public TwilioSyncInstrumentation() { - super("twilio-sdk"); - } +/** Instrument the Twilio SDK to identify calls as a separate service. */ +final class TwilioSyncInstrumentation implements TypeInstrumentation { @Override public ElementMatcher classLoaderMatcher() { @@ -56,14 +50,6 @@ public class TwilioSyncInstrumentation extends Instrumenter.Default { "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. */ @Override public Map, String> transformers() { diff --git a/instrumentation/vertx-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/RouteInstrumentation.java b/instrumentation/vertx-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/VertxInstrumentationModule.java similarity index 56% rename from instrumentation/vertx-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/RouteInstrumentation.java rename to instrumentation/vertx-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/VertxInstrumentationModule.java index 704c79bf77..62f3b04a48 100644 --- a/instrumentation/vertx-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/RouteInstrumentation.java +++ b/instrumentation/vertx-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/VertxInstrumentationModule.java @@ -7,6 +7,7 @@ package io.opentelemetry.javaagent.instrumentation.vertx; import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.safeHasSuperType; +import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.isInterface; import static net.bytebuddy.matcher.ElementMatchers.isMethod; @@ -15,32 +16,24 @@ import static net.bytebuddy.matcher.ElementMatchers.not; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; 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.ext.web.RoutingContext; +import java.util.List; import java.util.Map; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; -@AutoService(Instrumenter.class) -public final class RouteInstrumentation extends Instrumenter.Default { +@AutoService(InstrumentationModule.class) +public final class VertxInstrumentationModule extends InstrumentationModule { - public RouteInstrumentation() { + public VertxInstrumentationModule() { super("vertx"); } - @Override - public ElementMatcher classLoaderMatcher() { - return hasClassesNamed("io.vertx.ext.web.Route"); - } - - @Override - public ElementMatcher typeMatcher() { - return not(isInterface()).and(safeHasSuperType(named("io.vertx.ext.web.Route"))); - } - @Override public String[] helperClassNames() { return new String[] { @@ -49,10 +42,27 @@ public final class RouteInstrumentation extends Instrumenter.Default { } @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(named("handler")).and(takesArgument(0, named("io.vertx.core.Handler"))), - RouteInstrumentation.class.getName() + "$RouteAdvice"); + public List typeInstrumentations() { + return singletonList(new RouteInstrumentation()); + } + + private static final class RouteInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher classLoaderMatcher() { + return hasClassesNamed("io.vertx.ext.web.Route"); + } + + @Override + public ElementMatcher typeMatcher() { + return not(isInterface()).and(safeHasSuperType(named("io.vertx.ext.web.Route"))); + } + + @Override + public Map, String> transformers() { + return singletonMap( + isMethod().and(named("handler")).and(takesArgument(0, named("io.vertx.core.Handler"))), + VertxInstrumentationModule.class.getName() + "$RouteAdvice"); + } } public static class RouteAdvice { diff --git a/instrumentation/vertx-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/package-info.java b/instrumentation/vertx-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/package-info.java index 5c6dd2bdeb..2664388038 100644 --- a/instrumentation/vertx-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/package-info.java +++ b/instrumentation/vertx-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/package-info.java @@ -2,9 +2,9 @@ * The majority of monitoring needs of Vert.x application is covered by generic instrumentations. * Such as those of netty or JDBC. * - *

{@link io.opentelemetry.javaagent.instrumentation.vertx.RouteInstrumentation} wraps all Vert.x - * route handlers in order to update the name of the currently active SERVER span with the name of - * route. This is, arguably, a much more user-friendly name that defaults provided by HTTP server - * instrumentations. + *

{@link io.opentelemetry.javaagent.instrumentation.vertx.VertxInstrumentationModule} wraps all + * Vert.x route handlers in order to update the name of the currently active SERVER span with the + * name of route. This is, arguably, a much more user-friendly name that defaults provided by HTTP + * server instrumentations. */ package io.opentelemetry.javaagent.instrumentation.vertx; diff --git a/instrumentation/vertx-reactive-3.5/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/reactive/VertxRxInstrumentation.java b/instrumentation/vertx-reactive-3.5/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/reactive/VertxRxInstrumentationModule.java similarity index 53% rename from instrumentation/vertx-reactive-3.5/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/reactive/VertxRxInstrumentation.java rename to instrumentation/vertx-reactive-3.5/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/reactive/VertxRxInstrumentationModule.java index 753bc25bd3..5c16a4c562 100644 --- a/instrumentation/vertx-reactive-3.5/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/reactive/VertxRxInstrumentation.java +++ b/instrumentation/vertx-reactive-3.5/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/reactive/VertxRxInstrumentationModule.java @@ -6,16 +6,19 @@ package io.opentelemetry.javaagent.instrumentation.vertx.reactive; 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.named; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import com.google.auto.service.AutoService; 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.Handler; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.function.Consumer; import net.bytebuddy.asm.Advice; @@ -24,26 +27,13 @@ import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; /** This instrumentation allows span context propagation across Vert.x reactive executions. */ -@AutoService(Instrumenter.class) -public class VertxRxInstrumentation extends Instrumenter.Default { +@AutoService(InstrumentationModule.class) +public class VertxRxInstrumentationModule extends InstrumentationModule { - public VertxRxInstrumentation() { + public VertxRxInstrumentationModule() { super("vertx"); } - @Override - public ElementMatcher classLoaderMatcher() { - // Different versions of Vert.x has this class in different packages - return hasClassesNamed("io.vertx.reactivex.core.impl.AsyncResultSingle") - .or(hasClassesNamed("io.vertx.reactivex.impl.AsyncResultSingle")); - } - - @Override - public ElementMatcher typeMatcher() { - return named("io.vertx.reactivex.core.impl.AsyncResultSingle") - .or(named("io.vertx.reactivex.impl.AsyncResultSingle")); - } - @Override public String[] helperClassNames() { return new String[] { @@ -52,15 +42,35 @@ public class VertxRxInstrumentation extends Instrumenter.Default { } @Override - public Map, String> transformers() { - Map, String> result = new HashMap<>(); - result.put( - isConstructor().and(takesArgument(0, named("io.vertx.core.Handler"))), - this.getClass().getName() + "$AsyncResultSingleHandlerAdvice"); - result.put( - isConstructor().and(takesArgument(0, named("java.util.function.Consumer"))), - this.getClass().getName() + "$AsyncResultSingleConsumerAdvice"); - return result; + public List typeInstrumentations() { + return singletonList(new AsyncResultSingleInstrumentation()); + } + + private static final class AsyncResultSingleInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher classLoaderMatcher() { + // Different versions of Vert.x has this class in different packages + return hasClassesNamed("io.vertx.reactivex.core.impl.AsyncResultSingle") + .or(hasClassesNamed("io.vertx.reactivex.impl.AsyncResultSingle")); + } + + @Override + public ElementMatcher typeMatcher() { + return named("io.vertx.reactivex.core.impl.AsyncResultSingle") + .or(named("io.vertx.reactivex.impl.AsyncResultSingle")); + } + + @Override + public Map, String> transformers() { + Map, String> result = new HashMap<>(); + result.put( + isConstructor().and(takesArgument(0, named("io.vertx.core.Handler"))), + VertxRxInstrumentationModule.class.getName() + "$AsyncResultSingleHandlerAdvice"); + result.put( + isConstructor().and(takesArgument(0, named("java.util.function.Consumer"))), + VertxRxInstrumentationModule.class.getName() + "$AsyncResultSingleConsumerAdvice"); + return result; + } } public static class AsyncResultSingleHandlerAdvice { diff --git a/instrumentation/vertx-reactive-3.5/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/reactive/package-info.java b/instrumentation/vertx-reactive-3.5/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/reactive/package-info.java index ce6d03a009..c87927db23 100644 --- a/instrumentation/vertx-reactive-3.5/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/reactive/package-info.java +++ b/instrumentation/vertx-reactive-3.5/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/reactive/package-info.java @@ -2,8 +2,8 @@ * The majority of monitoring needs of Vert.x application is covered by generic instrumentations. * Such as those of netty or JDBC. * - *

{@link io.opentelemetry.javaagent.instrumentation.vertx.reactive.VertxRxInstrumentation} wraps - * {code AsyncResultSingle} classes from Vert.x RxJava library to ensure proper span context + *

{@link io.opentelemetry.javaagent.instrumentation.vertx.reactive.VertxRxInstrumentationModule} + * wraps {code AsyncResultSingle} classes from Vert.x RxJava library to ensure proper span context * propagation in reactive Vert.x applications. */ package io.opentelemetry.javaagent.instrumentation.vertx.reactive;