diff --git a/instrumentation/dropwizard-views-0.7/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardviews/DropwizardViewInstrumentation.java b/instrumentation/dropwizard-views-0.7/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardviews/DropwizardViewInstrumentationModule.java similarity index 65% rename from instrumentation/dropwizard-views-0.7/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardviews/DropwizardViewInstrumentation.java rename to instrumentation/dropwizard-views-0.7/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardviews/DropwizardViewInstrumentationModule.java index 0d511a2c94..52bafe1c3a 100644 --- a/instrumentation/dropwizard-views-0.7/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardviews/DropwizardViewInstrumentation.java +++ b/instrumentation/dropwizard-views-0.7/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardviews/DropwizardViewInstrumentationModule.java @@ -7,6 +7,7 @@ package io.opentelemetry.javaagent.instrumentation.dropwizardviews; 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; @@ -22,44 +23,47 @@ import io.opentelemetry.api.trace.Tracer; import io.opentelemetry.instrumentation.api.decorator.BaseDecorator; import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -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 DropwizardViewInstrumentation extends Instrumenter.Default { - - public DropwizardViewInstrumentation() { +@AutoService(InstrumentationModule.class) +public final class DropwizardViewInstrumentationModule extends InstrumentationModule { + public DropwizardViewInstrumentationModule() { super("dropwizard", "dropwizard-view"); } @Override - public ElementMatcher classLoaderMatcher() { - // Optimization for expensive typeMatcher. - return hasClassesNamed("io.dropwizard.views.ViewRenderer"); + public List typeInstrumentations() { + return singletonList(new ViewRendererInstrumentation()); } - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("io.dropwizard.views.ViewRenderer")); - } + private static final class ViewRendererInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher classLoaderMatcher() { + // Optimization for expensive typeMatcher. + return hasClassesNamed("io.dropwizard.views.ViewRenderer"); + } - @Override - public String[] helperClassNames() { - return new String[] {getClass().getName() + "$RenderAdvice"}; - } + @Override + public ElementMatcher typeMatcher() { + return implementsInterface(named("io.dropwizard.views.ViewRenderer")); + } - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(named("render")) - .and(takesArgument(0, named("io.dropwizard.views.View"))) - .and(isPublic()), - DropwizardViewInstrumentation.class.getName() + "$RenderAdvice"); + @Override + public Map, String> transformers() { + return singletonMap( + isMethod() + .and(named("render")) + .and(takesArgument(0, named("io.dropwizard.views.View"))) + .and(isPublic()), + DropwizardViewInstrumentationModule.class.getName() + "$RenderAdvice"); + } } public static class RenderAdvice { diff --git a/instrumentation/elasticsearch/elasticsearch-rest-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v5_0/Elasticsearch5RestClientInstrumentation.java b/instrumentation/elasticsearch/elasticsearch-rest-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v5_0/Elasticsearch5RestClientInstrumentationModule.java similarity index 63% rename from instrumentation/elasticsearch/elasticsearch-rest-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v5_0/Elasticsearch5RestClientInstrumentation.java rename to instrumentation/elasticsearch/elasticsearch-rest-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v5_0/Elasticsearch5RestClientInstrumentationModule.java index 5f34b82833..2f3d7f8f9c 100644 --- a/instrumentation/elasticsearch/elasticsearch-rest-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v5_0/Elasticsearch5RestClientInstrumentation.java +++ b/instrumentation/elasticsearch/elasticsearch-rest-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v5_0/Elasticsearch5RestClientInstrumentationModule.java @@ -7,6 +7,7 @@ package io.opentelemetry.javaagent.instrumentation.elasticsearch.rest.v5_0; import static io.opentelemetry.javaagent.instrumentation.elasticsearch.rest.ElasticsearchRestClientTracer.tracer; 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.named; @@ -16,7 +17,9 @@ import static net.bytebuddy.matcher.ElementMatchers.takesArguments; 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; @@ -24,10 +27,9 @@ import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; import org.elasticsearch.client.ResponseListener; -@AutoService(Instrumenter.class) -public class Elasticsearch5RestClientInstrumentation extends Instrumenter.Default { - - public Elasticsearch5RestClientInstrumentation() { +@AutoService(InstrumentationModule.class) +public class Elasticsearch5RestClientInstrumentationModule extends InstrumentationModule { + public Elasticsearch5RestClientInstrumentationModule() { super("elasticsearch", "elasticsearch-rest", "elasticsearch-rest-5"); } @@ -40,20 +42,28 @@ public class Elasticsearch5RestClientInstrumentation extends Instrumenter.Defaul } @Override - public ElementMatcher typeMatcher() { - return named("org.elasticsearch.client.RestClient"); + public List typeInstrumentations() { + return singletonList(new RestClientInstrumentation()); } - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(namedOneOf("performRequestAsync", "performRequestAsyncNoCatch")) - .and(takesArguments(7)) - .and(takesArgument(0, named("java.lang.String"))) // method - .and(takesArgument(1, named("java.lang.String"))) // endpoint - .and(takesArgument(5, named("org.elasticsearch.client.ResponseListener"))), - Elasticsearch5RestClientInstrumentation.class.getName() + "$ElasticsearchRestClientAdvice"); + private static final class RestClientInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher typeMatcher() { + return named("org.elasticsearch.client.RestClient"); + } + + @Override + public Map, String> transformers() { + return singletonMap( + isMethod() + .and(namedOneOf("performRequestAsync", "performRequestAsyncNoCatch")) + .and(takesArguments(7)) + .and(takesArgument(0, named("java.lang.String"))) // method + .and(takesArgument(1, named("java.lang.String"))) // endpoint + .and(takesArgument(5, named("org.elasticsearch.client.ResponseListener"))), + Elasticsearch5RestClientInstrumentationModule.class.getName() + + "$ElasticsearchRestClientAdvice"); + } } public static class ElasticsearchRestClientAdvice { diff --git a/instrumentation/elasticsearch/elasticsearch-rest-6.4/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v6_4/Elasticsearch6RestClientInstrumentation.java b/instrumentation/elasticsearch/elasticsearch-rest-6.4/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v6_4/Elasticsearch6RestClientInstrumentationModule.java similarity index 65% rename from instrumentation/elasticsearch/elasticsearch-rest-6.4/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v6_4/Elasticsearch6RestClientInstrumentation.java rename to instrumentation/elasticsearch/elasticsearch-rest-6.4/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v6_4/Elasticsearch6RestClientInstrumentationModule.java index fe496b80ff..4d90e30d79 100644 --- a/instrumentation/elasticsearch/elasticsearch-rest-6.4/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v6_4/Elasticsearch6RestClientInstrumentation.java +++ b/instrumentation/elasticsearch/elasticsearch-rest-6.4/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v6_4/Elasticsearch6RestClientInstrumentationModule.java @@ -6,6 +6,7 @@ package io.opentelemetry.javaagent.instrumentation.elasticsearch.rest.v6_4; import static io.opentelemetry.javaagent.instrumentation.elasticsearch.rest.ElasticsearchRestClientTracer.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; @@ -15,7 +16,9 @@ import static net.bytebuddy.matcher.ElementMatchers.takesArguments; 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; @@ -24,10 +27,9 @@ import net.bytebuddy.matcher.ElementMatcher; import org.elasticsearch.client.Request; import org.elasticsearch.client.ResponseListener; -@AutoService(Instrumenter.class) -public class Elasticsearch6RestClientInstrumentation extends Instrumenter.Default { - - public Elasticsearch6RestClientInstrumentation() { +@AutoService(InstrumentationModule.class) +public class Elasticsearch6RestClientInstrumentationModule extends InstrumentationModule { + public Elasticsearch6RestClientInstrumentationModule() { super("elasticsearch", "elasticsearch-rest", "elasticsearch-rest-6"); } @@ -40,19 +42,27 @@ public class Elasticsearch6RestClientInstrumentation extends Instrumenter.Defaul } @Override - public ElementMatcher typeMatcher() { - return named("org.elasticsearch.client.RestClient"); + public List typeInstrumentations() { + return singletonList(new RestClientInstrumentation()); } - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(named("performRequestAsyncNoCatch")) - .and(takesArguments(2)) - .and(takesArgument(0, named("org.elasticsearch.client.Request"))) - .and(takesArgument(1, named("org.elasticsearch.client.ResponseListener"))), - Elasticsearch6RestClientInstrumentation.class.getName() + "$ElasticsearchRestClientAdvice"); + private static final class RestClientInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher typeMatcher() { + return named("org.elasticsearch.client.RestClient"); + } + + @Override + public Map, String> transformers() { + return singletonMap( + isMethod() + .and(named("performRequestAsyncNoCatch")) + .and(takesArguments(2)) + .and(takesArgument(0, named("org.elasticsearch.client.Request"))) + .and(takesArgument(1, named("org.elasticsearch.client.ResponseListener"))), + Elasticsearch6RestClientInstrumentationModule.class.getName() + + "$ElasticsearchRestClientAdvice"); + } } public static class ElasticsearchRestClientAdvice { diff --git a/instrumentation/elasticsearch/elasticsearch-transport-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v5_0/Elasticsearch5TransportClientInstrumentation.java b/instrumentation/elasticsearch/elasticsearch-transport-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v5_0/Elasticsearch5TransportClientInstrumentationModule.java similarity index 64% rename from instrumentation/elasticsearch/elasticsearch-transport-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v5_0/Elasticsearch5TransportClientInstrumentation.java rename to instrumentation/elasticsearch/elasticsearch-transport-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v5_0/Elasticsearch5TransportClientInstrumentationModule.java index 540c7bad08..dbb763b4bd 100644 --- a/instrumentation/elasticsearch/elasticsearch-transport-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v5_0/Elasticsearch5TransportClientInstrumentation.java +++ b/instrumentation/elasticsearch/elasticsearch-transport-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v5_0/Elasticsearch5TransportClientInstrumentationModule.java @@ -6,6 +6,7 @@ package io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.v5_0; import static io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.ElasticsearchTransportClientTracer.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; @@ -14,7 +15,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; @@ -25,20 +28,12 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionRequest; import org.elasticsearch.action.ActionResponse; -@AutoService(Instrumenter.class) -public class Elasticsearch5TransportClientInstrumentation extends Instrumenter.Default { - - public Elasticsearch5TransportClientInstrumentation() { +@AutoService(InstrumentationModule.class) +public class Elasticsearch5TransportClientInstrumentationModule extends InstrumentationModule { + public Elasticsearch5TransportClientInstrumentationModule() { super("elasticsearch", "elasticsearch-transport", "elasticsearch-transport-5"); } - @Override - public ElementMatcher typeMatcher() { - // If we want to be more generic, we could instrument the interface instead: - // .and(safeHasSuperType(named("org.elasticsearch.client.ElasticsearchClient")))) - return named("org.elasticsearch.client.support.AbstractClient"); - } - @Override public String[] helperClassNames() { return new String[] { @@ -53,15 +48,29 @@ public class Elasticsearch5TransportClientInstrumentation extends Instrumenter.D } @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(named("execute")) - .and(takesArgument(0, named("org.elasticsearch.action.Action"))) - .and(takesArgument(1, named("org.elasticsearch.action.ActionRequest"))) - .and(takesArgument(2, named("org.elasticsearch.action.ActionListener"))), - Elasticsearch5TransportClientInstrumentation.class.getName() - + "$ElasticsearchTransportClientAdvice"); + public List typeInstrumentations() { + return singletonList(new AbstractClientInstrumentation()); + } + + private static final class AbstractClientInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher typeMatcher() { + // If we want to be more generic, we could instrument the interface instead: + // .and(safeHasSuperType(named("org.elasticsearch.client.ElasticsearchClient")))) + return named("org.elasticsearch.client.support.AbstractClient"); + } + + @Override + public Map, String> transformers() { + return singletonMap( + isMethod() + .and(named("execute")) + .and(takesArgument(0, named("org.elasticsearch.action.Action"))) + .and(takesArgument(1, named("org.elasticsearch.action.ActionRequest"))) + .and(takesArgument(2, named("org.elasticsearch.action.ActionListener"))), + Elasticsearch5TransportClientInstrumentationModule.class.getName() + + "$ElasticsearchTransportClientAdvice"); + } } public static class ElasticsearchTransportClientAdvice { diff --git a/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v5_3/Elasticsearch53TransportClientInstrumentation.java b/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v5_3/Elasticsearch53TransportClientInstrumentationModule.java similarity index 64% rename from instrumentation/elasticsearch/elasticsearch-transport-5.3/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v5_3/Elasticsearch53TransportClientInstrumentation.java rename to instrumentation/elasticsearch/elasticsearch-transport-5.3/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v5_3/Elasticsearch53TransportClientInstrumentationModule.java index 5322a9b664..a7bcb18100 100644 --- a/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v5_3/Elasticsearch53TransportClientInstrumentation.java +++ b/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v5_3/Elasticsearch53TransportClientInstrumentationModule.java @@ -6,6 +6,7 @@ package io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.v5_3; import static io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.ElasticsearchTransportClientTracer.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; @@ -14,7 +15,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; @@ -26,20 +29,12 @@ import org.elasticsearch.action.ActionRequest; import org.elasticsearch.action.ActionResponse; /** Beginning in version 5.3.0, DocumentRequest was renamed to DocWriteRequest. */ -@AutoService(Instrumenter.class) -public class Elasticsearch53TransportClientInstrumentation extends Instrumenter.Default { - - public Elasticsearch53TransportClientInstrumentation() { +@AutoService(InstrumentationModule.class) +public class Elasticsearch53TransportClientInstrumentationModule extends InstrumentationModule { + public Elasticsearch53TransportClientInstrumentationModule() { super("elasticsearch", "elasticsearch-transport", "elasticsearch-transport-5"); } - @Override - public ElementMatcher typeMatcher() { - // If we want to be more generic, we could instrument the interface instead: - // .and(safeHasSuperType(named("org.elasticsearch.client.ElasticsearchClient")))) - return named("org.elasticsearch.client.support.AbstractClient"); - } - @Override public String[] helperClassNames() { return new String[] { @@ -54,15 +49,29 @@ public class Elasticsearch53TransportClientInstrumentation extends Instrumenter. } @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(named("execute")) - .and(takesArgument(0, named("org.elasticsearch.action.Action"))) - .and(takesArgument(1, named("org.elasticsearch.action.ActionRequest"))) - .and(takesArgument(2, named("org.elasticsearch.action.ActionListener"))), - Elasticsearch53TransportClientInstrumentation.class.getName() - + "$ElasticsearchTransportClientAdvice"); + public List typeInstrumentations() { + return singletonList(new AbstractClientInstrumentation()); + } + + private static final class AbstractClientInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher typeMatcher() { + // If we want to be more generic, we could instrument the interface instead: + // .and(safeHasSuperType(named("org.elasticsearch.client.ElasticsearchClient")))) + return named("org.elasticsearch.client.support.AbstractClient"); + } + + @Override + public Map, String> transformers() { + return singletonMap( + isMethod() + .and(named("execute")) + .and(takesArgument(0, named("org.elasticsearch.action.Action"))) + .and(takesArgument(1, named("org.elasticsearch.action.ActionRequest"))) + .and(takesArgument(2, named("org.elasticsearch.action.ActionListener"))), + Elasticsearch53TransportClientInstrumentationModule.class.getName() + + "$ElasticsearchTransportClientAdvice"); + } } public static class ElasticsearchTransportClientAdvice { diff --git a/instrumentation/elasticsearch/elasticsearch-transport-6.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v6_0/Elasticsearch6TransportClientInstrumentation.java b/instrumentation/elasticsearch/elasticsearch-transport-6.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v6_0/Elasticsearch6TransportClientInstrumentationModule.java similarity index 65% rename from instrumentation/elasticsearch/elasticsearch-transport-6.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v6_0/Elasticsearch6TransportClientInstrumentation.java rename to instrumentation/elasticsearch/elasticsearch-transport-6.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v6_0/Elasticsearch6TransportClientInstrumentationModule.java index e9dbc1cc71..86b7111713 100644 --- a/instrumentation/elasticsearch/elasticsearch-transport-6.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v6_0/Elasticsearch6TransportClientInstrumentation.java +++ b/instrumentation/elasticsearch/elasticsearch-transport-6.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v6_0/Elasticsearch6TransportClientInstrumentationModule.java @@ -6,6 +6,7 @@ package io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.v6_0; import static io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.ElasticsearchTransportClientTracer.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; @@ -14,7 +15,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; @@ -29,20 +32,12 @@ import org.elasticsearch.action.ActionResponse; * Most of this class is identical to version 5's instrumentation, but they changed an interface to * an abstract class, so the bytecode isn't directly compatible. */ -@AutoService(Instrumenter.class) -public class Elasticsearch6TransportClientInstrumentation extends Instrumenter.Default { - - public Elasticsearch6TransportClientInstrumentation() { +@AutoService(InstrumentationModule.class) +public class Elasticsearch6TransportClientInstrumentationModule extends InstrumentationModule { + public Elasticsearch6TransportClientInstrumentationModule() { super("elasticsearch", "elasticsearch-transport", "elasticsearch-transport-6"); } - @Override - public ElementMatcher typeMatcher() { - // If we want to be more generic, we could instrument the interface instead: - // .and(safeHasSuperType(named("org.elasticsearch.client.ElasticsearchClient")))) - return named("org.elasticsearch.client.support.AbstractClient"); - } - @Override public String[] helperClassNames() { return new String[] { @@ -57,15 +52,29 @@ public class Elasticsearch6TransportClientInstrumentation extends Instrumenter.D } @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(named("execute")) - .and(takesArgument(0, named("org.elasticsearch.action.Action"))) - .and(takesArgument(1, named("org.elasticsearch.action.ActionRequest"))) - .and(takesArgument(2, named("org.elasticsearch.action.ActionListener"))), - Elasticsearch6TransportClientInstrumentation.class.getName() - + "$Elasticsearch6TransportClientAdvice"); + public List typeInstrumentations() { + return singletonList(new AbstractClientInstrumentation()); + } + + private static final class AbstractClientInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher typeMatcher() { + // If we want to be more generic, we could instrument the interface instead: + // .and(safeHasSuperType(named("org.elasticsearch.client.ElasticsearchClient")))) + return named("org.elasticsearch.client.support.AbstractClient"); + } + + @Override + public Map, String> transformers() { + return singletonMap( + isMethod() + .and(named("execute")) + .and(takesArgument(0, named("org.elasticsearch.action.Action"))) + .and(takesArgument(1, named("org.elasticsearch.action.ActionRequest"))) + .and(takesArgument(2, named("org.elasticsearch.action.ActionListener"))), + Elasticsearch6TransportClientInstrumentationModule.class.getName() + + "$Elasticsearch6TransportClientAdvice"); + } } public static class Elasticsearch6TransportClientAdvice { diff --git a/instrumentation/external-annotations/src/main/java/io/opentelemetry/javaagent/instrumentation/traceannotation/AbstractTraceAnnotationInstrumentation.java b/instrumentation/external-annotations/src/main/java/io/opentelemetry/javaagent/instrumentation/traceannotation/AbstractTraceAnnotationInstrumentation.java deleted file mode 100644 index b7cc45704d..0000000000 --- a/instrumentation/external-annotations/src/main/java/io/opentelemetry/javaagent/instrumentation/traceannotation/AbstractTraceAnnotationInstrumentation.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.traceannotation; - -import static net.bytebuddy.matcher.ElementMatchers.isDeclaredBy; -import static net.bytebuddy.matcher.ElementMatchers.none; - -import io.opentelemetry.instrumentation.api.config.Config; -import io.opentelemetry.instrumentation.api.config.MethodsConfigurationParser; -import io.opentelemetry.javaagent.tooling.Instrumenter; -import java.util.Map; -import java.util.Set; -import net.bytebuddy.description.ByteCodeElement; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import net.bytebuddy.matcher.ElementMatchers; - -public abstract class AbstractTraceAnnotationInstrumentation extends Instrumenter.Default { - private static final String TRACE_ANNOTATED_METHODS_EXCLUDE_CONFIG = - "otel.trace.annotated.methods.exclude"; - - public AbstractTraceAnnotationInstrumentation( - String instrumentationName, String... additionalNames) { - super(instrumentationName, additionalNames); - } - - /* - Returns a matcher for all methods that should be excluded from auto-instrumentation by - annotation-based advices. - */ - ElementMatcher.Junction configureExcludedMethods() { - ElementMatcher.Junction result = none(); - - Map> excludedMethods = - MethodsConfigurationParser.parse( - Config.get().getProperty(TRACE_ANNOTATED_METHODS_EXCLUDE_CONFIG)); - for (Map.Entry> entry : excludedMethods.entrySet()) { - String className = entry.getKey(); - ElementMatcher.Junction classMather = - isDeclaredBy(ElementMatchers.named(className)); - - ElementMatcher.Junction excludedMethodsMatcher = none(); - for (String methodName : entry.getValue()) { - excludedMethodsMatcher = excludedMethodsMatcher.or(ElementMatchers.named(methodName)); - } - - result = result.or(classMather.and(excludedMethodsMatcher)); - } - - return result; - } -} diff --git a/instrumentation/external-annotations/src/main/java/io/opentelemetry/javaagent/instrumentation/traceannotation/TraceAnnotationsInstrumentation.java b/instrumentation/external-annotations/src/main/java/io/opentelemetry/javaagent/instrumentation/traceannotation/TraceAnnotationsInstrumentation.java deleted file mode 100644 index 2151485796..0000000000 --- a/instrumentation/external-annotations/src/main/java/io/opentelemetry/javaagent/instrumentation/traceannotation/TraceAnnotationsInstrumentation.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.traceannotation; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.safeHasSuperType; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.declaresMethod; -import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.none; -import static net.bytebuddy.matcher.ElementMatchers.not; - -import com.google.auto.service.AutoService; -import com.google.common.collect.Sets; -import io.opentelemetry.instrumentation.api.config.Config; -import io.opentelemetry.javaagent.tooling.Instrumenter; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import net.bytebuddy.description.NamedElement; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@AutoService(Instrumenter.class) -public final class TraceAnnotationsInstrumentation extends AbstractTraceAnnotationInstrumentation { - - private static final Logger log = LoggerFactory.getLogger(TraceAnnotationsInstrumentation.class); - - private static final String TRACE_ANNOTATIONS_CONFIG = "otel.trace.annotations"; - - private static final String PACKAGE_CLASS_NAME_REGEX = "[\\w.$]+"; - - static final String CONFIG_FORMAT = - "(?:\\s*" - + PACKAGE_CLASS_NAME_REGEX - + "\\s*;)*\\s*" - + PACKAGE_CLASS_NAME_REGEX - + "\\s*;?\\s*"; - - private static final String[] DEFAULT_ANNOTATIONS = - new String[] { - "com.appoptics.api.ext.LogMethod", - "com.newrelic.api.agent.Trace", - "com.signalfx.tracing.api.Trace", - "com.tracelytics.api.ext.LogMethod", - "datadog.trace.api.Trace", - "io.opentracing.contrib.dropwizard.Trace", - "kamon.annotation.Trace", - "kamon.annotation.api.Trace", - "org.springframework.cloud.sleuth.annotation.NewSpan" - }; - - private final Set additionalTraceAnnotations; - private final ElementMatcher.Junction traceAnnotationMatcher; - /* - This matcher matches all methods that should be excluded from transformation - */ - private final ElementMatcher.Junction excludedMethodsMatcher; - - public TraceAnnotationsInstrumentation() { - super("trace", "trace-annotation"); - - String configString = Config.get().getProperty(TRACE_ANNOTATIONS_CONFIG); - if (configString == null) { - additionalTraceAnnotations = - Collections.unmodifiableSet(Sets.newHashSet(DEFAULT_ANNOTATIONS)); - } else if (configString.isEmpty()) { - additionalTraceAnnotations = Collections.emptySet(); - } else if (!configString.matches(CONFIG_FORMAT)) { - log.warn( - "Invalid trace annotations config '{}'. Must match 'package.Annotation$Name;*'.", - configString); - additionalTraceAnnotations = Collections.emptySet(); - } else { - Set annotations = Sets.newHashSet(); - String[] annotationClasses = configString.split(";", -1); - for (String annotationClass : annotationClasses) { - if (!annotationClass.trim().isEmpty()) { - annotations.add(annotationClass.trim()); - } - } - additionalTraceAnnotations = Collections.unmodifiableSet(annotations); - } - - if (additionalTraceAnnotations.isEmpty()) { - traceAnnotationMatcher = none(); - } else { - ElementMatcher.Junction methodTraceMatcher = null; - for (String annotationName : additionalTraceAnnotations) { - if (methodTraceMatcher == null) { - methodTraceMatcher = named(annotationName); - } else { - methodTraceMatcher = methodTraceMatcher.or(named(annotationName)); - } - } - this.traceAnnotationMatcher = methodTraceMatcher; - } - - excludedMethodsMatcher = configureExcludedMethods(); - } - - @Override - public ElementMatcher classLoaderMatcher() { - // Optimization for expensive typeMatcher. - ElementMatcher.Junction matcher = null; - for (String name : additionalTraceAnnotations) { - if (matcher == null) { - matcher = hasClassesNamed(name); - } else { - matcher = matcher.or(hasClassesNamed(name)); - } - } - if (matcher == null) { - return none(); - } - return matcher; - } - - @Override - public ElementMatcher typeMatcher() { - return safeHasSuperType(declaresMethod(isAnnotatedWith(traceAnnotationMatcher))); - } - - @Override - public String[] helperClassNames() { - return new String[] { - packageName + ".TraceAnnotationTracer", - }; - } - - @Override - public Map, String> transformers() { - return singletonMap( - isAnnotatedWith(traceAnnotationMatcher).and(not(excludedMethodsMatcher)), - packageName + ".TraceAdvice"); - } -} diff --git a/instrumentation/external-annotations/src/main/java/io/opentelemetry/javaagent/instrumentation/traceannotation/TraceAnnotationsInstrumentationModule.java b/instrumentation/external-annotations/src/main/java/io/opentelemetry/javaagent/instrumentation/traceannotation/TraceAnnotationsInstrumentationModule.java new file mode 100644 index 0000000000..da506febe1 --- /dev/null +++ b/instrumentation/external-annotations/src/main/java/io/opentelemetry/javaagent/instrumentation/traceannotation/TraceAnnotationsInstrumentationModule.java @@ -0,0 +1,189 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.traceannotation; + +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.declaresMethod; +import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith; +import static net.bytebuddy.matcher.ElementMatchers.isDeclaredBy; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.none; +import static net.bytebuddy.matcher.ElementMatchers.not; + +import com.google.auto.service.AutoService; +import com.google.common.collect.Sets; +import io.opentelemetry.instrumentation.api.config.Config; +import io.opentelemetry.instrumentation.api.config.MethodsConfigurationParser; +import io.opentelemetry.javaagent.tooling.InstrumentationModule; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import net.bytebuddy.description.ByteCodeElement; +import net.bytebuddy.description.NamedElement; +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; +import net.bytebuddy.matcher.ElementMatchers; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@AutoService(InstrumentationModule.class) +public final class TraceAnnotationsInstrumentationModule extends InstrumentationModule { + private static final Logger log = + LoggerFactory.getLogger(TraceAnnotationsInstrumentationModule.class); + + private static final String PACKAGE_CLASS_NAME_REGEX = "[\\w.$]+"; + + static final String CONFIG_FORMAT = + "(?:\\s*" + + PACKAGE_CLASS_NAME_REGEX + + "\\s*;)*\\s*" + + PACKAGE_CLASS_NAME_REGEX + + "\\s*;?\\s*"; + + private static final String[] DEFAULT_ANNOTATIONS = + new String[] { + "com.appoptics.api.ext.LogMethod", + "com.newrelic.api.agent.Trace", + "com.signalfx.tracing.api.Trace", + "com.tracelytics.api.ext.LogMethod", + "datadog.trace.api.Trace", + "io.opentracing.contrib.dropwizard.Trace", + "kamon.annotation.Trace", + "kamon.annotation.api.Trace", + "org.springframework.cloud.sleuth.annotation.NewSpan" + }; + + private static final String TRACE_ANNOTATIONS_CONFIG = "otel.trace.annotations"; + private static final String TRACE_ANNOTATED_METHODS_EXCLUDE_CONFIG = + "otel.trace.annotated.methods.exclude"; + + public TraceAnnotationsInstrumentationModule() { + super("trace", "trace-annotation"); + } + + @Override + public String[] helperClassNames() { + return new String[] { + packageName + ".TraceAnnotationTracer", + }; + } + + @Override + public List typeInstrumentations() { + return singletonList(new AnnotatedMethodsInstrumentation()); + } + + private static final class AnnotatedMethodsInstrumentation implements TypeInstrumentation { + private final Set additionalTraceAnnotations; + private final ElementMatcher.Junction traceAnnotationMatcher; + /** This matcher matches all methods that should be excluded from transformation. */ + private final ElementMatcher.Junction excludedMethodsMatcher; + + public AnnotatedMethodsInstrumentation() { + additionalTraceAnnotations = configureAdditionalTraceAnnotations(); + + if (additionalTraceAnnotations.isEmpty()) { + traceAnnotationMatcher = none(); + } else { + ElementMatcher.Junction methodTraceMatcher = null; + for (String annotationName : additionalTraceAnnotations) { + if (methodTraceMatcher == null) { + methodTraceMatcher = named(annotationName); + } else { + methodTraceMatcher = methodTraceMatcher.or(named(annotationName)); + } + } + this.traceAnnotationMatcher = methodTraceMatcher; + } + + excludedMethodsMatcher = configureExcludedMethods(); + } + + @Override + public ElementMatcher classLoaderMatcher() { + // Optimization for expensive typeMatcher. + ElementMatcher.Junction matcher = null; + for (String name : additionalTraceAnnotations) { + if (matcher == null) { + matcher = hasClassesNamed(name); + } else { + matcher = matcher.or(hasClassesNamed(name)); + } + } + if (matcher == null) { + return none(); + } + return matcher; + } + + @Override + public ElementMatcher typeMatcher() { + return safeHasSuperType(declaresMethod(isAnnotatedWith(traceAnnotationMatcher))); + } + + @Override + public Map, String> transformers() { + return singletonMap( + isAnnotatedWith(traceAnnotationMatcher).and(not(excludedMethodsMatcher)), + TraceAdvice.class.getName()); + } + + private static Set configureAdditionalTraceAnnotations() { + String configString = Config.get().getProperty(TRACE_ANNOTATIONS_CONFIG); + if (configString == null) { + return Collections.unmodifiableSet(Sets.newHashSet(DEFAULT_ANNOTATIONS)); + } else if (configString.isEmpty()) { + return Collections.emptySet(); + } else if (!configString.matches(CONFIG_FORMAT)) { + log.warn( + "Invalid trace annotations config '{}'. Must match 'package.Annotation$Name;*'.", + configString); + return Collections.emptySet(); + } else { + Set annotations = Sets.newHashSet(); + String[] annotationClasses = configString.split(";", -1); + for (String annotationClass : annotationClasses) { + if (!annotationClass.trim().isEmpty()) { + annotations.add(annotationClass.trim()); + } + } + return Collections.unmodifiableSet(annotations); + } + } + + /** + * Returns a matcher for all methods that should be excluded from auto-instrumentation by + * annotation-based advices. + */ + private static ElementMatcher.Junction configureExcludedMethods() { + ElementMatcher.Junction result = none(); + + Map> excludedMethods = + MethodsConfigurationParser.parse( + Config.get().getProperty(TRACE_ANNOTATED_METHODS_EXCLUDE_CONFIG)); + for (Map.Entry> entry : excludedMethods.entrySet()) { + String className = entry.getKey(); + ElementMatcher.Junction classMather = + isDeclaredBy(ElementMatchers.named(className)); + + ElementMatcher.Junction excludedMethodsMatcher = none(); + for (String methodName : entry.getValue()) { + excludedMethodsMatcher = excludedMethodsMatcher.or(ElementMatchers.named(methodName)); + } + + result = result.or(classMather.and(excludedMethodsMatcher)); + } + + return result; + } + } +} diff --git a/instrumentation/external-annotations/src/main/java/io/opentelemetry/javaagent/instrumentation/traceannotation/TraceConfigInstrumentation.java b/instrumentation/external-annotations/src/main/java/io/opentelemetry/javaagent/instrumentation/traceannotation/TraceConfigInstrumentationModule.java similarity index 66% rename from instrumentation/external-annotations/src/main/java/io/opentelemetry/javaagent/instrumentation/traceannotation/TraceConfigInstrumentation.java rename to instrumentation/external-annotations/src/main/java/io/opentelemetry/javaagent/instrumentation/traceannotation/TraceConfigInstrumentationModule.java index 99ffecbf06..6507d97788 100644 --- a/instrumentation/external-annotations/src/main/java/io/opentelemetry/javaagent/instrumentation/traceannotation/TraceConfigInstrumentation.java +++ b/instrumentation/external-annotations/src/main/java/io/opentelemetry/javaagent/instrumentation/traceannotation/TraceConfigInstrumentationModule.java @@ -12,11 +12,13 @@ import static net.bytebuddy.matcher.ElementMatchers.named; import com.google.auto.service.AutoService; import io.opentelemetry.instrumentation.api.config.Config; import io.opentelemetry.instrumentation.api.config.MethodsConfigurationParser; -import io.opentelemetry.javaagent.tooling.Instrumenter; +import io.opentelemetry.javaagent.tooling.InstrumentationModule; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.Set; -import net.bytebuddy.agent.builder.AgentBuilder; +import java.util.stream.Collectors; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; @@ -30,17 +32,19 @@ import net.bytebuddy.matcher.ElementMatcher; *

If this becomes a more common use case the building logic should be abstracted out into a * super class. */ -@AutoService(Instrumenter.class) -public class TraceConfigInstrumentation implements Instrumenter { +@AutoService(InstrumentationModule.class) +public class TraceConfigInstrumentationModule extends InstrumentationModule { private static final String TRACE_METHODS_CONFIG = "otel.trace.methods"; private static final String TRACE_ANNOTATED_METHODS_EXCLUDE_CONFIG = "otel.trace.annotated.methods.exclude"; - private final Map> classMethodsToTrace; + private final List typeInstrumentations; - public TraceConfigInstrumentation() { - classMethodsToTrace = + public TraceConfigInstrumentationModule() { + super("trace", "trace-config"); + + Map> classMethodsToTrace = MethodsConfigurationParser.parse(Config.get().getProperty(TRACE_METHODS_CONFIG)); Map> excludedMethods = @@ -52,39 +56,31 @@ public class TraceConfigInstrumentation implements Instrumenter { tracedMethods.removeAll(entry.getValue()); } } + + typeInstrumentations = + classMethodsToTrace.entrySet().stream() + .filter(e -> !e.getValue().isEmpty()) + .map(e -> new TracerClassInstrumentation(e.getKey(), e.getValue())) + .collect(Collectors.toList()); } @Override - public AgentBuilder instrument(AgentBuilder agentBuilder) { - if (classMethodsToTrace.isEmpty()) { - return agentBuilder; - } - - for (Map.Entry> entry : classMethodsToTrace.entrySet()) { - TracerClassInstrumentation tracerConfigClass = - new TracerClassInstrumentation(entry.getKey(), entry.getValue()); - agentBuilder = tracerConfigClass.instrument(agentBuilder); - } - return agentBuilder; + public String[] helperClassNames() { + return new String[] { + packageName + ".TraceAnnotationTracer", + }; } @Override - public int getOrder() { - return 0; + public List typeInstrumentations() { + return typeInstrumentations; } - // Not Using AutoService to hook up this instrumentation - public static class TracerClassInstrumentation extends Default { + private static final class TracerClassInstrumentation implements TypeInstrumentation { private final String className; private final Set methodNames; - /** No-arg constructor only used by muzzle and tests. */ - public TracerClassInstrumentation() { - this("io.opentracing.contrib.dropwizard.Trace", Collections.singleton("noop")); - } - public TracerClassInstrumentation(String className, Set methodNames) { - super("trace", "trace-config"); this.className = className; this.methodNames = methodNames; } @@ -100,13 +96,6 @@ public class TraceConfigInstrumentation implements Instrumenter { return safeHasSuperType(named(className)); } - @Override - public String[] helperClassNames() { - return new String[] { - packageName + ".TraceAnnotationTracer", - }; - } - @Override public Map, String> transformers() { ElementMatcher.Junction methodMatchers = null; @@ -118,8 +107,7 @@ public class TraceConfigInstrumentation implements Instrumenter { } } - return Collections., String>singletonMap( - methodMatchers, packageName + ".TraceAdvice"); + return Collections.singletonMap(methodMatchers, TraceAdvice.class.getName()); } } } diff --git a/instrumentation/external-annotations/src/test/groovy/ConfiguredTraceAnnotationsTest.groovy b/instrumentation/external-annotations/src/test/groovy/ConfiguredTraceAnnotationsTest.groovy index 9b4e89726c..8023ea4825 100644 --- a/instrumentation/external-annotations/src/test/groovy/ConfiguredTraceAnnotationsTest.groovy +++ b/instrumentation/external-annotations/src/test/groovy/ConfiguredTraceAnnotationsTest.groovy @@ -3,11 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -import static io.opentelemetry.javaagent.instrumentation.traceannotation.TraceAnnotationsInstrumentation.DEFAULT_ANNOTATIONS +import static io.opentelemetry.javaagent.instrumentation.traceannotation.TraceAnnotationsInstrumentationModule.DEFAULT_ANNOTATIONS import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.instrumentation.test.utils.ConfigUtils -import io.opentelemetry.javaagent.instrumentation.traceannotation.TraceAnnotationsInstrumentation +import io.opentelemetry.javaagent.instrumentation.traceannotation.TraceAnnotationsInstrumentationModule import io.opentelemetry.test.annotation.SayTracedHello import java.util.concurrent.Callable @@ -55,7 +55,7 @@ class ConfiguredTraceAnnotationsTest extends AgentTestRunner { } expect: - new TraceAnnotationsInstrumentation().additionalTraceAnnotations == expected.toSet() + new TraceAnnotationsInstrumentationModule.AnnotatedMethodsInstrumentation().additionalTraceAnnotations == expected.toSet() cleanup: ConfigUtils.setConfig(previousConfig) diff --git a/instrumentation/external-annotations/src/test/groovy/TraceProvidersTest.groovy b/instrumentation/external-annotations/src/test/groovy/TraceProvidersTest.groovy index 65e8c11a21..e1976e29cf 100644 --- a/instrumentation/external-annotations/src/test/groovy/TraceProvidersTest.groovy +++ b/instrumentation/external-annotations/src/test/groovy/TraceProvidersTest.groovy @@ -13,6 +13,7 @@ import io.opentelemetry.test.annotation.SayTracedHello class TraceProvidersTest extends AgentTestRunner { //Don't bother to instrument inner closures of this test class static final PREVIOUS_CONFIG = ConfigUtils.updateConfigAndResetInstrumentation { + it.remove("otel.trace.annotations") it.setProperty("otel.trace.classes.exclude", TraceProvidersTest.name + "*") } diff --git a/instrumentation/finatra-2.9/src/main/java/io/opentelemetry/javaagent/instrumentation/finatra/FinatraInstrumentation.java b/instrumentation/finatra-2.9/src/main/java/io/opentelemetry/javaagent/instrumentation/finatra/FinatraInstrumentationModule.java similarity index 67% rename from instrumentation/finatra-2.9/src/main/java/io/opentelemetry/javaagent/instrumentation/finatra/FinatraInstrumentation.java rename to instrumentation/finatra-2.9/src/main/java/io/opentelemetry/javaagent/instrumentation/finatra/FinatraInstrumentationModule.java index 2ba4f53f63..8b9fbdac38 100644 --- a/instrumentation/finatra-2.9/src/main/java/io/opentelemetry/javaagent/instrumentation/finatra/FinatraInstrumentation.java +++ b/instrumentation/finatra-2.9/src/main/java/io/opentelemetry/javaagent/instrumentation/finatra/FinatraInstrumentationModule.java @@ -8,6 +8,7 @@ package io.opentelemetry.javaagent.instrumentation.finatra; import static io.opentelemetry.javaagent.instrumentation.finatra.FinatraTracer.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.isMethod; import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; @@ -23,7 +24,9 @@ import com.twitter.util.FutureEventListener; import io.opentelemetry.api.trace.Span; import io.opentelemetry.instrumentation.api.tracer.BaseTracer; import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -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,47 +34,54 @@ import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; import scala.Some; -@AutoService(Instrumenter.class) -public class FinatraInstrumentation extends Instrumenter.Default { - public FinatraInstrumentation() { +@AutoService(InstrumentationModule.class) +public class FinatraInstrumentationModule extends InstrumentationModule { + public FinatraInstrumentationModule() { super("finatra"); } @Override public String[] helperClassNames() { return new String[] { - packageName + ".FinatraTracer", FinatraInstrumentation.class.getName() + "$Listener" + packageName + ".FinatraTracer", FinatraInstrumentationModule.class.getName() + "$Listener" }; } @Override - public ElementMatcher classLoaderMatcher() { - // Optimization for expensive typeMatcher. - return hasClassesNamed("com.twitter.finatra.http.internal.routing.Route"); + public List typeInstrumentations() { + return singletonList(new RouteInstrumentation()); } - @Override - public ElementMatcher typeMatcher() { - return nameStartsWith("com.twitter.finatra.") - .and( - extendsClass(named("com.twitter.finatra.http.internal.routing.Route"))); - } + private static final class RouteInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher classLoaderMatcher() { + // Optimization for expensive typeMatcher. + return hasClassesNamed("com.twitter.finatra.http.internal.routing.Route"); + } - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(named("handleMatch")) - .and(takesArguments(2)) - .and(takesArgument(0, named("com.twitter.finagle.http.Request"))), - FinatraInstrumentation.class.getName() + "$RouteAdvice"); + @Override + public ElementMatcher typeMatcher() { + return nameStartsWith("com.twitter.finatra.") + .and( + extendsClass(named("com.twitter.finatra.http.internal.routing.Route"))); + } + + @Override + public Map, String> transformers() { + return singletonMap( + isMethod() + .and(named("handleMatch")) + .and(takesArguments(2)) + .and(takesArgument(0, named("com.twitter.finagle.http.Request"))), + FinatraInstrumentationModule.class.getName() + "$RouteAdvice"); + } } public static class RouteAdvice { @Advice.OnMethodEnter(suppress = Throwable.class) public static SpanWithScope nameSpan( @Advice.FieldValue("routeInfo") RouteInfo routeInfo, - @Advice.FieldValue("clazz") Class clazz) { + @Advice.FieldValue("clazz") Class clazz) { Span serverSpan = BaseTracer.getCurrentServerSpan(); if (serverSpan != null) { diff --git a/instrumentation/geode-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeInstrumentation.java b/instrumentation/geode-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeInstrumentationModule.java similarity index 61% rename from instrumentation/geode-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeInstrumentation.java rename to instrumentation/geode-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeInstrumentationModule.java index a4a5ec2edf..834b69bd2b 100644 --- a/instrumentation/geode-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeInstrumentation.java +++ b/instrumentation/geode-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeInstrumentationModule.java @@ -6,7 +6,9 @@ package io.opentelemetry.javaagent.instrumentation.geode; import static io.opentelemetry.javaagent.instrumentation.geode.GeodeTracer.tracer; +import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.hasInterface; +import static java.util.Collections.singletonList; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; import static net.bytebuddy.matcher.ElementMatchers.named; @@ -16,9 +18,11 @@ import com.google.auto.service.AutoService; import io.opentelemetry.api.trace.Span; 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.util.HashMap; +import java.util.List; import java.util.Map; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; @@ -26,17 +30,12 @@ import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; import org.apache.geode.cache.Region; -@AutoService(Instrumenter.class) -public class GeodeInstrumentation extends Instrumenter.Default { - public GeodeInstrumentation() { +@AutoService(InstrumentationModule.class) +public class GeodeInstrumentationModule extends InstrumentationModule { + public GeodeInstrumentationModule() { super("geode", "geode-client"); } - @Override - public ElementMatcher typeMatcher() { - return hasInterface(named("org.apache.geode.cache.Region")); - } - @Override public String[] helperClassNames() { return new String[] { @@ -45,30 +44,48 @@ public class GeodeInstrumentation extends Instrumenter.Default { } @Override - public Map, String> transformers() { - Map, String> map = new HashMap<>(2); - map.put( - isMethod() - .and( - named("clear") - .or(nameStartsWith("contains")) - .or(named("create")) - .or(named("destroy")) - .or(named("entrySet")) - .or(named("get")) - .or(named("getAll")) - .or(named("invalidate")) - .or(nameStartsWith("keySet")) - .or(nameStartsWith("put")) - .or(nameStartsWith("remove")) - .or(named("replace"))), - GeodeInstrumentation.class.getName() + "$SimpleAdvice"); - map.put( - isMethod() - .and(named("existsValue").or(named("query")).or(named("selectValue"))) - .and(takesArgument(0, named("java.lang.String"))), - GeodeInstrumentation.class.getName() + "$QueryAdvice"); - return map; + public List typeInstrumentations() { + return singletonList(new RegionInstrumentation()); + } + + private static final class RegionInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher classLoaderMatcher() { + // optimization for expensive typeMatcher + return hasClassesNamed("org.apache.geode.cache.Region"); + } + + @Override + public ElementMatcher typeMatcher() { + return hasInterface(named("org.apache.geode.cache.Region")); + } + + @Override + public Map, String> transformers() { + Map, String> map = new HashMap<>(2); + map.put( + isMethod() + .and( + named("clear") + .or(nameStartsWith("contains")) + .or(named("create")) + .or(named("destroy")) + .or(named("entrySet")) + .or(named("get")) + .or(named("getAll")) + .or(named("invalidate")) + .or(nameStartsWith("keySet")) + .or(nameStartsWith("put")) + .or(nameStartsWith("remove")) + .or(named("replace"))), + GeodeInstrumentationModule.class.getName() + "$SimpleAdvice"); + map.put( + isMethod() + .and(named("existsValue").or(named("query")).or(named("selectValue"))) + .and(takesArgument(0, named("java.lang.String"))), + GeodeInstrumentationModule.class.getName() + "$QueryAdvice"); + return map; + } } public static class SimpleAdvice { diff --git a/instrumentation/google-http-client-1.19/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/GoogleHttpClientInstrumentation.java b/instrumentation/google-http-client-1.19/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/GoogleHttpClientInstrumentationModule.java similarity index 73% rename from instrumentation/google-http-client-1.19/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/GoogleHttpClientInstrumentation.java rename to instrumentation/google-http-client-1.19/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/GoogleHttpClientInstrumentationModule.java index 9977aa0a02..f6fc6ccd34 100644 --- a/instrumentation/google-http-client-1.19/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/GoogleHttpClientInstrumentation.java +++ b/instrumentation/google-http-client-1.19/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/GoogleHttpClientInstrumentationModule.java @@ -6,6 +6,7 @@ package io.opentelemetry.javaagent.instrumentation.googlehttpclient; import static io.opentelemetry.javaagent.instrumentation.googlehttpclient.GoogleHttpClientTracer.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.isPublic; @@ -23,28 +24,22 @@ 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.Java8BytecodeBridge; -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; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; -@AutoService(Instrumenter.class) -public class GoogleHttpClientInstrumentation extends Instrumenter.Default { - public GoogleHttpClientInstrumentation() { +@AutoService(InstrumentationModule.class) +public class GoogleHttpClientInstrumentationModule extends InstrumentationModule { + public GoogleHttpClientInstrumentationModule() { super("google-http-client"); } - @Override - public ElementMatcher typeMatcher() { - // HttpRequest is a final class. Only need to instrument it exactly - // Note: the rest of com.google.api is ignored in AdditionalLibraryIgnoresMatcher to speed - // things up - return named("com.google.api.client.http.HttpRequest"); - } - @Override public Map contextStore() { return singletonMap("com.google.api.client.http.HttpRequest", Context.class.getName()); @@ -58,21 +53,36 @@ public class GoogleHttpClientInstrumentation extends Instrumenter.Default { } @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - transformers.put( - isMethod().and(isPublic()).and(named("execute")).and(takesArguments(0)), - GoogleHttpClientInstrumentation.class.getName() + "$GoogleHttpClientAdvice"); + public List typeInstrumentations() { + return singletonList(new HttpRequestInstrumentation()); + } - transformers.put( - isMethod() - .and(isPublic()) - .and(named("executeAsync")) - .and(takesArguments(1)) - .and(takesArgument(0, (named("java.util.concurrent.Executor")))), - GoogleHttpClientInstrumentation.class.getName() + "$GoogleHttpClientAsyncAdvice"); + private static final class HttpRequestInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher typeMatcher() { + // HttpRequest is a final class. Only need to instrument it exactly + // Note: the rest of com.google.api is ignored in AdditionalLibraryIgnoresMatcher to speed + // things up + return named("com.google.api.client.http.HttpRequest"); + } - return transformers; + @Override + public Map, String> transformers() { + Map, String> transformers = new HashMap<>(); + transformers.put( + isMethod().and(isPublic()).and(named("execute")).and(takesArguments(0)), + GoogleHttpClientInstrumentationModule.class.getName() + "$GoogleHttpClientAdvice"); + + transformers.put( + isMethod() + .and(isPublic()) + .and(named("executeAsync")) + .and(takesArguments(1)) + .and(takesArgument(0, (named("java.util.concurrent.Executor")))), + GoogleHttpClientInstrumentationModule.class.getName() + "$GoogleHttpClientAsyncAdvice"); + + return transformers; + } } public static class GoogleHttpClientAdvice { diff --git a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/DefaultFilterChainInstrumentation.java b/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/DefaultFilterChainInstrumentation.java index 01135e4b30..16713099d1 100644 --- a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/DefaultFilterChainInstrumentation.java +++ b/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/DefaultFilterChainInstrumentation.java @@ -10,36 +10,20 @@ import static net.bytebuddy.matcher.ElementMatchers.isPrivate; 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.Collections; 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 DefaultFilterChainInstrumentation extends Instrumenter.Default { - - public DefaultFilterChainInstrumentation() { - super("grizzly"); - } +final class DefaultFilterChainInstrumentation implements TypeInstrumentation { @Override public ElementMatcher typeMatcher() { return named("org.glassfish.grizzly.filterchain.DefaultFilterChain"); } - @Override - public String[] helperClassNames() { - return new String[] {packageName + ".GrizzlyHttpServerTracer", packageName + ".ExtractAdapter"}; - } - - @Override - protected boolean defaultEnabled() { - return false; - } - @Override public Map, String> transformers() { return Collections.singletonMap( @@ -48,6 +32,6 @@ public class DefaultFilterChainInstrumentation extends Instrumenter.Default { .and(named("notifyFailure")) .and(takesArgument(0, named("org.glassfish.grizzly.filterchain.FilterChainContext"))) .and(takesArgument(1, named("java.lang.Throwable"))), - packageName + ".DefaultFilterChainAdvice"); + DefaultFilterChainAdvice.class.getName()); } } diff --git a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/FilterInstrumentation.java b/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/FilterInstrumentation.java index fa3e1fa0e8..99c6867fa2 100644 --- a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/FilterInstrumentation.java +++ b/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/FilterInstrumentation.java @@ -13,20 +13,14 @@ 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; import net.bytebuddy.matcher.ElementMatchers; -@AutoService(Instrumenter.class) -public final class FilterInstrumentation extends Instrumenter.Default { - - public FilterInstrumentation() { - super("grizzly"); - } +final class FilterInstrumentation implements TypeInstrumentation { @Override public ElementMatcher classLoaderMatcher() { @@ -47,22 +41,12 @@ public final class FilterInstrumentation extends Instrumenter.Default { "org.glassfish.grizzly.http.HttpServerFilter"))); } - @Override - public String[] helperClassNames() { - return new String[] {packageName + ".GrizzlyHttpServerTracer", packageName + ".ExtractAdapter"}; - } - - @Override - protected boolean defaultEnabled() { - return false; - } - @Override public Map, String> transformers() { return singletonMap( named("handleRead") .and(takesArgument(0, named("org.glassfish.grizzly.filterchain.FilterChainContext"))) .and(isPublic()), - packageName + ".FilterAdvice"); + FilterAdvice.class.getName()); } } diff --git a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/GrizzlyInstrumentationModule.java b/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/GrizzlyInstrumentationModule.java new file mode 100644 index 0000000000..8294514dd6 --- /dev/null +++ b/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/GrizzlyInstrumentationModule.java @@ -0,0 +1,39 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.grizzly; + +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 GrizzlyInstrumentationModule extends InstrumentationModule { + public GrizzlyInstrumentationModule() { + super("grizzly"); + } + + @Override + public String[] helperClassNames() { + return new String[] {packageName + ".GrizzlyHttpServerTracer", packageName + ".ExtractAdapter"}; + } + + @Override + public List typeInstrumentations() { + return asList( + new DefaultFilterChainInstrumentation(), + new FilterInstrumentation(), + new HttpCodecFilterInstrumentation(), + new HttpServerFilterInstrumentation()); + } + + @Override + protected boolean defaultEnabled() { + return false; + } +} diff --git a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/HttpCodecFilterInstrumentation.java b/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/HttpCodecFilterInstrumentation.java index 54a526a3a0..1bf711ea2f 100644 --- a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/HttpCodecFilterInstrumentation.java +++ b/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/HttpCodecFilterInstrumentation.java @@ -9,36 +9,20 @@ 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.HashMap; 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 HttpCodecFilterInstrumentation extends Instrumenter.Default { - - public HttpCodecFilterInstrumentation() { - super("grizzly"); - } +final class HttpCodecFilterInstrumentation implements TypeInstrumentation { @Override public ElementMatcher typeMatcher() { return named("org.glassfish.grizzly.http.HttpCodecFilter"); } - @Override - protected boolean defaultEnabled() { - return false; - } - - @Override - public String[] helperClassNames() { - return new String[] {packageName + ".GrizzlyHttpServerTracer", packageName + ".ExtractAdapter"}; - } - @Override public Map, String> transformers() { Map, String> transformers = new HashMap<>(); @@ -48,14 +32,14 @@ public final class HttpCodecFilterInstrumentation extends Instrumenter.Default { .and(takesArgument(0, named("org.glassfish.grizzly.filterchain.FilterChainContext"))) .and(takesArgument(1, named("org.glassfish.grizzly.http.HttpPacketParsing"))) .and(isPublic()), - packageName + ".HttpCodecFilterOldAdvice"); + HttpCodecFilterOldAdvice.class.getName()); // this is for 2.3.20+ transformers.put( named("handleRead") .and(takesArgument(0, named("org.glassfish.grizzly.filterchain.FilterChainContext"))) .and(takesArgument(1, named("org.glassfish.grizzly.http.HttpHeader"))) .and(isPublic()), - packageName + ".HttpCodecFilterAdvice"); + HttpCodecFilterAdvice.class.getName()); return transformers; } } diff --git a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/HttpServerFilterInstrumentation.java b/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/HttpServerFilterInstrumentation.java index 9ef0564e28..8d71e4f34d 100644 --- a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/HttpServerFilterInstrumentation.java +++ b/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/HttpServerFilterInstrumentation.java @@ -9,36 +9,20 @@ import static net.bytebuddy.matcher.ElementMatchers.isPrivate; 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.Collections; 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 HttpServerFilterInstrumentation extends Instrumenter.Default { - - public HttpServerFilterInstrumentation() { - super("grizzly"); - } +final class HttpServerFilterInstrumentation implements TypeInstrumentation { @Override public ElementMatcher typeMatcher() { return named("org.glassfish.grizzly.http.HttpServerFilter"); } - @Override - protected boolean defaultEnabled() { - return false; - } - - @Override - public String[] helperClassNames() { - return new String[] {packageName + ".GrizzlyHttpServerTracer", packageName + ".ExtractAdapter"}; - } - @Override public Map, String> transformers() { return Collections.singletonMap( @@ -48,6 +32,6 @@ public class HttpServerFilterInstrumentation extends Instrumenter.Default { .and(takesArgument(2, named("org.glassfish.grizzly.http.HttpResponsePacket"))) .and(takesArgument(3, named("org.glassfish.grizzly.http.HttpContent"))) .and(isPrivate()), - packageName + ".HttpServerFilterAdvice"); + HttpServerFilterAdvice.class.getName()); } } diff --git a/instrumentation/grizzly-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/client/GrizzlyClientInstrumentationModule.java b/instrumentation/grizzly-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/client/GrizzlyClientInstrumentationModule.java new file mode 100644 index 0000000000..358429e601 --- /dev/null +++ b/instrumentation/grizzly-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/client/GrizzlyClientInstrumentationModule.java @@ -0,0 +1,46 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.grizzly.client; + +import static java.util.Arrays.asList; +import static java.util.Collections.singletonMap; + +import com.google.auto.service.AutoService; +import io.opentelemetry.javaagent.instrumentation.api.Pair; +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 GrizzlyClientInstrumentationModule extends InstrumentationModule { + public GrizzlyClientInstrumentationModule() { + super("grizzly-client", "ning"); + } + + @Override + public String[] helperClassNames() { + return new String[] { + packageName + ".GrizzlyClientTracer", packageName + ".GrizzlyInjectAdapter" + }; + } + + @Override + public List typeInstrumentations() { + return asList( + new GrizzlyClientRequestInstrumentation(), new GrizzlyClientResponseInstrumentation()); + } + + @Override + public Map contextStore() { + return singletonMap("com.ning.http.client.AsyncHandler", Pair.class.getName()); + } + + @Override + protected boolean defaultEnabled() { + return false; + } +} diff --git a/instrumentation/grizzly-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/client/GrizzlyClientRequestInstrumentation.java b/instrumentation/grizzly-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/client/GrizzlyClientRequestInstrumentation.java index 589cdba1ba..b1f6bc88e5 100644 --- a/instrumentation/grizzly-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/client/GrizzlyClientRequestInstrumentation.java +++ b/instrumentation/grizzly-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/client/GrizzlyClientRequestInstrumentation.java @@ -10,43 +10,19 @@ 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.instrumentation.api.Pair; -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 GrizzlyClientRequestInstrumentation extends Instrumenter.Default { - - public GrizzlyClientRequestInstrumentation() { - super("grizzly-client", "ning"); - } - - @Override - public Map contextStore() { - return singletonMap("com.ning.http.client.AsyncHandler", Pair.class.getName()); - } +final class GrizzlyClientRequestInstrumentation implements TypeInstrumentation { @Override public ElementMatcher typeMatcher() { return named("com.ning.http.client.AsyncHttpClient"); } - @Override - public String[] helperClassNames() { - return new String[] { - packageName + ".GrizzlyClientTracer", packageName + ".GrizzlyInjectAdapter" - }; - } - - @Override - protected boolean defaultEnabled() { - return false; - } - @Override public Map, String> transformers() { return singletonMap( @@ -54,6 +30,6 @@ public final class GrizzlyClientRequestInstrumentation extends Instrumenter.Defa .and(takesArgument(0, named("com.ning.http.client.Request"))) .and(takesArgument(1, named("com.ning.http.client.AsyncHandler"))) .and(isPublic()), - packageName + ".GrizzlyClientRequestAdvice"); + GrizzlyClientRequestAdvice.class.getName()); } } diff --git a/instrumentation/grizzly-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/client/GrizzlyClientResponseInstrumentation.java b/instrumentation/grizzly-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/client/GrizzlyClientResponseInstrumentation.java index fcf11189ee..97e0c110d2 100644 --- a/instrumentation/grizzly-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/client/GrizzlyClientResponseInstrumentation.java +++ b/instrumentation/grizzly-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/client/GrizzlyClientResponseInstrumentation.java @@ -12,54 +12,30 @@ 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.instrumentation.api.Pair; -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 GrizzlyClientResponseInstrumentation extends Instrumenter.Default { - - public GrizzlyClientResponseInstrumentation() { - super("grizzly-client", "ning"); - } - - @Override - public Map contextStore() { - return singletonMap("com.ning.http.client.AsyncHandler", Pair.class.getName()); - } +final class GrizzlyClientResponseInstrumentation implements TypeInstrumentation { @Override public ElementMatcher classLoaderMatcher() { return hasClassesNamed("com.ning.http.client.AsyncCompletionHandler"); } - @Override - protected boolean defaultEnabled() { - return false; - } - @Override public ElementMatcher typeMatcher() { return hasSuperClass(named("com.ning.http.client.AsyncCompletionHandler")); } - @Override - public String[] helperClassNames() { - return new String[] { - packageName + ".GrizzlyClientTracer", packageName + ".GrizzlyInjectAdapter" - }; - } - @Override public Map, String> transformers() { return singletonMap( named("onCompleted") .and(takesArgument(0, named("com.ning.http.client.Response"))) .and(isPublic()), - packageName + ".GrizzlyClientResponseAdvice"); + GrizzlyClientResponseAdvice.class.getName()); } } diff --git a/instrumentation/grpc-1.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grpc/v1_5/GrpcClientBuilderBuildInstrumentation.java b/instrumentation/grpc-1.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grpc/v1_5/GrpcClientBuilderBuildInstrumentation.java index 24b22d1f71..600244ca6f 100644 --- a/instrumentation/grpc-1.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grpc/v1_5/GrpcClientBuilderBuildInstrumentation.java +++ b/instrumentation/grpc-1.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grpc/v1_5/GrpcClientBuilderBuildInstrumentation.java @@ -5,16 +5,16 @@ package io.opentelemetry.javaagent.instrumentation.grpc.v1_5; +import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; import static java.util.Collections.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.declaresField; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.named; -import com.google.auto.service.AutoService; import io.grpc.ClientInterceptor; import io.opentelemetry.instrumentation.grpc.v1_5.client.TracingClientInterceptor; -import io.opentelemetry.javaagent.tooling.Instrumenter; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.List; import java.util.Map; import net.bytebuddy.asm.Advice; @@ -22,8 +22,12 @@ import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; -@AutoService(Instrumenter.class) -public class GrpcClientBuilderBuildInstrumentation extends AbstractGrpcInstrumentation { +final class GrpcClientBuilderBuildInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher classLoaderMatcher() { + // optimization for expensive typeMatcher + return hasClassesNamed("io.grpc.ManagedChannelBuilder"); + } @Override public ElementMatcher typeMatcher() { diff --git a/instrumentation/grpc-1.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grpc/v1_5/AbstractGrpcInstrumentation.java b/instrumentation/grpc-1.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grpc/v1_5/GrpcInstrumentationModule.java similarity index 66% rename from instrumentation/grpc-1.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grpc/v1_5/AbstractGrpcInstrumentation.java rename to instrumentation/grpc-1.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grpc/v1_5/GrpcInstrumentationModule.java index ff8fbacf84..9eb1310759 100644 --- a/instrumentation/grpc-1.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grpc/v1_5/AbstractGrpcInstrumentation.java +++ b/instrumentation/grpc-1.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grpc/v1_5/GrpcInstrumentationModule.java @@ -5,16 +5,21 @@ package io.opentelemetry.javaagent.instrumentation.grpc.v1_5; -import io.opentelemetry.javaagent.tooling.Instrumenter; +import static java.util.Arrays.asList; -abstract class AbstractGrpcInstrumentation extends Instrumenter.Default { +import com.google.auto.service.AutoService; +import io.opentelemetry.javaagent.tooling.InstrumentationModule; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; +import java.util.List; - public AbstractGrpcInstrumentation() { +@AutoService(InstrumentationModule.class) +public class GrpcInstrumentationModule extends InstrumentationModule { + public GrpcInstrumentationModule() { super("grpc"); } @Override - public final String[] helperClassNames() { + public String[] helperClassNames() { return new String[] { "io.opentelemetry.instrumentation.grpc.v1_5.common.GrpcHelper", "io.opentelemetry.instrumentation.grpc.v1_5.client.GrpcClientTracer", @@ -29,4 +34,10 @@ abstract class AbstractGrpcInstrumentation extends Instrumenter.Default { "io.opentelemetry.instrumentation.grpc.v1_5.server.TracingServerInterceptor$TracingServerCallListener", }; } + + @Override + public List typeInstrumentations() { + return asList( + new GrpcClientBuilderBuildInstrumentation(), new GrpcServerBuilderInstrumentation()); + } } diff --git a/instrumentation/grpc-1.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grpc/v1_5/GrpcServerBuilderInstrumentation.java b/instrumentation/grpc-1.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grpc/v1_5/GrpcServerBuilderInstrumentation.java index 389fae2b39..f2e4853094 100644 --- a/instrumentation/grpc-1.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grpc/v1_5/GrpcServerBuilderInstrumentation.java +++ b/instrumentation/grpc-1.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grpc/v1_5/GrpcServerBuilderInstrumentation.java @@ -9,10 +9,9 @@ import static java.util.Collections.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.named; -import com.google.auto.service.AutoService; import io.grpc.ServerInterceptor; import io.opentelemetry.instrumentation.grpc.v1_5.server.TracingServerInterceptor; -import io.opentelemetry.javaagent.tooling.Instrumenter; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.List; import java.util.Map; import net.bytebuddy.asm.Advice; @@ -20,8 +19,7 @@ import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; -@AutoService(Instrumenter.class) -public class GrpcServerBuilderInstrumentation extends AbstractGrpcInstrumentation { +final class GrpcServerBuilderInstrumentation implements TypeInstrumentation { @Override public ElementMatcher typeMatcher() { diff --git a/instrumentation/guava-10.0/src/main/java/io/opentelemetry/javaagent/instrumentation/guava/ListenableFutureInstrumentation.java b/instrumentation/guava-10.0/src/main/java/io/opentelemetry/javaagent/instrumentation/guava/GuavaInstrumentationModule.java similarity index 70% rename from instrumentation/guava-10.0/src/main/java/io/opentelemetry/javaagent/instrumentation/guava/ListenableFutureInstrumentation.java rename to instrumentation/guava-10.0/src/main/java/io/opentelemetry/javaagent/instrumentation/guava/GuavaInstrumentationModule.java index 73919838fd..839dbf5076 100644 --- a/instrumentation/guava-10.0/src/main/java/io/opentelemetry/javaagent/instrumentation/guava/ListenableFutureInstrumentation.java +++ b/instrumentation/guava-10.0/src/main/java/io/opentelemetry/javaagent/instrumentation/guava/GuavaInstrumentationModule.java @@ -5,6 +5,7 @@ package io.opentelemetry.javaagent.instrumentation.guava; +import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.named; @@ -17,7 +18,9 @@ import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; import io.opentelemetry.javaagent.instrumentation.api.concurrent.ExecutorInstrumentationUtils; import io.opentelemetry.javaagent.instrumentation.api.concurrent.RunnableWrapper; import io.opentelemetry.javaagent.instrumentation.api.concurrent.State; -import io.opentelemetry.javaagent.tooling.Instrumenter; +import io.opentelemetry.javaagent.tooling.InstrumentationModule; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; +import java.util.List; import java.util.Map; import java.util.concurrent.Executor; import net.bytebuddy.asm.Advice; @@ -26,16 +29,16 @@ import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatchers; -@AutoService(Instrumenter.class) -public class ListenableFutureInstrumentation extends Instrumenter.Default { +@AutoService(InstrumentationModule.class) +public class GuavaInstrumentationModule extends InstrumentationModule { - public ListenableFutureInstrumentation() { + public GuavaInstrumentationModule() { super("guava"); } @Override - public ElementMatcher typeMatcher() { - return named("com.google.common.util.concurrent.AbstractFuture"); + public List typeInstrumentations() { + return singletonList(new ListenableFutureInstrumentation()); } @Override @@ -43,11 +46,18 @@ public class ListenableFutureInstrumentation extends Instrumenter.Default { return singletonMap(Runnable.class.getName(), State.class.getName()); } - @Override - public Map, String> transformers() { - return singletonMap( - named("addListener").and(ElementMatchers.takesArguments(Runnable.class, Executor.class)), - ListenableFutureInstrumentation.class.getName() + "$AddListenerAdvice"); + private static final class ListenableFutureInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher typeMatcher() { + return named("com.google.common.util.concurrent.AbstractFuture"); + } + + @Override + public Map, String> transformers() { + return singletonMap( + named("addListener").and(ElementMatchers.takesArguments(Runnable.class, Executor.class)), + GuavaInstrumentationModule.class.getName() + "$AddListenerAdvice"); + } } public static class AddListenerAdvice { diff --git a/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/AbstractHibernateInstrumentation.java b/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/AbstractHibernateInstrumentation.java deleted file mode 100644 index f115b89499..0000000000 --- a/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/AbstractHibernateInstrumentation.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.hibernate.v3_3; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; - -import io.opentelemetry.javaagent.tooling.Instrumenter; -import net.bytebuddy.matcher.ElementMatcher; -import org.hibernate.classic.Validatable; -import org.hibernate.transaction.JBossTransactionManagerLookup; - -public abstract class AbstractHibernateInstrumentation extends Instrumenter.Default { - - public AbstractHibernateInstrumentation() { - super("hibernate", "hibernate-core"); - } - - @Override - public ElementMatcher classLoaderMatcher() { - // Optimization for expensive typeMatcher. - return hasClassesNamed("org.hibernate.Session"); - } - - @Override - public String[] helperClassNames() { - return new String[] { - "io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils", - "io.opentelemetry.javaagent.instrumentation.hibernate.HibernateDecorator", - packageName + ".AbstractHibernateInstrumentation$V3Advice", - }; - } - - public abstract static class V3Advice { - - /** - * Some cases of instrumentation will match more broadly than others, so this unused method - * allows all instrumentation to uniformly match versions of Hibernate between 3.3 and 4. - */ - public static void muzzleCheck( - // Not in 4.0 - Validatable validatable, - // Not before 3.3.0.GA - JBossTransactionManagerLookup lookup) { - validatable.validate(); - lookup.getUserTransactionName(); - } - } -} diff --git a/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/CriteriaInstrumentation.java b/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/CriteriaInstrumentation.java index 7e0acd964a..e4490c6800 100644 --- a/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/CriteriaInstrumentation.java +++ b/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/CriteriaInstrumentation.java @@ -5,19 +5,19 @@ package io.opentelemetry.javaagent.instrumentation.hibernate.v3_3; +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.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.named; -import com.google.auto.service.AutoService; import io.opentelemetry.context.Context; import io.opentelemetry.javaagent.instrumentation.api.ContextStore; import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; -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; @@ -26,12 +26,12 @@ import net.bytebuddy.implementation.bytecode.assign.Assigner; import net.bytebuddy.matcher.ElementMatcher; import org.hibernate.Criteria; -@AutoService(Instrumenter.class) -public class CriteriaInstrumentation extends AbstractHibernateInstrumentation { +final class CriteriaInstrumentation implements TypeInstrumentation { @Override - public Map contextStore() { - return singletonMap("org.hibernate.Criteria", Context.class.getName()); + public ElementMatcher classLoaderMatcher() { + // Optimization for expensive typeMatcher. + return hasClassesNamed("org.hibernate.Criteria"); } @Override diff --git a/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/HibernateInstrumentationModule.java b/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/HibernateInstrumentationModule.java new file mode 100644 index 0000000000..16c8492592 --- /dev/null +++ b/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/HibernateInstrumentationModule.java @@ -0,0 +1,54 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.hibernate.v3_3; + +import static java.util.Arrays.asList; + +import com.google.auto.service.AutoService; +import io.opentelemetry.context.Context; +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; + +@AutoService(InstrumentationModule.class) +public class HibernateInstrumentationModule extends InstrumentationModule { + + public HibernateInstrumentationModule() { + super("hibernate", "hibernate-core"); + } + + @Override + public String[] helperClassNames() { + return new String[] { + "io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils", + "io.opentelemetry.javaagent.instrumentation.hibernate.HibernateDecorator", + }; + } + + @Override + public List typeInstrumentations() { + return asList( + new CriteriaInstrumentation(), + new QueryInstrumentation(), + new SessionFactoryInstrumentation(), + new SessionInstrumentation(), + new TransactionInstrumentation()); + } + + @Override + public Map contextStore() { + Map map = new HashMap<>(); + map.put("org.hibernate.Criteria", Context.class.getName()); + map.put("org.hibernate.Query", Context.class.getName()); + map.put("org.hibernate.Session", Context.class.getName()); + map.put("org.hibernate.StatelessSession", Context.class.getName()); + map.put("org.hibernate.Transaction", Context.class.getName()); + return Collections.unmodifiableMap(map); + } +} diff --git a/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/QueryInstrumentation.java b/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/QueryInstrumentation.java index d969741d2e..db724d3204 100644 --- a/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/QueryInstrumentation.java +++ b/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/QueryInstrumentation.java @@ -5,19 +5,19 @@ package io.opentelemetry.javaagent.instrumentation.hibernate.v3_3; +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.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.named; -import com.google.auto.service.AutoService; import io.opentelemetry.context.Context; import io.opentelemetry.javaagent.instrumentation.api.ContextStore; import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; -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; @@ -25,12 +25,12 @@ import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; import org.hibernate.Query; -@AutoService(Instrumenter.class) -public class QueryInstrumentation extends AbstractHibernateInstrumentation { +final class QueryInstrumentation implements TypeInstrumentation { @Override - public Map contextStore() { - return singletonMap("org.hibernate.Query", Context.class.getName()); + public ElementMatcher classLoaderMatcher() { + // Optimization for expensive typeMatcher. + return hasClassesNamed("org.hibernate.Query"); } @Override diff --git a/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/SessionFactoryInstrumentation.java b/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/SessionFactoryInstrumentation.java index 11a9bda575..28486dabdd 100644 --- a/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/SessionFactoryInstrumentation.java +++ b/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/SessionFactoryInstrumentation.java @@ -7,6 +7,7 @@ package io.opentelemetry.javaagent.instrumentation.hibernate.v3_3; import static io.opentelemetry.javaagent.instrumentation.hibernate.HibernateDecorator.DECORATE; import static io.opentelemetry.javaagent.instrumentation.hibernate.HibernateDecorator.tracer; +import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.hasInterface; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; @@ -16,14 +17,12 @@ import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.returns; import static net.bytebuddy.matcher.ElementMatchers.takesArguments; -import com.google.auto.service.AutoService; import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Context; 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 java.util.HashMap; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.Map; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; @@ -32,16 +31,12 @@ import net.bytebuddy.matcher.ElementMatcher; import org.hibernate.Session; import org.hibernate.StatelessSession; -@AutoService(Instrumenter.class) -public class SessionFactoryInstrumentation extends AbstractHibernateInstrumentation { +final class SessionFactoryInstrumentation implements TypeInstrumentation { @Override - public Map contextStore() { - Map stores = new HashMap<>(); - stores.put("org.hibernate.Session", Context.class.getName()); - stores.put("org.hibernate.StatelessSession", Context.class.getName()); - stores.put("org.hibernate.SharedSessionContract", Context.class.getName()); - return stores; + public ElementMatcher classLoaderMatcher() { + // Optimization for expensive typeMatcher. + return hasClassesNamed("org.hibernate.SessionFactory"); } @Override diff --git a/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/SessionInstrumentation.java b/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/SessionInstrumentation.java index 47e0386a34..33d49f424b 100644 --- a/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/SessionInstrumentation.java +++ b/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/SessionInstrumentation.java @@ -7,6 +7,7 @@ package io.opentelemetry.javaagent.instrumentation.hibernate.v3_3; import static io.opentelemetry.javaagent.instrumentation.hibernate.HibernateDecorator.DECORATE; import static io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils.SCOPE_ONLY_METHODS; +import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.hasInterface; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; @@ -16,7 +17,6 @@ import static net.bytebuddy.matcher.ElementMatchers.returns; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArguments; -import com.google.auto.service.AutoService; import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Context; import io.opentelemetry.javaagent.instrumentation.api.ContextStore; @@ -24,8 +24,7 @@ import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; -import io.opentelemetry.javaagent.tooling.Instrumenter; -import java.util.Collections; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.HashMap; import java.util.Map; import net.bytebuddy.asm.Advice; @@ -39,18 +38,12 @@ import org.hibernate.Session; import org.hibernate.StatelessSession; import org.hibernate.Transaction; -@AutoService(Instrumenter.class) -public class SessionInstrumentation extends AbstractHibernateInstrumentation { +final class SessionInstrumentation implements TypeInstrumentation { @Override - public Map contextStore() { - Map map = new HashMap<>(); - map.put("org.hibernate.Session", Context.class.getName()); - map.put("org.hibernate.StatelessSession", Context.class.getName()); - map.put("org.hibernate.Query", Context.class.getName()); - map.put("org.hibernate.Transaction", Context.class.getName()); - map.put("org.hibernate.Criteria", Context.class.getName()); - return Collections.unmodifiableMap(map); + public ElementMatcher classLoaderMatcher() { + // Optimization for expensive typeMatcher. + return hasClassesNamed("org.hibernate.Session", "org.hibernate.StatelessSession"); } @Override diff --git a/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/TransactionInstrumentation.java b/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/TransactionInstrumentation.java index b00fd8ae33..e78572cfc2 100644 --- a/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/TransactionInstrumentation.java +++ b/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/TransactionInstrumentation.java @@ -5,19 +5,19 @@ package io.opentelemetry.javaagent.instrumentation.hibernate.v3_3; +import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; import static java.util.Collections.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.takesArguments; -import com.google.auto.service.AutoService; import io.opentelemetry.context.Context; import io.opentelemetry.javaagent.instrumentation.api.ContextStore; import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; -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; @@ -25,12 +25,12 @@ import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; import org.hibernate.Transaction; -@AutoService(Instrumenter.class) -public class TransactionInstrumentation extends AbstractHibernateInstrumentation { +final class TransactionInstrumentation implements TypeInstrumentation { @Override - public Map contextStore() { - return singletonMap("org.hibernate.Transaction", Context.class.getName()); + public ElementMatcher classLoaderMatcher() { + // Optimization for expensive typeMatcher. + return hasClassesNamed("org.hibernate.Transaction"); } @Override diff --git a/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/V3Advice.java b/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/V3Advice.java new file mode 100644 index 0000000000..003454000c --- /dev/null +++ b/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/V3Advice.java @@ -0,0 +1,25 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.hibernate.v3_3; + +import org.hibernate.classic.Validatable; +import org.hibernate.transaction.JBossTransactionManagerLookup; + +public abstract class V3Advice { + + /** + * Some cases of instrumentation will match more broadly than others, so this unused method allows + * all instrumentation to uniformly match versions of Hibernate between 3.3 and 4. + */ + public static void muzzleCheck( + // Not in 4.0 + Validatable validatable, + // Not before 3.3.0.GA + JBossTransactionManagerLookup lookup) { + validatable.validate(); + lookup.getUserTransactionName(); + } +} diff --git a/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/AbstractHibernateInstrumentation.java b/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/AbstractHibernateInstrumentation.java deleted file mode 100644 index 6a2a7957f3..0000000000 --- a/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/AbstractHibernateInstrumentation.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.hibernate.v4_0; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; - -import io.opentelemetry.javaagent.tooling.Instrumenter; -import net.bytebuddy.matcher.ElementMatcher; -import org.hibernate.SharedSessionContract; - -public abstract class AbstractHibernateInstrumentation extends Instrumenter.Default { - - public AbstractHibernateInstrumentation() { - super("hibernate", "hibernate-core"); - } - - @Override - public ElementMatcher classLoaderMatcher() { - // Optimization for expensive typeMatcher. - return hasClassesNamed("org.hibernate.Session"); - } - - @Override - public String[] helperClassNames() { - return new String[] { - "io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils", - "io.opentelemetry.javaagent.instrumentation.hibernate.HibernateDecorator", - packageName + ".AbstractHibernateInstrumentation$V4Advice", - }; - } - - public abstract static class V4Advice { - - /** - * Some cases of instrumentation will match more broadly than others, so this unused method - * allows all instrumentation to uniformly match versions of Hibernate starting at 4.0. - */ - public static void muzzleCheck(SharedSessionContract contract) { - contract.createCriteria(""); - } - } -} diff --git a/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/CriteriaInstrumentation.java b/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/CriteriaInstrumentation.java index abeea573cc..2dcba414e6 100644 --- a/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/CriteriaInstrumentation.java +++ b/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/CriteriaInstrumentation.java @@ -5,19 +5,19 @@ package io.opentelemetry.javaagent.instrumentation.hibernate.v4_0; +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.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.named; -import com.google.auto.service.AutoService; import io.opentelemetry.context.Context; import io.opentelemetry.javaagent.instrumentation.api.ContextStore; import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; -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; @@ -26,12 +26,12 @@ import net.bytebuddy.implementation.bytecode.assign.Assigner; import net.bytebuddy.matcher.ElementMatcher; import org.hibernate.Criteria; -@AutoService(Instrumenter.class) -public class CriteriaInstrumentation extends AbstractHibernateInstrumentation { +final class CriteriaInstrumentation implements TypeInstrumentation { @Override - public Map contextStore() { - return singletonMap("org.hibernate.Criteria", Context.class.getName()); + public ElementMatcher classLoaderMatcher() { + // Optimization for expensive typeMatcher. + return hasClassesNamed("org.hibernate.Criteria"); } @Override diff --git a/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/HibernateInstrumentationModule.java b/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/HibernateInstrumentationModule.java new file mode 100644 index 0000000000..88e18f0d14 --- /dev/null +++ b/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/HibernateInstrumentationModule.java @@ -0,0 +1,53 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.hibernate.v4_0; + +import static java.util.Arrays.asList; + +import com.google.auto.service.AutoService; +import io.opentelemetry.context.Context; +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; + +@AutoService(InstrumentationModule.class) +public class HibernateInstrumentationModule extends InstrumentationModule { + + public HibernateInstrumentationModule() { + super("hibernate", "hibernate-core"); + } + + @Override + public String[] helperClassNames() { + return new String[] { + "io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils", + "io.opentelemetry.javaagent.instrumentation.hibernate.HibernateDecorator", + }; + } + + @Override + public List typeInstrumentations() { + return asList( + new CriteriaInstrumentation(), + new QueryInstrumentation(), + new SessionFactoryInstrumentation(), + new SessionInstrumentation(), + new TransactionInstrumentation()); + } + + @Override + public Map contextStore() { + Map map = new HashMap<>(); + map.put("org.hibernate.Criteria", Context.class.getName()); + map.put("org.hibernate.Query", Context.class.getName()); + map.put("org.hibernate.SharedSessionContract", Context.class.getName()); + map.put("org.hibernate.Transaction", Context.class.getName()); + return Collections.unmodifiableMap(map); + } +} diff --git a/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/QueryInstrumentation.java b/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/QueryInstrumentation.java index 0be579d38d..7dd8096b08 100644 --- a/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/QueryInstrumentation.java +++ b/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/QueryInstrumentation.java @@ -5,19 +5,19 @@ package io.opentelemetry.javaagent.instrumentation.hibernate.v4_0; +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.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.named; -import com.google.auto.service.AutoService; import io.opentelemetry.context.Context; import io.opentelemetry.javaagent.instrumentation.api.ContextStore; import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; -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; @@ -25,12 +25,12 @@ import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; import org.hibernate.Query; -@AutoService(Instrumenter.class) -public class QueryInstrumentation extends AbstractHibernateInstrumentation { +final class QueryInstrumentation implements TypeInstrumentation { @Override - public Map contextStore() { - return singletonMap("org.hibernate.Query", Context.class.getName()); + public ElementMatcher classLoaderMatcher() { + // Optimization for expensive typeMatcher. + return hasClassesNamed("org.hibernate.Query"); } @Override diff --git a/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/SessionFactoryInstrumentation.java b/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/SessionFactoryInstrumentation.java index d1766539f9..da2ec5d88d 100644 --- a/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/SessionFactoryInstrumentation.java +++ b/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/SessionFactoryInstrumentation.java @@ -7,6 +7,7 @@ package io.opentelemetry.javaagent.instrumentation.hibernate.v4_0; import static io.opentelemetry.javaagent.instrumentation.hibernate.HibernateDecorator.DECORATE; import static io.opentelemetry.javaagent.instrumentation.hibernate.HibernateDecorator.tracer; +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.singletonMap; @@ -15,13 +16,12 @@ import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.returns; import static net.bytebuddy.matcher.ElementMatchers.takesArguments; -import com.google.auto.service.AutoService; import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Context; 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.util.Map; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; @@ -29,12 +29,12 @@ import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; import org.hibernate.SharedSessionContract; -@AutoService(Instrumenter.class) -public class SessionFactoryInstrumentation extends AbstractHibernateInstrumentation { +final class SessionFactoryInstrumentation implements TypeInstrumentation { @Override - public Map contextStore() { - return singletonMap("org.hibernate.SharedSessionContract", Context.class.getName()); + public ElementMatcher classLoaderMatcher() { + // Optimization for expensive typeMatcher. + return hasClassesNamed("org.hibernate.SessionFactory"); } @Override diff --git a/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/SessionInstrumentation.java b/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/SessionInstrumentation.java index a4d24e55b4..22b749a2eb 100644 --- a/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/SessionInstrumentation.java +++ b/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/SessionInstrumentation.java @@ -7,6 +7,7 @@ package io.opentelemetry.javaagent.instrumentation.hibernate.v4_0; import static io.opentelemetry.javaagent.instrumentation.hibernate.HibernateDecorator.DECORATE; import static io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils.SCOPE_ONLY_METHODS; +import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.hasInterface; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; @@ -16,7 +17,6 @@ import static net.bytebuddy.matcher.ElementMatchers.returns; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArguments; -import com.google.auto.service.AutoService; import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Context; import io.opentelemetry.javaagent.instrumentation.api.ContextStore; @@ -24,8 +24,7 @@ import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; -import io.opentelemetry.javaagent.tooling.Instrumenter; -import java.util.Collections; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.HashMap; import java.util.Map; import net.bytebuddy.asm.Advice; @@ -38,17 +37,12 @@ import org.hibernate.Query; import org.hibernate.SharedSessionContract; import org.hibernate.Transaction; -@AutoService(Instrumenter.class) -public class SessionInstrumentation extends AbstractHibernateInstrumentation { +final class SessionInstrumentation implements TypeInstrumentation { @Override - public Map contextStore() { - Map map = new HashMap<>(); - map.put("org.hibernate.SharedSessionContract", Context.class.getName()); - map.put("org.hibernate.Query", Context.class.getName()); - map.put("org.hibernate.Transaction", Context.class.getName()); - map.put("org.hibernate.Criteria", Context.class.getName()); - return Collections.unmodifiableMap(map); + public ElementMatcher classLoaderMatcher() { + // Optimization for expensive typeMatcher. + return hasClassesNamed("org.hibernate.SharedSessionContract"); } @Override diff --git a/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/TransactionInstrumentation.java b/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/TransactionInstrumentation.java index f4bb9bdf0a..3e4f20330a 100644 --- a/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/TransactionInstrumentation.java +++ b/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/TransactionInstrumentation.java @@ -5,19 +5,19 @@ package io.opentelemetry.javaagent.instrumentation.hibernate.v4_0; +import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; import static java.util.Collections.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.takesArguments; -import com.google.auto.service.AutoService; import io.opentelemetry.context.Context; import io.opentelemetry.javaagent.instrumentation.api.ContextStore; import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; -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; @@ -25,12 +25,12 @@ import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; import org.hibernate.Transaction; -@AutoService(Instrumenter.class) -public class TransactionInstrumentation extends AbstractHibernateInstrumentation { +final class TransactionInstrumentation implements TypeInstrumentation { @Override - public Map contextStore() { - return singletonMap("org.hibernate.Transaction", Context.class.getName()); + public ElementMatcher classLoaderMatcher() { + // Optimization for expensive typeMatcher. + return hasClassesNamed("org.hibernate.Transaction"); } @Override diff --git a/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/V4Advice.java b/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/V4Advice.java new file mode 100644 index 0000000000..19f3431af0 --- /dev/null +++ b/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/V4Advice.java @@ -0,0 +1,19 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.hibernate.v4_0; + +import org.hibernate.SharedSessionContract; + +public abstract class V4Advice { + + /** + * Some cases of instrumentation will match more broadly than others, so this unused method allows + * all instrumentation to uniformly match versions of Hibernate starting at 4.0. + */ + public static void muzzleCheck(SharedSessionContract contract) { + contract.createCriteria(""); + } +} diff --git a/instrumentation/hibernate/hibernate-4.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_3/HibernateInstrumentationModule.java b/instrumentation/hibernate/hibernate-4.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_3/HibernateInstrumentationModule.java new file mode 100644 index 0000000000..83153770be --- /dev/null +++ b/instrumentation/hibernate/hibernate-4.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_3/HibernateInstrumentationModule.java @@ -0,0 +1,45 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.hibernate.v4_3; + +import static java.util.Arrays.asList; + +import com.google.auto.service.AutoService; +import io.opentelemetry.context.Context; +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; + +@AutoService(InstrumentationModule.class) +public class HibernateInstrumentationModule extends InstrumentationModule { + public HibernateInstrumentationModule() { + super("hibernate", "hibernate-core"); + } + + @Override + public String[] helperClassNames() { + return new String[] { + "io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils", + "io.opentelemetry.javaagent.instrumentation.hibernate.HibernateDecorator", + }; + } + + @Override + public List typeInstrumentations() { + return asList(new ProcedureCallInstrumentation(), new SessionInstrumentation()); + } + + @Override + public Map contextStore() { + Map map = new HashMap<>(); + map.put("org.hibernate.SharedSessionContract", Context.class.getName()); + map.put("org.hibernate.procedure.ProcedureCall", Context.class.getName()); + return Collections.unmodifiableMap(map); + } +} diff --git a/instrumentation/hibernate/hibernate-4.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_3/ProcedureCallInstrumentation.java b/instrumentation/hibernate/hibernate-4.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_3/ProcedureCallInstrumentation.java index ea0434434a..1db3ba6bfd 100644 --- a/instrumentation/hibernate/hibernate-4.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_3/ProcedureCallInstrumentation.java +++ b/instrumentation/hibernate/hibernate-4.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_3/ProcedureCallInstrumentation.java @@ -11,13 +11,12 @@ import static java.util.Collections.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.named; -import com.google.auto.service.AutoService; import io.opentelemetry.context.Context; import io.opentelemetry.javaagent.instrumentation.api.ContextStore; import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; -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; @@ -25,30 +24,12 @@ import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; import org.hibernate.procedure.ProcedureCall; -@AutoService(Instrumenter.class) -public class ProcedureCallInstrumentation extends Instrumenter.Default { - - public ProcedureCallInstrumentation() { - super("hibernate", "hibernate-core"); - } - - @Override - public Map contextStore() { - return singletonMap("org.hibernate.procedure.ProcedureCall", Context.class.getName()); - } - - @Override - public String[] helperClassNames() { - return new String[] { - "io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils", - "io.opentelemetry.javaagent.instrumentation.hibernate.HibernateDecorator", - }; - } +final class ProcedureCallInstrumentation implements TypeInstrumentation { @Override public ElementMatcher classLoaderMatcher() { // Optimization for expensive typeMatcher. - return hasClassesNamed("org.hibernate.Session"); + return hasClassesNamed("org.hibernate.procedure.ProcedureCall"); } @Override diff --git a/instrumentation/hibernate/hibernate-4.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_3/SessionInstrumentation.java b/instrumentation/hibernate/hibernate-4.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_3/SessionInstrumentation.java index 0fa8f4b54a..2e8ba6bd29 100644 --- a/instrumentation/hibernate/hibernate-4.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_3/SessionInstrumentation.java +++ b/instrumentation/hibernate/hibernate-4.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_3/SessionInstrumentation.java @@ -13,14 +13,11 @@ import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.returns; -import com.google.auto.service.AutoService; import io.opentelemetry.context.Context; import io.opentelemetry.javaagent.instrumentation.api.ContextStore; import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; -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 net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; @@ -29,33 +26,12 @@ import net.bytebuddy.matcher.ElementMatcher; import org.hibernate.SharedSessionContract; import org.hibernate.procedure.ProcedureCall; -@AutoService(Instrumenter.class) -public class SessionInstrumentation extends Instrumenter.Default { - - public SessionInstrumentation() { - super("hibernate", "hibernate-core"); - } - - @Override - public Map contextStore() { - Map map = new HashMap<>(); - map.put("org.hibernate.SharedSessionContract", Context.class.getName()); - map.put("org.hibernate.procedure.ProcedureCall", Context.class.getName()); - return Collections.unmodifiableMap(map); - } - - @Override - public String[] helperClassNames() { - return new String[] { - "io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils", - "io.opentelemetry.javaagent.instrumentation.hibernate.HibernateDecorator", - }; - } +final class SessionInstrumentation implements TypeInstrumentation { @Override public ElementMatcher classLoaderMatcher() { // Optimization for expensive typeMatcher. - return hasClassesNamed("org.hibernate.Session"); + return hasClassesNamed("org.hibernate.SharedSessionContract"); } @Override diff --git a/instrumentation/http-url-connection/src/main/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/HttpUrlConnectionInstrumentation.java b/instrumentation/http-url-connection/src/main/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/HttpUrlConnectionInstrumentationModule.java similarity index 72% rename from instrumentation/http-url-connection/src/main/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/HttpUrlConnectionInstrumentation.java rename to instrumentation/http-url-connection/src/main/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/HttpUrlConnectionInstrumentationModule.java index 16ab17e690..c4a0158969 100644 --- a/instrumentation/http-url-connection/src/main/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/HttpUrlConnectionInstrumentation.java +++ b/instrumentation/http-url-connection/src/main/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/HttpUrlConnectionInstrumentationModule.java @@ -8,6 +8,7 @@ package io.opentelemetry.javaagent.instrumentation.httpurlconnection; import static io.opentelemetry.javaagent.instrumentation.httpurlconnection.HttpUrlConnectionTracer.tracer; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; 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; @@ -21,8 +22,10 @@ import io.opentelemetry.context.Scope; import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; import io.opentelemetry.javaagent.instrumentation.api.ContextStore; import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.tooling.Instrumenter; +import io.opentelemetry.javaagent.tooling.InstrumentationModule; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.net.HttpURLConnection; +import java.util.List; import java.util.Map; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; @@ -30,46 +33,56 @@ import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatchers; -@AutoService(Instrumenter.class) -public class HttpUrlConnectionInstrumentation extends Instrumenter.Default { +@AutoService(InstrumentationModule.class) +public class HttpUrlConnectionInstrumentationModule extends InstrumentationModule { - public HttpUrlConnectionInstrumentation() { + public HttpUrlConnectionInstrumentationModule() { super("httpurlconnection"); } - @Override - public ElementMatcher typeMatcher() { - return nameStartsWith("java.net.") - .or(ElementMatchers.nameStartsWith("sun.net")) - // In WebLogic, URL.openConnection() returns its own internal implementation of - // HttpURLConnection, which does not delegate the methods that have to be instrumented to - // the JDK superclass. Therefore it needs to be instrumented directly. - .or(named("weblogic.net.http.HttpURLConnection")) - // This class is a simple delegator. Skip because it does not update its `connected` field. - .and(not(named("sun.net.www.protocol.https.HttpsURLConnectionImpl"))) - .and(extendsClass(named("java.net.HttpURLConnection"))); - } - @Override public String[] helperClassNames() { return new String[] { packageName + ".HttpUrlConnectionTracer", packageName + ".HeadersInjectAdapter", - HttpUrlConnectionInstrumentation.class.getName() + "$HttpUrlState", - HttpUrlConnectionInstrumentation.class.getName() + "$HttpUrlState$1", + HttpUrlConnectionInstrumentationModule.class.getName() + "$HttpUrlState", + HttpUrlConnectionInstrumentationModule.class.getName() + "$HttpUrlState$1", }; } + @Override + public List typeInstrumentations() { + return singletonList(new HttpUrlConnectionInstrumentation()); + } + @Override public Map contextStore() { return singletonMap("java.net.HttpURLConnection", getClass().getName() + "$HttpUrlState"); } - @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(isPublic()).and(namedOneOf("connect", "getOutputStream", "getInputStream")), - HttpUrlConnectionInstrumentation.class.getName() + "$HttpUrlConnectionAdvice"); + private static final class HttpUrlConnectionInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher typeMatcher() { + return nameStartsWith("java.net.") + .or(ElementMatchers.nameStartsWith("sun.net")) + // In WebLogic, URL.openConnection() returns its own internal implementation of + // HttpURLConnection, which does not delegate the methods that have to be instrumented to + // the JDK superclass. Therefore it needs to be instrumented directly. + .or(named("weblogic.net.http.HttpURLConnection")) + // This class is a simple delegator. Skip because it does not update its `connected` + // field. + .and(not(named("sun.net.www.protocol.https.HttpsURLConnectionImpl"))) + .and(extendsClass(named("java.net.HttpURLConnection"))); + } + + @Override + public Map, String> transformers() { + return singletonMap( + isMethod() + .and(isPublic()) + .and(namedOneOf("connect", "getOutputStream", "getInputStream")), + HttpUrlConnectionInstrumentationModule.class.getName() + "$HttpUrlConnectionAdvice"); + } } public static class HttpUrlConnectionAdvice { diff --git a/instrumentation/hystrix-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/hystrix/HystrixInstrumentation.java b/instrumentation/hystrix-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/hystrix/HystrixInstrumentationModule.java similarity index 55% rename from instrumentation/hystrix-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/hystrix/HystrixInstrumentation.java rename to instrumentation/hystrix-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/hystrix/HystrixInstrumentationModule.java index 6c5ed8a901..dda69c7afc 100644 --- a/instrumentation/hystrix-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/hystrix/HystrixInstrumentation.java +++ b/instrumentation/hystrix-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/hystrix/HystrixInstrumentationModule.java @@ -10,6 +10,7 @@ import static io.opentelemetry.javaagent.instrumentation.hystrix.HystrixTracer.t import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; +import static java.util.Collections.singletonList; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.returns; @@ -17,8 +18,10 @@ import com.google.auto.service.AutoService; import com.netflix.hystrix.HystrixInvokableInfo; import io.opentelemetry.api.trace.Span; import io.opentelemetry.javaagent.instrumentation.rxjava.TracedOnSubscribe; -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,28 +29,15 @@ import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; import rx.Observable; -@AutoService(Instrumenter.class) -public class HystrixInstrumentation extends Instrumenter.Default { +@AutoService(InstrumentationModule.class) +public class HystrixInstrumentationModule extends InstrumentationModule { private static final String OPERATION_NAME = "hystrix.cmd"; - public HystrixInstrumentation() { + public HystrixInstrumentationModule() { super("hystrix"); } - @Override - public ElementMatcher classLoaderMatcher() { - // Optimization for expensive typeMatcher. - return hasClassesNamed("com.netflix.hystrix.HystrixCommand"); - } - - @Override - public ElementMatcher typeMatcher() { - return extendsClass( - namedOneOf( - "com.netflix.hystrix.HystrixCommand", "com.netflix.hystrix.HystrixObservableCommand")); - } - @Override public String[] helperClassNames() { return new String[] { @@ -56,20 +46,42 @@ public class HystrixInstrumentation extends Instrumenter.Default { "io.opentelemetry.javaagent.instrumentation.rxjava.TracedSubscriber", "io.opentelemetry.javaagent.instrumentation.rxjava.TracedOnSubscribe", packageName + ".HystrixTracer", - packageName + ".HystrixInstrumentation$HystrixOnSubscribe", + getClass().getName() + "$HystrixOnSubscribe", }; } @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - transformers.put( - named("getExecutionObservable").and(returns(named("rx.Observable"))), - HystrixInstrumentation.class.getName() + "$ExecuteAdvice"); - transformers.put( - named("getFallbackObservable").and(returns(named("rx.Observable"))), - HystrixInstrumentation.class.getName() + "$FallbackAdvice"); - return transformers; + public List typeInstrumentations() { + return singletonList(new HystrixCommandInstrumentation()); + } + + private static final class HystrixCommandInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher classLoaderMatcher() { + // Optimization for expensive typeMatcher. + return hasClassesNamed( + "com.netflix.hystrix.HystrixCommand", "com.netflix.hystrix.HystrixObservableCommand"); + } + + @Override + public ElementMatcher typeMatcher() { + return extendsClass( + namedOneOf( + "com.netflix.hystrix.HystrixCommand", + "com.netflix.hystrix.HystrixObservableCommand")); + } + + @Override + public Map, String> transformers() { + Map, String> transformers = new HashMap<>(); + transformers.put( + named("getExecutionObservable").and(returns(named("rx.Observable"))), + HystrixInstrumentationModule.class.getName() + "$ExecuteAdvice"); + transformers.put( + named("getFallbackObservable").and(returns(named("rx.Observable"))), + HystrixInstrumentationModule.class.getName() + "$FallbackAdvice"); + return transformers; + } } public static class ExecuteAdvice { @@ -77,10 +89,10 @@ public class HystrixInstrumentation extends Instrumenter.Default { @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void stopSpan( @Advice.This HystrixInvokableInfo command, - @Advice.Return(readOnly = false) Observable result, + @Advice.Return(readOnly = false) Observable result, @Advice.Thrown Throwable throwable) { - result = Observable.create(new HystrixOnSubscribe(result, command, "execute")); + result = Observable.create(new HystrixOnSubscribe<>(result, command, "execute")); } } @@ -92,16 +104,16 @@ public class HystrixInstrumentation extends Instrumenter.Default { @Advice.Return(readOnly = false) Observable result, @Advice.Thrown Throwable throwable) { - result = Observable.create(new HystrixOnSubscribe(result, command, "fallback")); + result = Observable.create(new HystrixOnSubscribe<>(result, command, "fallback")); } } - public static class HystrixOnSubscribe extends TracedOnSubscribe { + public static class HystrixOnSubscribe extends TracedOnSubscribe { private final HystrixInvokableInfo command; private final String methodName; public HystrixOnSubscribe( - Observable originalObservable, HystrixInvokableInfo command, String methodName) { + Observable originalObservable, HystrixInvokableInfo command, String methodName) { super(originalObservable, OPERATION_NAME, tracer(), INTERNAL); this.command = command; diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/matcher/MuzzleGradlePluginUtil.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/matcher/MuzzleGradlePluginUtil.java index ae1cd71529..dc4af96bef 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/matcher/MuzzleGradlePluginUtil.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/matcher/MuzzleGradlePluginUtil.java @@ -50,15 +50,6 @@ public final class MuzzleGradlePluginUtil { throws Exception { // muzzle validate all instrumenters for (Object instrumenter : loadAllInstrumenters(agentClassLoader)) { - if (instrumenter.getClass().getName().endsWith("TraceConfigInstrumentation")) { - // TraceConfigInstrumentation doesn't do muzzle checks - // check on TracerClassInstrumentation instead - instrumenter = - agentClassLoader - .loadClass(instrumenter.getClass().getName() + "$TracerClassInstrumentation") - .getDeclaredConstructor() - .newInstance(); - } if (!(instrumenter instanceof Instrumenter.Default || instrumenter instanceof InstrumentationModule)) { // only default Instrumenters and modules use muzzle. Skip custom instrumenters. @@ -107,15 +98,6 @@ public final class MuzzleGradlePluginUtil { // run helper injector on all instrumenters if (assertPass) { for (Object instrumenter : loadAllInstrumenters(agentClassLoader)) { - if (instrumenter.getClass().getName().endsWith("TraceConfigInstrumentation")) { - // TraceConfigInstrumentation doesn't do muzzle checks - // check on TracerClassInstrumentation instead - instrumenter = - agentClassLoader - .loadClass(instrumenter.getClass().getName() + "$TracerClassInstrumentation") - .getDeclaredConstructor() - .newInstance(); - } if (!(instrumenter instanceof Instrumenter.Default || instrumenter instanceof InstrumentationModule)) { // only default Instrumenters and modules use muzzle. Skip custom instrumenters. diff --git a/javaagent/src/test/groovy/io/opentelemetry/javaagent/muzzle/MuzzleBytecodeTransformTest.groovy b/javaagent/src/test/groovy/io/opentelemetry/javaagent/muzzle/MuzzleBytecodeTransformTest.groovy index d385b18a03..463aa6b00b 100644 --- a/javaagent/src/test/groovy/io/opentelemetry/javaagent/muzzle/MuzzleBytecodeTransformTest.groovy +++ b/javaagent/src/test/groovy/io/opentelemetry/javaagent/muzzle/MuzzleBytecodeTransformTest.groovy @@ -19,11 +19,6 @@ class MuzzleBytecodeTransformTest extends Specification { List nonLazyFields = [] List unInitFields = [] for (Object instrumenter : SafeServiceLoader.load(IntegrationTestUtils.getAgentClassLoader().loadClass("io.opentelemetry.javaagent.tooling.Instrumenter"), IntegrationTestUtils.getAgentClassLoader())) { - if (instrumenter.getClass().getName().endsWith("TraceConfigInstrumentation")) { - // TraceConfigInstrumentation doesn't do muzzle checks - // check on TracerClassInstrumentation instead - instrumenter = IntegrationTestUtils.getAgentClassLoader().loadClass(instrumenter.getClass().getName() + '$TracerClassInstrumentation').newInstance() - } if (!IntegrationTestUtils.getAgentClassLoader().loadClass('io.opentelemetry.javaagent.tooling.Instrumenter$Default').isAssignableFrom(instrumenter.getClass())) { // muzzle only applies to default instrumenters continue