Refactor Instrumenters into InstrumentationModules - D, E, F, G, H (#1557)

This commit is contained in:
Mateusz Rzeszutek 2020-11-09 23:41:12 +01:00 committed by GitHub
parent d307ffc532
commit aa3ba8d165
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
50 changed files with 1000 additions and 897 deletions

View File

@ -7,6 +7,7 @@ package io.opentelemetry.javaagent.instrumentation.dropwizardviews;
import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.isPublic;
@ -22,44 +23,47 @@ import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.instrumentation.api.decorator.BaseDecorator; import io.opentelemetry.instrumentation.api.decorator.BaseDecorator;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.List;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class) @AutoService(InstrumentationModule.class)
public final class DropwizardViewInstrumentation extends Instrumenter.Default { public final class DropwizardViewInstrumentationModule extends InstrumentationModule {
public DropwizardViewInstrumentationModule() {
public DropwizardViewInstrumentation() {
super("dropwizard", "dropwizard-view"); super("dropwizard", "dropwizard-view");
} }
@Override @Override
public ElementMatcher<ClassLoader> classLoaderMatcher() { public List<TypeInstrumentation> typeInstrumentations() {
// Optimization for expensive typeMatcher. return singletonList(new ViewRendererInstrumentation());
return hasClassesNamed("io.dropwizard.views.ViewRenderer");
} }
@Override private static final class ViewRendererInstrumentation implements TypeInstrumentation {
public ElementMatcher<TypeDescription> typeMatcher() { @Override
return implementsInterface(named("io.dropwizard.views.ViewRenderer")); public ElementMatcher<ClassLoader> classLoaderMatcher() {
} // Optimization for expensive typeMatcher.
return hasClassesNamed("io.dropwizard.views.ViewRenderer");
}
@Override @Override
public String[] helperClassNames() { public ElementMatcher<TypeDescription> typeMatcher() {
return new String[] {getClass().getName() + "$RenderAdvice"}; return implementsInterface(named("io.dropwizard.views.ViewRenderer"));
} }
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap( return singletonMap(
isMethod() isMethod()
.and(named("render")) .and(named("render"))
.and(takesArgument(0, named("io.dropwizard.views.View"))) .and(takesArgument(0, named("io.dropwizard.views.View")))
.and(isPublic()), .and(isPublic()),
DropwizardViewInstrumentation.class.getName() + "$RenderAdvice"); DropwizardViewInstrumentationModule.class.getName() + "$RenderAdvice");
}
} }
public static class RenderAdvice { public static class RenderAdvice {

View File

@ -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.instrumentation.elasticsearch.rest.ElasticsearchRestClientTracer.tracer;
import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named; 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 com.google.auto.service.AutoService;
import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Scope; import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.List;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -24,10 +27,9 @@ import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
import org.elasticsearch.client.ResponseListener; import org.elasticsearch.client.ResponseListener;
@AutoService(Instrumenter.class) @AutoService(InstrumentationModule.class)
public class Elasticsearch5RestClientInstrumentation extends Instrumenter.Default { public class Elasticsearch5RestClientInstrumentationModule extends InstrumentationModule {
public Elasticsearch5RestClientInstrumentationModule() {
public Elasticsearch5RestClientInstrumentation() {
super("elasticsearch", "elasticsearch-rest", "elasticsearch-rest-5"); super("elasticsearch", "elasticsearch-rest", "elasticsearch-rest-5");
} }
@ -40,20 +42,28 @@ public class Elasticsearch5RestClientInstrumentation extends Instrumenter.Defaul
} }
@Override @Override
public ElementMatcher<TypeDescription> typeMatcher() { public List<TypeInstrumentation> typeInstrumentations() {
return named("org.elasticsearch.client.RestClient"); return singletonList(new RestClientInstrumentation());
} }
@Override private static final class RestClientInstrumentation implements TypeInstrumentation {
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { @Override
return singletonMap( public ElementMatcher<TypeDescription> typeMatcher() {
isMethod() return named("org.elasticsearch.client.RestClient");
.and(namedOneOf("performRequestAsync", "performRequestAsyncNoCatch")) }
.and(takesArguments(7))
.and(takesArgument(0, named("java.lang.String"))) // method @Override
.and(takesArgument(1, named("java.lang.String"))) // endpoint public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
.and(takesArgument(5, named("org.elasticsearch.client.ResponseListener"))), return singletonMap(
Elasticsearch5RestClientInstrumentation.class.getName() + "$ElasticsearchRestClientAdvice"); 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 { public static class ElasticsearchRestClientAdvice {

View File

@ -6,6 +6,7 @@
package io.opentelemetry.javaagent.instrumentation.elasticsearch.rest.v6_4; package io.opentelemetry.javaagent.instrumentation.elasticsearch.rest.v6_4;
import static io.opentelemetry.javaagent.instrumentation.elasticsearch.rest.ElasticsearchRestClientTracer.tracer; import static io.opentelemetry.javaagent.instrumentation.elasticsearch.rest.ElasticsearchRestClientTracer.tracer;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
@ -15,7 +16,9 @@ import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Scope; import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.List;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -24,10 +27,9 @@ import net.bytebuddy.matcher.ElementMatcher;
import org.elasticsearch.client.Request; import org.elasticsearch.client.Request;
import org.elasticsearch.client.ResponseListener; import org.elasticsearch.client.ResponseListener;
@AutoService(Instrumenter.class) @AutoService(InstrumentationModule.class)
public class Elasticsearch6RestClientInstrumentation extends Instrumenter.Default { public class Elasticsearch6RestClientInstrumentationModule extends InstrumentationModule {
public Elasticsearch6RestClientInstrumentationModule() {
public Elasticsearch6RestClientInstrumentation() {
super("elasticsearch", "elasticsearch-rest", "elasticsearch-rest-6"); super("elasticsearch", "elasticsearch-rest", "elasticsearch-rest-6");
} }
@ -40,19 +42,27 @@ public class Elasticsearch6RestClientInstrumentation extends Instrumenter.Defaul
} }
@Override @Override
public ElementMatcher<TypeDescription> typeMatcher() { public List<TypeInstrumentation> typeInstrumentations() {
return named("org.elasticsearch.client.RestClient"); return singletonList(new RestClientInstrumentation());
} }
@Override private static final class RestClientInstrumentation implements TypeInstrumentation {
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { @Override
return singletonMap( public ElementMatcher<TypeDescription> typeMatcher() {
isMethod() return named("org.elasticsearch.client.RestClient");
.and(named("performRequestAsyncNoCatch")) }
.and(takesArguments(2))
.and(takesArgument(0, named("org.elasticsearch.client.Request"))) @Override
.and(takesArgument(1, named("org.elasticsearch.client.ResponseListener"))), public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
Elasticsearch6RestClientInstrumentation.class.getName() + "$ElasticsearchRestClientAdvice"); 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 { public static class ElasticsearchRestClientAdvice {

View File

@ -6,6 +6,7 @@
package io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.v5_0; package io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.v5_0;
import static io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.ElasticsearchTransportClientTracer.tracer; import static io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.ElasticsearchTransportClientTracer.tracer;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
@ -14,7 +15,9 @@ import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Scope; import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.List;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -25,20 +28,12 @@ import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.ActionRequest; import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.ActionResponse; import org.elasticsearch.action.ActionResponse;
@AutoService(Instrumenter.class) @AutoService(InstrumentationModule.class)
public class Elasticsearch5TransportClientInstrumentation extends Instrumenter.Default { public class Elasticsearch5TransportClientInstrumentationModule extends InstrumentationModule {
public Elasticsearch5TransportClientInstrumentationModule() {
public Elasticsearch5TransportClientInstrumentation() {
super("elasticsearch", "elasticsearch-transport", "elasticsearch-transport-5"); super("elasticsearch", "elasticsearch-transport", "elasticsearch-transport-5");
} }
@Override
public ElementMatcher<TypeDescription> 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 @Override
public String[] helperClassNames() { public String[] helperClassNames() {
return new String[] { return new String[] {
@ -53,15 +48,29 @@ public class Elasticsearch5TransportClientInstrumentation extends Instrumenter.D
} }
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public List<TypeInstrumentation> typeInstrumentations() {
return singletonMap( return singletonList(new AbstractClientInstrumentation());
isMethod() }
.and(named("execute"))
.and(takesArgument(0, named("org.elasticsearch.action.Action"))) private static final class AbstractClientInstrumentation implements TypeInstrumentation {
.and(takesArgument(1, named("org.elasticsearch.action.ActionRequest"))) @Override
.and(takesArgument(2, named("org.elasticsearch.action.ActionListener"))), public ElementMatcher<TypeDescription> typeMatcher() {
Elasticsearch5TransportClientInstrumentation.class.getName() // If we want to be more generic, we could instrument the interface instead:
+ "$ElasticsearchTransportClientAdvice"); // .and(safeHasSuperType(named("org.elasticsearch.client.ElasticsearchClient"))))
return named("org.elasticsearch.client.support.AbstractClient");
}
@Override
public Map<? extends ElementMatcher<? super MethodDescription>, 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 { public static class ElasticsearchTransportClientAdvice {

View File

@ -6,6 +6,7 @@
package io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.v5_3; package io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.v5_3;
import static io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.ElasticsearchTransportClientTracer.tracer; import static io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.ElasticsearchTransportClientTracer.tracer;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
@ -14,7 +15,9 @@ import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Scope; import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.List;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -26,20 +29,12 @@ import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.ActionResponse; import org.elasticsearch.action.ActionResponse;
/** Beginning in version 5.3.0, DocumentRequest was renamed to DocWriteRequest. */ /** Beginning in version 5.3.0, DocumentRequest was renamed to DocWriteRequest. */
@AutoService(Instrumenter.class) @AutoService(InstrumentationModule.class)
public class Elasticsearch53TransportClientInstrumentation extends Instrumenter.Default { public class Elasticsearch53TransportClientInstrumentationModule extends InstrumentationModule {
public Elasticsearch53TransportClientInstrumentationModule() {
public Elasticsearch53TransportClientInstrumentation() {
super("elasticsearch", "elasticsearch-transport", "elasticsearch-transport-5"); super("elasticsearch", "elasticsearch-transport", "elasticsearch-transport-5");
} }
@Override
public ElementMatcher<TypeDescription> 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 @Override
public String[] helperClassNames() { public String[] helperClassNames() {
return new String[] { return new String[] {
@ -54,15 +49,29 @@ public class Elasticsearch53TransportClientInstrumentation extends Instrumenter.
} }
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public List<TypeInstrumentation> typeInstrumentations() {
return singletonMap( return singletonList(new AbstractClientInstrumentation());
isMethod() }
.and(named("execute"))
.and(takesArgument(0, named("org.elasticsearch.action.Action"))) private static final class AbstractClientInstrumentation implements TypeInstrumentation {
.and(takesArgument(1, named("org.elasticsearch.action.ActionRequest"))) @Override
.and(takesArgument(2, named("org.elasticsearch.action.ActionListener"))), public ElementMatcher<TypeDescription> typeMatcher() {
Elasticsearch53TransportClientInstrumentation.class.getName() // If we want to be more generic, we could instrument the interface instead:
+ "$ElasticsearchTransportClientAdvice"); // .and(safeHasSuperType(named("org.elasticsearch.client.ElasticsearchClient"))))
return named("org.elasticsearch.client.support.AbstractClient");
}
@Override
public Map<? extends ElementMatcher<? super MethodDescription>, 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 { public static class ElasticsearchTransportClientAdvice {

View File

@ -6,6 +6,7 @@
package io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.v6_0; package io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.v6_0;
import static io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.ElasticsearchTransportClientTracer.tracer; import static io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.ElasticsearchTransportClientTracer.tracer;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
@ -14,7 +15,9 @@ import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Scope; import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.List;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -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 * 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. * an abstract class, so the bytecode isn't directly compatible.
*/ */
@AutoService(Instrumenter.class) @AutoService(InstrumentationModule.class)
public class Elasticsearch6TransportClientInstrumentation extends Instrumenter.Default { public class Elasticsearch6TransportClientInstrumentationModule extends InstrumentationModule {
public Elasticsearch6TransportClientInstrumentationModule() {
public Elasticsearch6TransportClientInstrumentation() {
super("elasticsearch", "elasticsearch-transport", "elasticsearch-transport-6"); super("elasticsearch", "elasticsearch-transport", "elasticsearch-transport-6");
} }
@Override
public ElementMatcher<TypeDescription> 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 @Override
public String[] helperClassNames() { public String[] helperClassNames() {
return new String[] { return new String[] {
@ -57,15 +52,29 @@ public class Elasticsearch6TransportClientInstrumentation extends Instrumenter.D
} }
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public List<TypeInstrumentation> typeInstrumentations() {
return singletonMap( return singletonList(new AbstractClientInstrumentation());
isMethod() }
.and(named("execute"))
.and(takesArgument(0, named("org.elasticsearch.action.Action"))) private static final class AbstractClientInstrumentation implements TypeInstrumentation {
.and(takesArgument(1, named("org.elasticsearch.action.ActionRequest"))) @Override
.and(takesArgument(2, named("org.elasticsearch.action.ActionListener"))), public ElementMatcher<TypeDescription> typeMatcher() {
Elasticsearch6TransportClientInstrumentation.class.getName() // If we want to be more generic, we could instrument the interface instead:
+ "$Elasticsearch6TransportClientAdvice"); // .and(safeHasSuperType(named("org.elasticsearch.client.ElasticsearchClient"))))
return named("org.elasticsearch.client.support.AbstractClient");
}
@Override
public Map<? extends ElementMatcher<? super MethodDescription>, 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 { public static class Elasticsearch6TransportClientAdvice {

View File

@ -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<MethodDescription> configureExcludedMethods() {
ElementMatcher.Junction<MethodDescription> result = none();
Map<String, Set<String>> excludedMethods =
MethodsConfigurationParser.parse(
Config.get().getProperty(TRACE_ANNOTATED_METHODS_EXCLUDE_CONFIG));
for (Map.Entry<String, Set<String>> entry : excludedMethods.entrySet()) {
String className = entry.getKey();
ElementMatcher.Junction<ByteCodeElement> classMather =
isDeclaredBy(ElementMatchers.<TypeDescription>named(className));
ElementMatcher.Junction<MethodDescription> excludedMethodsMatcher = none();
for (String methodName : entry.getValue()) {
excludedMethodsMatcher = excludedMethodsMatcher.or(ElementMatchers.named(methodName));
}
result = result.or(classMather.and(excludedMethodsMatcher));
}
return result;
}
}

View File

@ -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<String> additionalTraceAnnotations;
private final ElementMatcher.Junction<NamedElement> traceAnnotationMatcher;
/*
This matcher matches all methods that should be excluded from transformation
*/
private final ElementMatcher.Junction<MethodDescription> 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<String> 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<NamedElement> 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<ClassLoader> classLoaderMatcher() {
// Optimization for expensive typeMatcher.
ElementMatcher.Junction<ClassLoader> 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<TypeDescription> typeMatcher() {
return safeHasSuperType(declaresMethod(isAnnotatedWith(traceAnnotationMatcher)));
}
@Override
public String[] helperClassNames() {
return new String[] {
packageName + ".TraceAnnotationTracer",
};
}
@Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap(
isAnnotatedWith(traceAnnotationMatcher).and(not(excludedMethodsMatcher)),
packageName + ".TraceAdvice");
}
}

View File

@ -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<TypeInstrumentation> typeInstrumentations() {
return singletonList(new AnnotatedMethodsInstrumentation());
}
private static final class AnnotatedMethodsInstrumentation implements TypeInstrumentation {
private final Set<String> additionalTraceAnnotations;
private final ElementMatcher.Junction<NamedElement> traceAnnotationMatcher;
/** This matcher matches all methods that should be excluded from transformation. */
private final ElementMatcher.Junction<MethodDescription> excludedMethodsMatcher;
public AnnotatedMethodsInstrumentation() {
additionalTraceAnnotations = configureAdditionalTraceAnnotations();
if (additionalTraceAnnotations.isEmpty()) {
traceAnnotationMatcher = none();
} else {
ElementMatcher.Junction<NamedElement> 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<ClassLoader> classLoaderMatcher() {
// Optimization for expensive typeMatcher.
ElementMatcher.Junction<ClassLoader> 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<TypeDescription> typeMatcher() {
return safeHasSuperType(declaresMethod(isAnnotatedWith(traceAnnotationMatcher)));
}
@Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap(
isAnnotatedWith(traceAnnotationMatcher).and(not(excludedMethodsMatcher)),
TraceAdvice.class.getName());
}
private static Set<String> 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<String> 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<MethodDescription> configureExcludedMethods() {
ElementMatcher.Junction<MethodDescription> result = none();
Map<String, Set<String>> excludedMethods =
MethodsConfigurationParser.parse(
Config.get().getProperty(TRACE_ANNOTATED_METHODS_EXCLUDE_CONFIG));
for (Map.Entry<String, Set<String>> entry : excludedMethods.entrySet()) {
String className = entry.getKey();
ElementMatcher.Junction<ByteCodeElement> classMather =
isDeclaredBy(ElementMatchers.named(className));
ElementMatcher.Junction<MethodDescription> excludedMethodsMatcher = none();
for (String methodName : entry.getValue()) {
excludedMethodsMatcher = excludedMethodsMatcher.or(ElementMatchers.named(methodName));
}
result = result.or(classMather.and(excludedMethodsMatcher));
}
return result;
}
}
}

View File

@ -12,11 +12,13 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import io.opentelemetry.instrumentation.api.config.Config; import io.opentelemetry.instrumentation.api.config.Config;
import io.opentelemetry.instrumentation.api.config.MethodsConfigurationParser; 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.Collections;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; 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.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@ -30,17 +32,19 @@ import net.bytebuddy.matcher.ElementMatcher;
* <p>If this becomes a more common use case the building logic should be abstracted out into a * <p>If this becomes a more common use case the building logic should be abstracted out into a
* super class. * super class.
*/ */
@AutoService(Instrumenter.class) @AutoService(InstrumentationModule.class)
public class TraceConfigInstrumentation implements Instrumenter { public class TraceConfigInstrumentationModule extends InstrumentationModule {
private static final String TRACE_METHODS_CONFIG = "otel.trace.methods"; private static final String TRACE_METHODS_CONFIG = "otel.trace.methods";
private static final String TRACE_ANNOTATED_METHODS_EXCLUDE_CONFIG = private static final String TRACE_ANNOTATED_METHODS_EXCLUDE_CONFIG =
"otel.trace.annotated.methods.exclude"; "otel.trace.annotated.methods.exclude";
private final Map<String, Set<String>> classMethodsToTrace; private final List<TypeInstrumentation> typeInstrumentations;
public TraceConfigInstrumentation() { public TraceConfigInstrumentationModule() {
classMethodsToTrace = super("trace", "trace-config");
Map<String, Set<String>> classMethodsToTrace =
MethodsConfigurationParser.parse(Config.get().getProperty(TRACE_METHODS_CONFIG)); MethodsConfigurationParser.parse(Config.get().getProperty(TRACE_METHODS_CONFIG));
Map<String, Set<String>> excludedMethods = Map<String, Set<String>> excludedMethods =
@ -52,39 +56,31 @@ public class TraceConfigInstrumentation implements Instrumenter {
tracedMethods.removeAll(entry.getValue()); 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 @Override
public AgentBuilder instrument(AgentBuilder agentBuilder) { public String[] helperClassNames() {
if (classMethodsToTrace.isEmpty()) { return new String[] {
return agentBuilder; packageName + ".TraceAnnotationTracer",
} };
for (Map.Entry<String, Set<String>> entry : classMethodsToTrace.entrySet()) {
TracerClassInstrumentation tracerConfigClass =
new TracerClassInstrumentation(entry.getKey(), entry.getValue());
agentBuilder = tracerConfigClass.instrument(agentBuilder);
}
return agentBuilder;
} }
@Override @Override
public int getOrder() { public List<TypeInstrumentation> typeInstrumentations() {
return 0; return typeInstrumentations;
} }
// Not Using AutoService to hook up this instrumentation private static final class TracerClassInstrumentation implements TypeInstrumentation {
public static class TracerClassInstrumentation extends Default {
private final String className; private final String className;
private final Set<String> methodNames; private final Set<String> 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<String> methodNames) { public TracerClassInstrumentation(String className, Set<String> methodNames) {
super("trace", "trace-config");
this.className = className; this.className = className;
this.methodNames = methodNames; this.methodNames = methodNames;
} }
@ -100,13 +96,6 @@ public class TraceConfigInstrumentation implements Instrumenter {
return safeHasSuperType(named(className)); return safeHasSuperType(named(className));
} }
@Override
public String[] helperClassNames() {
return new String[] {
packageName + ".TraceAnnotationTracer",
};
}
@Override @Override
public Map<ElementMatcher<? super MethodDescription>, String> transformers() { public Map<ElementMatcher<? super MethodDescription>, String> transformers() {
ElementMatcher.Junction<MethodDescription> methodMatchers = null; ElementMatcher.Junction<MethodDescription> methodMatchers = null;
@ -118,8 +107,7 @@ public class TraceConfigInstrumentation implements Instrumenter {
} }
} }
return Collections.<ElementMatcher<? super MethodDescription>, String>singletonMap( return Collections.singletonMap(methodMatchers, TraceAdvice.class.getName());
methodMatchers, packageName + ".TraceAdvice");
} }
} }
} }

View File

@ -3,11 +3,11 @@
* SPDX-License-Identifier: Apache-2.0 * 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.AgentTestRunner
import io.opentelemetry.instrumentation.test.utils.ConfigUtils 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 io.opentelemetry.test.annotation.SayTracedHello
import java.util.concurrent.Callable import java.util.concurrent.Callable
@ -55,7 +55,7 @@ class ConfiguredTraceAnnotationsTest extends AgentTestRunner {
} }
expect: expect:
new TraceAnnotationsInstrumentation().additionalTraceAnnotations == expected.toSet() new TraceAnnotationsInstrumentationModule.AnnotatedMethodsInstrumentation().additionalTraceAnnotations == expected.toSet()
cleanup: cleanup:
ConfigUtils.setConfig(previousConfig) ConfigUtils.setConfig(previousConfig)

View File

@ -13,6 +13,7 @@ import io.opentelemetry.test.annotation.SayTracedHello
class TraceProvidersTest extends AgentTestRunner { class TraceProvidersTest extends AgentTestRunner {
//Don't bother to instrument inner closures of this test class //Don't bother to instrument inner closures of this test class
static final PREVIOUS_CONFIG = ConfigUtils.updateConfigAndResetInstrumentation { static final PREVIOUS_CONFIG = ConfigUtils.updateConfigAndResetInstrumentation {
it.remove("otel.trace.annotations")
it.setProperty("otel.trace.classes.exclude", TraceProvidersTest.name + "*") it.setProperty("otel.trace.classes.exclude", TraceProvidersTest.name + "*")
} }

View File

@ -8,6 +8,7 @@ package io.opentelemetry.javaagent.instrumentation.finatra;
import static io.opentelemetry.javaagent.instrumentation.finatra.FinatraTracer.tracer; import static io.opentelemetry.javaagent.instrumentation.finatra.FinatraTracer.tracer;
import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; 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.api.trace.Span;
import io.opentelemetry.instrumentation.api.tracer.BaseTracer; import io.opentelemetry.instrumentation.api.tracer.BaseTracer;
import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.List;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -31,47 +34,54 @@ import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
import scala.Some; import scala.Some;
@AutoService(Instrumenter.class) @AutoService(InstrumentationModule.class)
public class FinatraInstrumentation extends Instrumenter.Default { public class FinatraInstrumentationModule extends InstrumentationModule {
public FinatraInstrumentation() { public FinatraInstrumentationModule() {
super("finatra"); super("finatra");
} }
@Override @Override
public String[] helperClassNames() { public String[] helperClassNames() {
return new String[] { return new String[] {
packageName + ".FinatraTracer", FinatraInstrumentation.class.getName() + "$Listener" packageName + ".FinatraTracer", FinatraInstrumentationModule.class.getName() + "$Listener"
}; };
} }
@Override @Override
public ElementMatcher<ClassLoader> classLoaderMatcher() { public List<TypeInstrumentation> typeInstrumentations() {
// Optimization for expensive typeMatcher. return singletonList(new RouteInstrumentation());
return hasClassesNamed("com.twitter.finatra.http.internal.routing.Route");
} }
@Override private static final class RouteInstrumentation implements TypeInstrumentation {
public ElementMatcher<? super TypeDescription> typeMatcher() { @Override
return nameStartsWith("com.twitter.finatra.") public ElementMatcher<ClassLoader> classLoaderMatcher() {
.<TypeDescription>and( // Optimization for expensive typeMatcher.
extendsClass(named("com.twitter.finatra.http.internal.routing.Route"))); return hasClassesNamed("com.twitter.finatra.http.internal.routing.Route");
} }
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public ElementMatcher<? super TypeDescription> typeMatcher() {
return singletonMap( return nameStartsWith("com.twitter.finatra.")
isMethod() .<TypeDescription>and(
.and(named("handleMatch")) extendsClass(named("com.twitter.finatra.http.internal.routing.Route")));
.and(takesArguments(2)) }
.and(takesArgument(0, named("com.twitter.finagle.http.Request"))),
FinatraInstrumentation.class.getName() + "$RouteAdvice"); @Override
public Map<? extends ElementMatcher<? super MethodDescription>, 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 { public static class RouteAdvice {
@Advice.OnMethodEnter(suppress = Throwable.class) @Advice.OnMethodEnter(suppress = Throwable.class)
public static SpanWithScope nameSpan( public static SpanWithScope nameSpan(
@Advice.FieldValue("routeInfo") RouteInfo routeInfo, @Advice.FieldValue("routeInfo") RouteInfo routeInfo,
@Advice.FieldValue("clazz") Class clazz) { @Advice.FieldValue("clazz") Class<?> clazz) {
Span serverSpan = BaseTracer.getCurrentServerSpan(); Span serverSpan = BaseTracer.getCurrentServerSpan();
if (serverSpan != null) { if (serverSpan != null) {

View File

@ -6,7 +6,9 @@
package io.opentelemetry.javaagent.instrumentation.geode; package io.opentelemetry.javaagent.instrumentation.geode;
import static io.opentelemetry.javaagent.instrumentation.geode.GeodeTracer.tracer; 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 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.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
import static net.bytebuddy.matcher.ElementMatchers.named; 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.api.trace.Span;
import io.opentelemetry.context.Scope; import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -26,17 +30,12 @@ import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
import org.apache.geode.cache.Region; import org.apache.geode.cache.Region;
@AutoService(Instrumenter.class) @AutoService(InstrumentationModule.class)
public class GeodeInstrumentation extends Instrumenter.Default { public class GeodeInstrumentationModule extends InstrumentationModule {
public GeodeInstrumentation() { public GeodeInstrumentationModule() {
super("geode", "geode-client"); super("geode", "geode-client");
} }
@Override
public ElementMatcher<? super TypeDescription> typeMatcher() {
return hasInterface(named("org.apache.geode.cache.Region"));
}
@Override @Override
public String[] helperClassNames() { public String[] helperClassNames() {
return new String[] { return new String[] {
@ -45,30 +44,48 @@ public class GeodeInstrumentation extends Instrumenter.Default {
} }
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public List<TypeInstrumentation> typeInstrumentations() {
Map<ElementMatcher<? super MethodDescription>, String> map = new HashMap<>(2); return singletonList(new RegionInstrumentation());
map.put( }
isMethod()
.and( private static final class RegionInstrumentation implements TypeInstrumentation {
named("clear") @Override
.or(nameStartsWith("contains")) public ElementMatcher<ClassLoader> classLoaderMatcher() {
.or(named("create")) // optimization for expensive typeMatcher
.or(named("destroy")) return hasClassesNamed("org.apache.geode.cache.Region");
.or(named("entrySet")) }
.or(named("get"))
.or(named("getAll")) @Override
.or(named("invalidate")) public ElementMatcher<? super TypeDescription> typeMatcher() {
.or(nameStartsWith("keySet")) return hasInterface(named("org.apache.geode.cache.Region"));
.or(nameStartsWith("put")) }
.or(nameStartsWith("remove"))
.or(named("replace"))), @Override
GeodeInstrumentation.class.getName() + "$SimpleAdvice"); public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
map.put( Map<ElementMatcher<? super MethodDescription>, String> map = new HashMap<>(2);
isMethod() map.put(
.and(named("existsValue").or(named("query")).or(named("selectValue"))) isMethod()
.and(takesArgument(0, named("java.lang.String"))), .and(
GeodeInstrumentation.class.getName() + "$QueryAdvice"); named("clear")
return map; .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 { public static class SimpleAdvice {

View File

@ -6,6 +6,7 @@
package io.opentelemetry.javaagent.instrumentation.googlehttpclient; package io.opentelemetry.javaagent.instrumentation.googlehttpclient;
import static io.opentelemetry.javaagent.instrumentation.googlehttpclient.GoogleHttpClientTracer.tracer; import static io.opentelemetry.javaagent.instrumentation.googlehttpclient.GoogleHttpClientTracer.tracer;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.isPublic; 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.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class) @AutoService(InstrumentationModule.class)
public class GoogleHttpClientInstrumentation extends Instrumenter.Default { public class GoogleHttpClientInstrumentationModule extends InstrumentationModule {
public GoogleHttpClientInstrumentation() { public GoogleHttpClientInstrumentationModule() {
super("google-http-client"); super("google-http-client");
} }
@Override
public ElementMatcher<? super TypeDescription> 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 @Override
public Map<String, String> contextStore() { public Map<String, String> contextStore() {
return singletonMap("com.google.api.client.http.HttpRequest", Context.class.getName()); return singletonMap("com.google.api.client.http.HttpRequest", Context.class.getName());
@ -58,21 +53,36 @@ public class GoogleHttpClientInstrumentation extends Instrumenter.Default {
} }
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public List<TypeInstrumentation> typeInstrumentations() {
Map<ElementMatcher<? super MethodDescription>, String> transformers = new HashMap<>(); return singletonList(new HttpRequestInstrumentation());
transformers.put( }
isMethod().and(isPublic()).and(named("execute")).and(takesArguments(0)),
GoogleHttpClientInstrumentation.class.getName() + "$GoogleHttpClientAdvice");
transformers.put( private static final class HttpRequestInstrumentation implements TypeInstrumentation {
isMethod() @Override
.and(isPublic()) public ElementMatcher<? super TypeDescription> typeMatcher() {
.and(named("executeAsync")) // HttpRequest is a final class. Only need to instrument it exactly
.and(takesArguments(1)) // Note: the rest of com.google.api is ignored in AdditionalLibraryIgnoresMatcher to speed
.and(takesArgument(0, (named("java.util.concurrent.Executor")))), // things up
GoogleHttpClientInstrumentation.class.getName() + "$GoogleHttpClientAsyncAdvice"); return named("com.google.api.client.http.HttpRequest");
}
return transformers; @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
Map<ElementMatcher<? super MethodDescription>, 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 { public static class GoogleHttpClientAdvice {

View File

@ -10,36 +10,20 @@ import static net.bytebuddy.matcher.ElementMatchers.isPrivate;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class) final class DefaultFilterChainInstrumentation implements TypeInstrumentation {
public class DefaultFilterChainInstrumentation extends Instrumenter.Default {
public DefaultFilterChainInstrumentation() {
super("grizzly");
}
@Override @Override
public ElementMatcher<? super TypeDescription> typeMatcher() { public ElementMatcher<? super TypeDescription> typeMatcher() {
return named("org.glassfish.grizzly.filterchain.DefaultFilterChain"); 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 @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return Collections.singletonMap( return Collections.singletonMap(
@ -48,6 +32,6 @@ public class DefaultFilterChainInstrumentation extends Instrumenter.Default {
.and(named("notifyFailure")) .and(named("notifyFailure"))
.and(takesArgument(0, named("org.glassfish.grizzly.filterchain.FilterChainContext"))) .and(takesArgument(0, named("org.glassfish.grizzly.filterchain.FilterChainContext")))
.and(takesArgument(1, named("java.lang.Throwable"))), .and(takesArgument(1, named("java.lang.Throwable"))),
packageName + ".DefaultFilterChainAdvice"); DefaultFilterChainAdvice.class.getName());
} }
} }

View File

@ -13,20 +13,14 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.not; import static net.bytebuddy.matcher.ElementMatchers.not;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import java.util.Map; import java.util.Map;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers; import net.bytebuddy.matcher.ElementMatchers;
@AutoService(Instrumenter.class) final class FilterInstrumentation implements TypeInstrumentation {
public final class FilterInstrumentation extends Instrumenter.Default {
public FilterInstrumentation() {
super("grizzly");
}
@Override @Override
public ElementMatcher<ClassLoader> classLoaderMatcher() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
@ -47,22 +41,12 @@ public final class FilterInstrumentation extends Instrumenter.Default {
"org.glassfish.grizzly.http.HttpServerFilter"))); "org.glassfish.grizzly.http.HttpServerFilter")));
} }
@Override
public String[] helperClassNames() {
return new String[] {packageName + ".GrizzlyHttpServerTracer", packageName + ".ExtractAdapter"};
}
@Override
protected boolean defaultEnabled() {
return false;
}
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap( return singletonMap(
named("handleRead") named("handleRead")
.and(takesArgument(0, named("org.glassfish.grizzly.filterchain.FilterChainContext"))) .and(takesArgument(0, named("org.glassfish.grizzly.filterchain.FilterChainContext")))
.and(isPublic()), .and(isPublic()),
packageName + ".FilterAdvice"); FilterAdvice.class.getName());
} }
} }

View File

@ -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<TypeInstrumentation> typeInstrumentations() {
return asList(
new DefaultFilterChainInstrumentation(),
new FilterInstrumentation(),
new HttpCodecFilterInstrumentation(),
new HttpServerFilterInstrumentation());
}
@Override
protected boolean defaultEnabled() {
return false;
}
}

View File

@ -9,36 +9,20 @@ import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class) final class HttpCodecFilterInstrumentation implements TypeInstrumentation {
public final class HttpCodecFilterInstrumentation extends Instrumenter.Default {
public HttpCodecFilterInstrumentation() {
super("grizzly");
}
@Override @Override
public ElementMatcher<? super TypeDescription> typeMatcher() { public ElementMatcher<? super TypeDescription> typeMatcher() {
return named("org.glassfish.grizzly.http.HttpCodecFilter"); 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 @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
Map<ElementMatcher<? super MethodDescription>, String> transformers = new HashMap<>(); Map<ElementMatcher<? super MethodDescription>, String> transformers = new HashMap<>();
@ -48,14 +32,14 @@ public final class HttpCodecFilterInstrumentation extends Instrumenter.Default {
.and(takesArgument(0, named("org.glassfish.grizzly.filterchain.FilterChainContext"))) .and(takesArgument(0, named("org.glassfish.grizzly.filterchain.FilterChainContext")))
.and(takesArgument(1, named("org.glassfish.grizzly.http.HttpPacketParsing"))) .and(takesArgument(1, named("org.glassfish.grizzly.http.HttpPacketParsing")))
.and(isPublic()), .and(isPublic()),
packageName + ".HttpCodecFilterOldAdvice"); HttpCodecFilterOldAdvice.class.getName());
// this is for 2.3.20+ // this is for 2.3.20+
transformers.put( transformers.put(
named("handleRead") named("handleRead")
.and(takesArgument(0, named("org.glassfish.grizzly.filterchain.FilterChainContext"))) .and(takesArgument(0, named("org.glassfish.grizzly.filterchain.FilterChainContext")))
.and(takesArgument(1, named("org.glassfish.grizzly.http.HttpHeader"))) .and(takesArgument(1, named("org.glassfish.grizzly.http.HttpHeader")))
.and(isPublic()), .and(isPublic()),
packageName + ".HttpCodecFilterAdvice"); HttpCodecFilterAdvice.class.getName());
return transformers; return transformers;
} }
} }

View File

@ -9,36 +9,20 @@ import static net.bytebuddy.matcher.ElementMatchers.isPrivate;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class) final class HttpServerFilterInstrumentation implements TypeInstrumentation {
public class HttpServerFilterInstrumentation extends Instrumenter.Default {
public HttpServerFilterInstrumentation() {
super("grizzly");
}
@Override @Override
public ElementMatcher<? super TypeDescription> typeMatcher() { public ElementMatcher<? super TypeDescription> typeMatcher() {
return named("org.glassfish.grizzly.http.HttpServerFilter"); 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 @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return Collections.singletonMap( return Collections.singletonMap(
@ -48,6 +32,6 @@ public class HttpServerFilterInstrumentation extends Instrumenter.Default {
.and(takesArgument(2, named("org.glassfish.grizzly.http.HttpResponsePacket"))) .and(takesArgument(2, named("org.glassfish.grizzly.http.HttpResponsePacket")))
.and(takesArgument(3, named("org.glassfish.grizzly.http.HttpContent"))) .and(takesArgument(3, named("org.glassfish.grizzly.http.HttpContent")))
.and(isPrivate()), .and(isPrivate()),
packageName + ".HttpServerFilterAdvice"); HttpServerFilterAdvice.class.getName());
} }
} }

View File

@ -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<TypeInstrumentation> typeInstrumentations() {
return asList(
new GrizzlyClientRequestInstrumentation(), new GrizzlyClientResponseInstrumentation());
}
@Override
public Map<String, String> contextStore() {
return singletonMap("com.ning.http.client.AsyncHandler", Pair.class.getName());
}
@Override
protected boolean defaultEnabled() {
return false;
}
}

View File

@ -10,43 +10,19 @@ import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import io.opentelemetry.javaagent.instrumentation.api.Pair;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import java.util.Map; import java.util.Map;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class) final class GrizzlyClientRequestInstrumentation implements TypeInstrumentation {
public final class GrizzlyClientRequestInstrumentation extends Instrumenter.Default {
public GrizzlyClientRequestInstrumentation() {
super("grizzly-client", "ning");
}
@Override
public Map<String, String> contextStore() {
return singletonMap("com.ning.http.client.AsyncHandler", Pair.class.getName());
}
@Override @Override
public ElementMatcher<? super TypeDescription> typeMatcher() { public ElementMatcher<? super TypeDescription> typeMatcher() {
return named("com.ning.http.client.AsyncHttpClient"); 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 @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap( return singletonMap(
@ -54,6 +30,6 @@ public final class GrizzlyClientRequestInstrumentation extends Instrumenter.Defa
.and(takesArgument(0, named("com.ning.http.client.Request"))) .and(takesArgument(0, named("com.ning.http.client.Request")))
.and(takesArgument(1, named("com.ning.http.client.AsyncHandler"))) .and(takesArgument(1, named("com.ning.http.client.AsyncHandler")))
.and(isPublic()), .and(isPublic()),
packageName + ".GrizzlyClientRequestAdvice"); GrizzlyClientRequestAdvice.class.getName());
} }
} }

View File

@ -12,54 +12,30 @@ import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import io.opentelemetry.javaagent.instrumentation.api.Pair;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import java.util.Map; import java.util.Map;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class) final class GrizzlyClientResponseInstrumentation implements TypeInstrumentation {
public final class GrizzlyClientResponseInstrumentation extends Instrumenter.Default {
public GrizzlyClientResponseInstrumentation() {
super("grizzly-client", "ning");
}
@Override
public Map<String, String> contextStore() {
return singletonMap("com.ning.http.client.AsyncHandler", Pair.class.getName());
}
@Override @Override
public ElementMatcher<ClassLoader> classLoaderMatcher() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
return hasClassesNamed("com.ning.http.client.AsyncCompletionHandler"); return hasClassesNamed("com.ning.http.client.AsyncCompletionHandler");
} }
@Override
protected boolean defaultEnabled() {
return false;
}
@Override @Override
public ElementMatcher<? super TypeDescription> typeMatcher() { public ElementMatcher<? super TypeDescription> typeMatcher() {
return hasSuperClass(named("com.ning.http.client.AsyncCompletionHandler")); return hasSuperClass(named("com.ning.http.client.AsyncCompletionHandler"));
} }
@Override
public String[] helperClassNames() {
return new String[] {
packageName + ".GrizzlyClientTracer", packageName + ".GrizzlyInjectAdapter"
};
}
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap( return singletonMap(
named("onCompleted") named("onCompleted")
.and(takesArgument(0, named("com.ning.http.client.Response"))) .and(takesArgument(0, named("com.ning.http.client.Response")))
.and(isPublic()), .and(isPublic()),
packageName + ".GrizzlyClientResponseAdvice"); GrizzlyClientResponseAdvice.class.getName());
} }
} }

View File

@ -5,16 +5,16 @@
package io.opentelemetry.javaagent.instrumentation.grpc.v1_5; 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 io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.declaresField; import static net.bytebuddy.matcher.ElementMatchers.declaresField;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.grpc.ClientInterceptor; import io.grpc.ClientInterceptor;
import io.opentelemetry.instrumentation.grpc.v1_5.client.TracingClientInterceptor; 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.List;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
@ -22,8 +22,12 @@ import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class) final class GrpcClientBuilderBuildInstrumentation implements TypeInstrumentation {
public class GrpcClientBuilderBuildInstrumentation extends AbstractGrpcInstrumentation { @Override
public ElementMatcher<ClassLoader> classLoaderMatcher() {
// optimization for expensive typeMatcher
return hasClassesNamed("io.grpc.ManagedChannelBuilder");
}
@Override @Override
public ElementMatcher<TypeDescription> typeMatcher() { public ElementMatcher<TypeDescription> typeMatcher() {

View File

@ -5,16 +5,21 @@
package io.opentelemetry.javaagent.instrumentation.grpc.v1_5; 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"); super("grpc");
} }
@Override @Override
public final String[] helperClassNames() { public String[] helperClassNames() {
return new String[] { return new String[] {
"io.opentelemetry.instrumentation.grpc.v1_5.common.GrpcHelper", "io.opentelemetry.instrumentation.grpc.v1_5.common.GrpcHelper",
"io.opentelemetry.instrumentation.grpc.v1_5.client.GrpcClientTracer", "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", "io.opentelemetry.instrumentation.grpc.v1_5.server.TracingServerInterceptor$TracingServerCallListener",
}; };
} }
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return asList(
new GrpcClientBuilderBuildInstrumentation(), new GrpcServerBuilderInstrumentation());
}
} }

View File

@ -9,10 +9,9 @@ import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.grpc.ServerInterceptor; import io.grpc.ServerInterceptor;
import io.opentelemetry.instrumentation.grpc.v1_5.server.TracingServerInterceptor; 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.List;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
@ -20,8 +19,7 @@ import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class) final class GrpcServerBuilderInstrumentation implements TypeInstrumentation {
public class GrpcServerBuilderInstrumentation extends AbstractGrpcInstrumentation {
@Override @Override
public ElementMatcher<TypeDescription> typeMatcher() { public ElementMatcher<TypeDescription> typeMatcher() {

View File

@ -5,6 +5,7 @@
package io.opentelemetry.javaagent.instrumentation.guava; package io.opentelemetry.javaagent.instrumentation.guava;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
@ -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.ExecutorInstrumentationUtils;
import io.opentelemetry.javaagent.instrumentation.api.concurrent.RunnableWrapper; import io.opentelemetry.javaagent.instrumentation.api.concurrent.RunnableWrapper;
import io.opentelemetry.javaagent.instrumentation.api.concurrent.State; import io.opentelemetry.javaagent.instrumentation.api.concurrent.State;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
@ -26,16 +29,16 @@ import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers; import net.bytebuddy.matcher.ElementMatchers;
@AutoService(Instrumenter.class) @AutoService(InstrumentationModule.class)
public class ListenableFutureInstrumentation extends Instrumenter.Default { public class GuavaInstrumentationModule extends InstrumentationModule {
public ListenableFutureInstrumentation() { public GuavaInstrumentationModule() {
super("guava"); super("guava");
} }
@Override @Override
public ElementMatcher<TypeDescription> typeMatcher() { public List<TypeInstrumentation> typeInstrumentations() {
return named("com.google.common.util.concurrent.AbstractFuture"); return singletonList(new ListenableFutureInstrumentation());
} }
@Override @Override
@ -43,11 +46,18 @@ public class ListenableFutureInstrumentation extends Instrumenter.Default {
return singletonMap(Runnable.class.getName(), State.class.getName()); return singletonMap(Runnable.class.getName(), State.class.getName());
} }
@Override private static final class ListenableFutureInstrumentation implements TypeInstrumentation {
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { @Override
return singletonMap( public ElementMatcher<TypeDescription> typeMatcher() {
named("addListener").and(ElementMatchers.takesArguments(Runnable.class, Executor.class)), return named("com.google.common.util.concurrent.AbstractFuture");
ListenableFutureInstrumentation.class.getName() + "$AddListenerAdvice"); }
@Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap(
named("addListener").and(ElementMatchers.takesArguments(Runnable.class, Executor.class)),
GuavaInstrumentationModule.class.getName() + "$AddListenerAdvice");
}
} }
public static class AddListenerAdvice { public static class AddListenerAdvice {

View File

@ -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<ClassLoader> 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();
}
}
}

View File

@ -5,19 +5,19 @@
package io.opentelemetry.javaagent.instrumentation.hibernate.v3_3; 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.bytebuddy.matcher.AgentElementMatchers.implementsInterface;
import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.context.Context; import io.opentelemetry.context.Context;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore; import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope;
import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -26,12 +26,12 @@ import net.bytebuddy.implementation.bytecode.assign.Assigner;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
import org.hibernate.Criteria; import org.hibernate.Criteria;
@AutoService(Instrumenter.class) final class CriteriaInstrumentation implements TypeInstrumentation {
public class CriteriaInstrumentation extends AbstractHibernateInstrumentation {
@Override @Override
public Map<String, String> contextStore() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
return singletonMap("org.hibernate.Criteria", Context.class.getName()); // Optimization for expensive typeMatcher.
return hasClassesNamed("org.hibernate.Criteria");
} }
@Override @Override

View File

@ -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<TypeInstrumentation> typeInstrumentations() {
return asList(
new CriteriaInstrumentation(),
new QueryInstrumentation(),
new SessionFactoryInstrumentation(),
new SessionInstrumentation(),
new TransactionInstrumentation());
}
@Override
public Map<String, String> contextStore() {
Map<String, String> 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);
}
}

View File

@ -5,19 +5,19 @@
package io.opentelemetry.javaagent.instrumentation.hibernate.v3_3; 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.bytebuddy.matcher.AgentElementMatchers.implementsInterface;
import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.context.Context; import io.opentelemetry.context.Context;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore; import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope;
import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -25,12 +25,12 @@ import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
import org.hibernate.Query; import org.hibernate.Query;
@AutoService(Instrumenter.class) final class QueryInstrumentation implements TypeInstrumentation {
public class QueryInstrumentation extends AbstractHibernateInstrumentation {
@Override @Override
public Map<String, String> contextStore() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
return singletonMap("org.hibernate.Query", Context.class.getName()); // Optimization for expensive typeMatcher.
return hasClassesNamed("org.hibernate.Query");
} }
@Override @Override

View File

@ -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.DECORATE;
import static io.opentelemetry.javaagent.instrumentation.hibernate.HibernateDecorator.tracer; 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.hasInterface;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface;
import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf;
@ -16,14 +17,12 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.returns; import static net.bytebuddy.matcher.ElementMatchers.returns;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments; import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import com.google.auto.service.AutoService;
import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Context; import io.opentelemetry.context.Context;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore; import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -32,16 +31,12 @@ import net.bytebuddy.matcher.ElementMatcher;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.StatelessSession; import org.hibernate.StatelessSession;
@AutoService(Instrumenter.class) final class SessionFactoryInstrumentation implements TypeInstrumentation {
public class SessionFactoryInstrumentation extends AbstractHibernateInstrumentation {
@Override @Override
public Map<String, String> contextStore() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
Map<String, String> stores = new HashMap<>(); // Optimization for expensive typeMatcher.
stores.put("org.hibernate.Session", Context.class.getName()); return hasClassesNamed("org.hibernate.SessionFactory");
stores.put("org.hibernate.StatelessSession", Context.class.getName());
stores.put("org.hibernate.SharedSessionContract", Context.class.getName());
return stores;
} }
@Override @Override

View File

@ -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.DECORATE;
import static io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils.SCOPE_ONLY_METHODS; 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.hasInterface;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface;
import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf;
@ -16,7 +17,6 @@ import static net.bytebuddy.matcher.ElementMatchers.returns;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments; import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import com.google.auto.service.AutoService;
import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Context; import io.opentelemetry.context.Context;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore; 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.Java8BytecodeBridge;
import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope;
import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
@ -39,18 +38,12 @@ import org.hibernate.Session;
import org.hibernate.StatelessSession; import org.hibernate.StatelessSession;
import org.hibernate.Transaction; import org.hibernate.Transaction;
@AutoService(Instrumenter.class) final class SessionInstrumentation implements TypeInstrumentation {
public class SessionInstrumentation extends AbstractHibernateInstrumentation {
@Override @Override
public Map<String, String> contextStore() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
Map<String, String> map = new HashMap<>(); // Optimization for expensive typeMatcher.
map.put("org.hibernate.Session", Context.class.getName()); return hasClassesNamed("org.hibernate.Session", "org.hibernate.StatelessSession");
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);
} }
@Override @Override

View File

@ -5,19 +5,19 @@
package io.opentelemetry.javaagent.instrumentation.hibernate.v3_3; 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.bytebuddy.matcher.AgentElementMatchers.implementsInterface;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments; import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import com.google.auto.service.AutoService;
import io.opentelemetry.context.Context; import io.opentelemetry.context.Context;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore; import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope;
import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -25,12 +25,12 @@ import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
import org.hibernate.Transaction; import org.hibernate.Transaction;
@AutoService(Instrumenter.class) final class TransactionInstrumentation implements TypeInstrumentation {
public class TransactionInstrumentation extends AbstractHibernateInstrumentation {
@Override @Override
public Map<String, String> contextStore() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
return singletonMap("org.hibernate.Transaction", Context.class.getName()); // Optimization for expensive typeMatcher.
return hasClassesNamed("org.hibernate.Transaction");
} }
@Override @Override

View File

@ -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();
}
}

View File

@ -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<ClassLoader> 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("");
}
}
}

View File

@ -5,19 +5,19 @@
package io.opentelemetry.javaagent.instrumentation.hibernate.v4_0; 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.bytebuddy.matcher.AgentElementMatchers.implementsInterface;
import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.context.Context; import io.opentelemetry.context.Context;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore; import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope;
import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -26,12 +26,12 @@ import net.bytebuddy.implementation.bytecode.assign.Assigner;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
import org.hibernate.Criteria; import org.hibernate.Criteria;
@AutoService(Instrumenter.class) final class CriteriaInstrumentation implements TypeInstrumentation {
public class CriteriaInstrumentation extends AbstractHibernateInstrumentation {
@Override @Override
public Map<String, String> contextStore() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
return singletonMap("org.hibernate.Criteria", Context.class.getName()); // Optimization for expensive typeMatcher.
return hasClassesNamed("org.hibernate.Criteria");
} }
@Override @Override

View File

@ -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<TypeInstrumentation> typeInstrumentations() {
return asList(
new CriteriaInstrumentation(),
new QueryInstrumentation(),
new SessionFactoryInstrumentation(),
new SessionInstrumentation(),
new TransactionInstrumentation());
}
@Override
public Map<String, String> contextStore() {
Map<String, String> 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);
}
}

View File

@ -5,19 +5,19 @@
package io.opentelemetry.javaagent.instrumentation.hibernate.v4_0; 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.bytebuddy.matcher.AgentElementMatchers.implementsInterface;
import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.context.Context; import io.opentelemetry.context.Context;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore; import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope;
import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -25,12 +25,12 @@ import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
import org.hibernate.Query; import org.hibernate.Query;
@AutoService(Instrumenter.class) final class QueryInstrumentation implements TypeInstrumentation {
public class QueryInstrumentation extends AbstractHibernateInstrumentation {
@Override @Override
public Map<String, String> contextStore() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
return singletonMap("org.hibernate.Query", Context.class.getName()); // Optimization for expensive typeMatcher.
return hasClassesNamed("org.hibernate.Query");
} }
@Override @Override

View File

@ -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.DECORATE;
import static io.opentelemetry.javaagent.instrumentation.hibernate.HibernateDecorator.tracer; 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.bytebuddy.matcher.AgentElementMatchers.implementsInterface;
import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf;
import static java.util.Collections.singletonMap; 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.returns;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments; import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import com.google.auto.service.AutoService;
import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Context; import io.opentelemetry.context.Context;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore; import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -29,12 +29,12 @@ import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
import org.hibernate.SharedSessionContract; import org.hibernate.SharedSessionContract;
@AutoService(Instrumenter.class) final class SessionFactoryInstrumentation implements TypeInstrumentation {
public class SessionFactoryInstrumentation extends AbstractHibernateInstrumentation {
@Override @Override
public Map<String, String> contextStore() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
return singletonMap("org.hibernate.SharedSessionContract", Context.class.getName()); // Optimization for expensive typeMatcher.
return hasClassesNamed("org.hibernate.SessionFactory");
} }
@Override @Override

View File

@ -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.DECORATE;
import static io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils.SCOPE_ONLY_METHODS; 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.hasInterface;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface;
import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf;
@ -16,7 +17,6 @@ import static net.bytebuddy.matcher.ElementMatchers.returns;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments; import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import com.google.auto.service.AutoService;
import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Context; import io.opentelemetry.context.Context;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore; 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.Java8BytecodeBridge;
import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope;
import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
@ -38,17 +37,12 @@ import org.hibernate.Query;
import org.hibernate.SharedSessionContract; import org.hibernate.SharedSessionContract;
import org.hibernate.Transaction; import org.hibernate.Transaction;
@AutoService(Instrumenter.class) final class SessionInstrumentation implements TypeInstrumentation {
public class SessionInstrumentation extends AbstractHibernateInstrumentation {
@Override @Override
public Map<String, String> contextStore() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
Map<String, String> map = new HashMap<>(); // Optimization for expensive typeMatcher.
map.put("org.hibernate.SharedSessionContract", Context.class.getName()); return hasClassesNamed("org.hibernate.SharedSessionContract");
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);
} }
@Override @Override

View File

@ -5,19 +5,19 @@
package io.opentelemetry.javaagent.instrumentation.hibernate.v4_0; 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.bytebuddy.matcher.AgentElementMatchers.implementsInterface;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments; import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import com.google.auto.service.AutoService;
import io.opentelemetry.context.Context; import io.opentelemetry.context.Context;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore; import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope;
import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -25,12 +25,12 @@ import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
import org.hibernate.Transaction; import org.hibernate.Transaction;
@AutoService(Instrumenter.class) final class TransactionInstrumentation implements TypeInstrumentation {
public class TransactionInstrumentation extends AbstractHibernateInstrumentation {
@Override @Override
public Map<String, String> contextStore() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
return singletonMap("org.hibernate.Transaction", Context.class.getName()); // Optimization for expensive typeMatcher.
return hasClassesNamed("org.hibernate.Transaction");
} }
@Override @Override

View File

@ -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("");
}
}

View File

@ -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<TypeInstrumentation> typeInstrumentations() {
return asList(new ProcedureCallInstrumentation(), new SessionInstrumentation());
}
@Override
public Map<String, String> contextStore() {
Map<String, String> map = new HashMap<>();
map.put("org.hibernate.SharedSessionContract", Context.class.getName());
map.put("org.hibernate.procedure.ProcedureCall", Context.class.getName());
return Collections.unmodifiableMap(map);
}
}

View File

@ -11,13 +11,12 @@ import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.context.Context; import io.opentelemetry.context.Context;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore; import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope;
import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -25,30 +24,12 @@ import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
import org.hibernate.procedure.ProcedureCall; import org.hibernate.procedure.ProcedureCall;
@AutoService(Instrumenter.class) final class ProcedureCallInstrumentation implements TypeInstrumentation {
public class ProcedureCallInstrumentation extends Instrumenter.Default {
public ProcedureCallInstrumentation() {
super("hibernate", "hibernate-core");
}
@Override
public Map<String, String> 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",
};
}
@Override @Override
public ElementMatcher<ClassLoader> classLoaderMatcher() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
// Optimization for expensive typeMatcher. // Optimization for expensive typeMatcher.
return hasClassesNamed("org.hibernate.Session"); return hasClassesNamed("org.hibernate.procedure.ProcedureCall");
} }
@Override @Override

View File

@ -13,14 +13,11 @@ import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.returns; import static net.bytebuddy.matcher.ElementMatchers.returns;
import com.google.auto.service.AutoService;
import io.opentelemetry.context.Context; import io.opentelemetry.context.Context;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore; import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -29,33 +26,12 @@ import net.bytebuddy.matcher.ElementMatcher;
import org.hibernate.SharedSessionContract; import org.hibernate.SharedSessionContract;
import org.hibernate.procedure.ProcedureCall; import org.hibernate.procedure.ProcedureCall;
@AutoService(Instrumenter.class) final class SessionInstrumentation implements TypeInstrumentation {
public class SessionInstrumentation extends Instrumenter.Default {
public SessionInstrumentation() {
super("hibernate", "hibernate-core");
}
@Override
public Map<String, String> contextStore() {
Map<String, String> 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",
};
}
@Override @Override
public ElementMatcher<ClassLoader> classLoaderMatcher() { public ElementMatcher<ClassLoader> classLoaderMatcher() {
// Optimization for expensive typeMatcher. // Optimization for expensive typeMatcher.
return hasClassesNamed("org.hibernate.Session"); return hasClassesNamed("org.hibernate.SharedSessionContract");
} }
@Override @Override

View File

@ -8,6 +8,7 @@ package io.opentelemetry.javaagent.instrumentation.httpurlconnection;
import static io.opentelemetry.javaagent.instrumentation.httpurlconnection.HttpUrlConnectionTracer.tracer; 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.bytebuddy.matcher.AgentElementMatchers.extendsClass;
import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.isPublic;
@ -21,8 +22,10 @@ import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore; import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.tooling.Instrumenter; import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.util.List;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -30,46 +33,56 @@ import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers; import net.bytebuddy.matcher.ElementMatchers;
@AutoService(Instrumenter.class) @AutoService(InstrumentationModule.class)
public class HttpUrlConnectionInstrumentation extends Instrumenter.Default { public class HttpUrlConnectionInstrumentationModule extends InstrumentationModule {
public HttpUrlConnectionInstrumentation() { public HttpUrlConnectionInstrumentationModule() {
super("httpurlconnection"); super("httpurlconnection");
} }
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return nameStartsWith("java.net.")
.or(ElementMatchers.<TypeDescription>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 @Override
public String[] helperClassNames() { public String[] helperClassNames() {
return new String[] { return new String[] {
packageName + ".HttpUrlConnectionTracer", packageName + ".HttpUrlConnectionTracer",
packageName + ".HeadersInjectAdapter", packageName + ".HeadersInjectAdapter",
HttpUrlConnectionInstrumentation.class.getName() + "$HttpUrlState", HttpUrlConnectionInstrumentationModule.class.getName() + "$HttpUrlState",
HttpUrlConnectionInstrumentation.class.getName() + "$HttpUrlState$1", HttpUrlConnectionInstrumentationModule.class.getName() + "$HttpUrlState$1",
}; };
} }
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new HttpUrlConnectionInstrumentation());
}
@Override @Override
public Map<String, String> contextStore() { public Map<String, String> contextStore() {
return singletonMap("java.net.HttpURLConnection", getClass().getName() + "$HttpUrlState"); return singletonMap("java.net.HttpURLConnection", getClass().getName() + "$HttpUrlState");
} }
@Override private static final class HttpUrlConnectionInstrumentation implements TypeInstrumentation {
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { @Override
return singletonMap( public ElementMatcher<TypeDescription> typeMatcher() {
isMethod().and(isPublic()).and(namedOneOf("connect", "getOutputStream", "getInputStream")), return nameStartsWith("java.net.")
HttpUrlConnectionInstrumentation.class.getName() + "$HttpUrlConnectionAdvice"); .or(ElementMatchers.<TypeDescription>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<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap(
isMethod()
.and(isPublic())
.and(namedOneOf("connect", "getOutputStream", "getInputStream")),
HttpUrlConnectionInstrumentationModule.class.getName() + "$HttpUrlConnectionAdvice");
}
} }
public static class HttpUrlConnectionAdvice { public static class HttpUrlConnectionAdvice {

View File

@ -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.ClassLoaderMatcher.hasClassesNamed;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass;
import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf;
import static java.util.Collections.singletonList;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.returns; import static net.bytebuddy.matcher.ElementMatchers.returns;
@ -17,8 +18,10 @@ import com.google.auto.service.AutoService;
import com.netflix.hystrix.HystrixInvokableInfo; import com.netflix.hystrix.HystrixInvokableInfo;
import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Span;
import io.opentelemetry.javaagent.instrumentation.rxjava.TracedOnSubscribe; 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.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -26,28 +29,15 @@ import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
import rx.Observable; import rx.Observable;
@AutoService(Instrumenter.class) @AutoService(InstrumentationModule.class)
public class HystrixInstrumentation extends Instrumenter.Default { public class HystrixInstrumentationModule extends InstrumentationModule {
private static final String OPERATION_NAME = "hystrix.cmd"; private static final String OPERATION_NAME = "hystrix.cmd";
public HystrixInstrumentation() { public HystrixInstrumentationModule() {
super("hystrix"); super("hystrix");
} }
@Override
public ElementMatcher<ClassLoader> classLoaderMatcher() {
// Optimization for expensive typeMatcher.
return hasClassesNamed("com.netflix.hystrix.HystrixCommand");
}
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return extendsClass(
namedOneOf(
"com.netflix.hystrix.HystrixCommand", "com.netflix.hystrix.HystrixObservableCommand"));
}
@Override @Override
public String[] helperClassNames() { public String[] helperClassNames() {
return new String[] { return new String[] {
@ -56,20 +46,42 @@ public class HystrixInstrumentation extends Instrumenter.Default {
"io.opentelemetry.javaagent.instrumentation.rxjava.TracedSubscriber", "io.opentelemetry.javaagent.instrumentation.rxjava.TracedSubscriber",
"io.opentelemetry.javaagent.instrumentation.rxjava.TracedOnSubscribe", "io.opentelemetry.javaagent.instrumentation.rxjava.TracedOnSubscribe",
packageName + ".HystrixTracer", packageName + ".HystrixTracer",
packageName + ".HystrixInstrumentation$HystrixOnSubscribe", getClass().getName() + "$HystrixOnSubscribe",
}; };
} }
@Override @Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() { public List<TypeInstrumentation> typeInstrumentations() {
Map<ElementMatcher.Junction<MethodDescription>, String> transformers = new HashMap<>(); return singletonList(new HystrixCommandInstrumentation());
transformers.put( }
named("getExecutionObservable").and(returns(named("rx.Observable"))),
HystrixInstrumentation.class.getName() + "$ExecuteAdvice"); private static final class HystrixCommandInstrumentation implements TypeInstrumentation {
transformers.put( @Override
named("getFallbackObservable").and(returns(named("rx.Observable"))), public ElementMatcher<ClassLoader> classLoaderMatcher() {
HystrixInstrumentation.class.getName() + "$FallbackAdvice"); // Optimization for expensive typeMatcher.
return transformers; return hasClassesNamed(
"com.netflix.hystrix.HystrixCommand", "com.netflix.hystrix.HystrixObservableCommand");
}
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return extendsClass(
namedOneOf(
"com.netflix.hystrix.HystrixCommand",
"com.netflix.hystrix.HystrixObservableCommand"));
}
@Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
Map<ElementMatcher.Junction<MethodDescription>, 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 { public static class ExecuteAdvice {
@ -77,10 +89,10 @@ public class HystrixInstrumentation extends Instrumenter.Default {
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void stopSpan( public static void stopSpan(
@Advice.This HystrixInvokableInfo<?> command, @Advice.This HystrixInvokableInfo<?> command,
@Advice.Return(readOnly = false) Observable result, @Advice.Return(readOnly = false) Observable<?> result,
@Advice.Thrown Throwable throwable) { @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.Return(readOnly = false) Observable<?> result,
@Advice.Thrown Throwable throwable) { @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<T> extends TracedOnSubscribe<T> {
private final HystrixInvokableInfo<?> command; private final HystrixInvokableInfo<?> command;
private final String methodName; private final String methodName;
public HystrixOnSubscribe( public HystrixOnSubscribe(
Observable originalObservable, HystrixInvokableInfo<?> command, String methodName) { Observable<T> originalObservable, HystrixInvokableInfo<?> command, String methodName) {
super(originalObservable, OPERATION_NAME, tracer(), INTERNAL); super(originalObservable, OPERATION_NAME, tracer(), INTERNAL);
this.command = command; this.command = command;

View File

@ -50,15 +50,6 @@ public final class MuzzleGradlePluginUtil {
throws Exception { throws Exception {
// muzzle validate all instrumenters // muzzle validate all instrumenters
for (Object instrumenter : loadAllInstrumenters(agentClassLoader)) { 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 if (!(instrumenter instanceof Instrumenter.Default
|| instrumenter instanceof InstrumentationModule)) { || instrumenter instanceof InstrumentationModule)) {
// only default Instrumenters and modules use muzzle. Skip custom instrumenters. // only default Instrumenters and modules use muzzle. Skip custom instrumenters.
@ -107,15 +98,6 @@ public final class MuzzleGradlePluginUtil {
// run helper injector on all instrumenters // run helper injector on all instrumenters
if (assertPass) { if (assertPass) {
for (Object instrumenter : loadAllInstrumenters(agentClassLoader)) { 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 if (!(instrumenter instanceof Instrumenter.Default
|| instrumenter instanceof InstrumentationModule)) { || instrumenter instanceof InstrumentationModule)) {
// only default Instrumenters and modules use muzzle. Skip custom instrumenters. // only default Instrumenters and modules use muzzle. Skip custom instrumenters.

View File

@ -19,11 +19,6 @@ class MuzzleBytecodeTransformTest extends Specification {
List<Class> nonLazyFields = [] List<Class> nonLazyFields = []
List<Class> unInitFields = [] List<Class> unInitFields = []
for (Object instrumenter : SafeServiceLoader.load(IntegrationTestUtils.getAgentClassLoader().loadClass("io.opentelemetry.javaagent.tooling.Instrumenter"), IntegrationTestUtils.getAgentClassLoader())) { 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())) { if (!IntegrationTestUtils.getAgentClassLoader().loadClass('io.opentelemetry.javaagent.tooling.Instrumenter$Default').isAssignableFrom(instrumenter.getClass())) {
// muzzle only applies to default instrumenters // muzzle only applies to default instrumenters
continue continue