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

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

View File

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

View File

@ -6,6 +6,7 @@
package io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.v5_0;
import static io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.ElasticsearchTransportClientTracer.tracer;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named;
@ -14,7 +15,9 @@ import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.List;
import java.util.Map;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription;
@ -25,20 +28,12 @@ import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.ActionResponse;
@AutoService(Instrumenter.class)
public class Elasticsearch5TransportClientInstrumentation extends Instrumenter.Default {
public Elasticsearch5TransportClientInstrumentation() {
@AutoService(InstrumentationModule.class)
public class Elasticsearch5TransportClientInstrumentationModule extends InstrumentationModule {
public Elasticsearch5TransportClientInstrumentationModule() {
super("elasticsearch", "elasticsearch-transport", "elasticsearch-transport-5");
}
@Override
public ElementMatcher<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
public String[] helperClassNames() {
return new String[] {
@ -53,15 +48,29 @@ public class Elasticsearch5TransportClientInstrumentation extends Instrumenter.D
}
@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"))),
Elasticsearch5TransportClientInstrumentation.class.getName()
+ "$ElasticsearchTransportClientAdvice");
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new AbstractClientInstrumentation());
}
private static final class AbstractClientInstrumentation implements TypeInstrumentation {
@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
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 {

View File

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

View File

@ -6,6 +6,7 @@
package io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.v6_0;
import static io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.ElasticsearchTransportClientTracer.tracer;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named;
@ -14,7 +15,9 @@ import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.List;
import java.util.Map;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription;
@ -29,20 +32,12 @@ import org.elasticsearch.action.ActionResponse;
* Most of this class is identical to version 5's instrumentation, but they changed an interface to
* an abstract class, so the bytecode isn't directly compatible.
*/
@AutoService(Instrumenter.class)
public class Elasticsearch6TransportClientInstrumentation extends Instrumenter.Default {
public Elasticsearch6TransportClientInstrumentation() {
@AutoService(InstrumentationModule.class)
public class Elasticsearch6TransportClientInstrumentationModule extends InstrumentationModule {
public Elasticsearch6TransportClientInstrumentationModule() {
super("elasticsearch", "elasticsearch-transport", "elasticsearch-transport-6");
}
@Override
public ElementMatcher<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
public String[] helperClassNames() {
return new String[] {
@ -57,15 +52,29 @@ public class Elasticsearch6TransportClientInstrumentation extends Instrumenter.D
}
@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"))),
Elasticsearch6TransportClientInstrumentation.class.getName()
+ "$Elasticsearch6TransportClientAdvice");
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new AbstractClientInstrumentation());
}
private static final class AbstractClientInstrumentation implements TypeInstrumentation {
@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
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 {

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

View File

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

View File

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

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

View File

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

View File

@ -6,6 +6,7 @@
package io.opentelemetry.javaagent.instrumentation.googlehttpclient;
import static io.opentelemetry.javaagent.instrumentation.googlehttpclient.GoogleHttpClientTracer.tracer;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
@ -23,28 +24,22 @@ import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class)
public class GoogleHttpClientInstrumentation extends Instrumenter.Default {
public GoogleHttpClientInstrumentation() {
@AutoService(InstrumentationModule.class)
public class GoogleHttpClientInstrumentationModule extends InstrumentationModule {
public GoogleHttpClientInstrumentationModule() {
super("google-http-client");
}
@Override
public ElementMatcher<? 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
public Map<String, String> contextStore() {
return singletonMap("com.google.api.client.http.HttpRequest", Context.class.getName());
@ -58,21 +53,36 @@ public class GoogleHttpClientInstrumentation extends Instrumenter.Default {
}
@Override
public Map<? 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)),
GoogleHttpClientInstrumentation.class.getName() + "$GoogleHttpClientAdvice");
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new HttpRequestInstrumentation());
}
transformers.put(
isMethod()
.and(isPublic())
.and(named("executeAsync"))
.and(takesArguments(1))
.and(takesArgument(0, (named("java.util.concurrent.Executor")))),
GoogleHttpClientInstrumentation.class.getName() + "$GoogleHttpClientAsyncAdvice");
private static final class HttpRequestInstrumentation implements TypeInstrumentation {
@Override
public ElementMatcher<? 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");
}
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 {

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

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.takesArgument;
import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Map;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers;
@AutoService(Instrumenter.class)
public final class FilterInstrumentation extends Instrumenter.Default {
public FilterInstrumentation() {
super("grizzly");
}
final class FilterInstrumentation implements TypeInstrumentation {
@Override
public ElementMatcher<ClassLoader> classLoaderMatcher() {
@ -47,22 +41,12 @@ public final class FilterInstrumentation extends Instrumenter.Default {
"org.glassfish.grizzly.http.HttpServerFilter")));
}
@Override
public String[] helperClassNames() {
return new String[] {packageName + ".GrizzlyHttpServerTracer", packageName + ".ExtractAdapter"};
}
@Override
protected boolean defaultEnabled() {
return false;
}
@Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap(
named("handleRead")
.and(takesArgument(0, named("org.glassfish.grizzly.filterchain.FilterChainContext")))
.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.takesArgument;
import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.HashMap;
import java.util.Map;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class)
public final class HttpCodecFilterInstrumentation extends Instrumenter.Default {
public HttpCodecFilterInstrumentation() {
super("grizzly");
}
final class HttpCodecFilterInstrumentation implements TypeInstrumentation {
@Override
public ElementMatcher<? super TypeDescription> typeMatcher() {
return named("org.glassfish.grizzly.http.HttpCodecFilter");
}
@Override
protected boolean defaultEnabled() {
return false;
}
@Override
public String[] helperClassNames() {
return new String[] {packageName + ".GrizzlyHttpServerTracer", packageName + ".ExtractAdapter"};
}
@Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
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(1, named("org.glassfish.grizzly.http.HttpPacketParsing")))
.and(isPublic()),
packageName + ".HttpCodecFilterOldAdvice");
HttpCodecFilterOldAdvice.class.getName());
// this is for 2.3.20+
transformers.put(
named("handleRead")
.and(takesArgument(0, named("org.glassfish.grizzly.filterchain.FilterChainContext")))
.and(takesArgument(1, named("org.glassfish.grizzly.http.HttpHeader")))
.and(isPublic()),
packageName + ".HttpCodecFilterAdvice");
HttpCodecFilterAdvice.class.getName());
return transformers;
}
}

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

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

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

View File

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

View File

@ -5,16 +5,21 @@
package io.opentelemetry.javaagent.instrumentation.grpc.v1_5;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import static java.util.Arrays.asList;
abstract class AbstractGrpcInstrumentation extends Instrumenter.Default {
import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.List;
public AbstractGrpcInstrumentation() {
@AutoService(InstrumentationModule.class)
public class GrpcInstrumentationModule extends InstrumentationModule {
public GrpcInstrumentationModule() {
super("grpc");
}
@Override
public final String[] helperClassNames() {
public String[] helperClassNames() {
return new String[] {
"io.opentelemetry.instrumentation.grpc.v1_5.common.GrpcHelper",
"io.opentelemetry.instrumentation.grpc.v1_5.client.GrpcClientTracer",
@ -29,4 +34,10 @@ abstract class AbstractGrpcInstrumentation extends Instrumenter.Default {
"io.opentelemetry.instrumentation.grpc.v1_5.server.TracingServerInterceptor$TracingServerCallListener",
};
}
@Override
public List<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.named;
import com.google.auto.service.AutoService;
import io.grpc.ServerInterceptor;
import io.opentelemetry.instrumentation.grpc.v1_5.server.TracingServerInterceptor;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.List;
import java.util.Map;
import net.bytebuddy.asm.Advice;
@ -20,8 +19,7 @@ import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class)
public class GrpcServerBuilderInstrumentation extends AbstractGrpcInstrumentation {
final class GrpcServerBuilderInstrumentation implements TypeInstrumentation {
@Override
public ElementMatcher<TypeDescription> typeMatcher() {

View File

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

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;
import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface;
import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf;
import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.context.Context;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope;
import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Map;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription;
@ -26,12 +26,12 @@ import net.bytebuddy.implementation.bytecode.assign.Assigner;
import net.bytebuddy.matcher.ElementMatcher;
import org.hibernate.Criteria;
@AutoService(Instrumenter.class)
public class CriteriaInstrumentation extends AbstractHibernateInstrumentation {
final class CriteriaInstrumentation implements TypeInstrumentation {
@Override
public Map<String, String> contextStore() {
return singletonMap("org.hibernate.Criteria", Context.class.getName());
public ElementMatcher<ClassLoader> classLoaderMatcher() {
// Optimization for expensive typeMatcher.
return hasClassesNamed("org.hibernate.Criteria");
}
@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;
import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface;
import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf;
import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.context.Context;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope;
import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Map;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription;
@ -25,12 +25,12 @@ import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
import org.hibernate.Query;
@AutoService(Instrumenter.class)
public class QueryInstrumentation extends AbstractHibernateInstrumentation {
final class QueryInstrumentation implements TypeInstrumentation {
@Override
public Map<String, String> contextStore() {
return singletonMap("org.hibernate.Query", Context.class.getName());
public ElementMatcher<ClassLoader> classLoaderMatcher() {
// Optimization for expensive typeMatcher.
return hasClassesNamed("org.hibernate.Query");
}
@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.tracer;
import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.hasInterface;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface;
import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf;
@ -16,14 +17,12 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.returns;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import com.google.auto.service.AutoService;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Context;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import java.util.HashMap;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Map;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription;
@ -32,16 +31,12 @@ import net.bytebuddy.matcher.ElementMatcher;
import org.hibernate.Session;
import org.hibernate.StatelessSession;
@AutoService(Instrumenter.class)
public class SessionFactoryInstrumentation extends AbstractHibernateInstrumentation {
final class SessionFactoryInstrumentation implements TypeInstrumentation {
@Override
public Map<String, String> contextStore() {
Map<String, String> stores = new HashMap<>();
stores.put("org.hibernate.Session", Context.class.getName());
stores.put("org.hibernate.StatelessSession", Context.class.getName());
stores.put("org.hibernate.SharedSessionContract", Context.class.getName());
return stores;
public ElementMatcher<ClassLoader> classLoaderMatcher() {
// Optimization for expensive typeMatcher.
return hasClassesNamed("org.hibernate.SessionFactory");
}
@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.SessionMethodUtils.SCOPE_ONLY_METHODS;
import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.hasInterface;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface;
import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf;
@ -16,7 +17,6 @@ import static net.bytebuddy.matcher.ElementMatchers.returns;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import com.google.auto.service.AutoService;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Context;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
@ -24,8 +24,7 @@ import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope;
import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import java.util.Collections;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.HashMap;
import java.util.Map;
import net.bytebuddy.asm.Advice;
@ -39,18 +38,12 @@ import org.hibernate.Session;
import org.hibernate.StatelessSession;
import org.hibernate.Transaction;
@AutoService(Instrumenter.class)
public class SessionInstrumentation extends AbstractHibernateInstrumentation {
final class SessionInstrumentation implements TypeInstrumentation {
@Override
public Map<String, String> contextStore() {
Map<String, String> map = new HashMap<>();
map.put("org.hibernate.Session", Context.class.getName());
map.put("org.hibernate.StatelessSession", Context.class.getName());
map.put("org.hibernate.Query", Context.class.getName());
map.put("org.hibernate.Transaction", Context.class.getName());
map.put("org.hibernate.Criteria", Context.class.getName());
return Collections.unmodifiableMap(map);
public ElementMatcher<ClassLoader> classLoaderMatcher() {
// Optimization for expensive typeMatcher.
return hasClassesNamed("org.hibernate.Session", "org.hibernate.StatelessSession");
}
@Override

View File

@ -5,19 +5,19 @@
package io.opentelemetry.javaagent.instrumentation.hibernate.v3_3;
import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface;
import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import com.google.auto.service.AutoService;
import io.opentelemetry.context.Context;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope;
import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Map;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription;
@ -25,12 +25,12 @@ import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
import org.hibernate.Transaction;
@AutoService(Instrumenter.class)
public class TransactionInstrumentation extends AbstractHibernateInstrumentation {
final class TransactionInstrumentation implements TypeInstrumentation {
@Override
public Map<String, String> contextStore() {
return singletonMap("org.hibernate.Transaction", Context.class.getName());
public ElementMatcher<ClassLoader> classLoaderMatcher() {
// Optimization for expensive typeMatcher.
return hasClassesNamed("org.hibernate.Transaction");
}
@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;
import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface;
import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf;
import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.context.Context;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope;
import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Map;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription;
@ -26,12 +26,12 @@ import net.bytebuddy.implementation.bytecode.assign.Assigner;
import net.bytebuddy.matcher.ElementMatcher;
import org.hibernate.Criteria;
@AutoService(Instrumenter.class)
public class CriteriaInstrumentation extends AbstractHibernateInstrumentation {
final class CriteriaInstrumentation implements TypeInstrumentation {
@Override
public Map<String, String> contextStore() {
return singletonMap("org.hibernate.Criteria", Context.class.getName());
public ElementMatcher<ClassLoader> classLoaderMatcher() {
// Optimization for expensive typeMatcher.
return hasClassesNamed("org.hibernate.Criteria");
}
@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;
import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface;
import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf;
import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.context.Context;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope;
import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Map;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription;
@ -25,12 +25,12 @@ import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
import org.hibernate.Query;
@AutoService(Instrumenter.class)
public class QueryInstrumentation extends AbstractHibernateInstrumentation {
final class QueryInstrumentation implements TypeInstrumentation {
@Override
public Map<String, String> contextStore() {
return singletonMap("org.hibernate.Query", Context.class.getName());
public ElementMatcher<ClassLoader> classLoaderMatcher() {
// Optimization for expensive typeMatcher.
return hasClassesNamed("org.hibernate.Query");
}
@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.tracer;
import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface;
import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf;
import static java.util.Collections.singletonMap;
@ -15,13 +16,12 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.returns;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import com.google.auto.service.AutoService;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Context;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Map;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription;
@ -29,12 +29,12 @@ import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
import org.hibernate.SharedSessionContract;
@AutoService(Instrumenter.class)
public class SessionFactoryInstrumentation extends AbstractHibernateInstrumentation {
final class SessionFactoryInstrumentation implements TypeInstrumentation {
@Override
public Map<String, String> contextStore() {
return singletonMap("org.hibernate.SharedSessionContract", Context.class.getName());
public ElementMatcher<ClassLoader> classLoaderMatcher() {
// Optimization for expensive typeMatcher.
return hasClassesNamed("org.hibernate.SessionFactory");
}
@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.SessionMethodUtils.SCOPE_ONLY_METHODS;
import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.hasInterface;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface;
import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf;
@ -16,7 +17,6 @@ import static net.bytebuddy.matcher.ElementMatchers.returns;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import com.google.auto.service.AutoService;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Context;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
@ -24,8 +24,7 @@ import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope;
import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import java.util.Collections;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.HashMap;
import java.util.Map;
import net.bytebuddy.asm.Advice;
@ -38,17 +37,12 @@ import org.hibernate.Query;
import org.hibernate.SharedSessionContract;
import org.hibernate.Transaction;
@AutoService(Instrumenter.class)
public class SessionInstrumentation extends AbstractHibernateInstrumentation {
final class SessionInstrumentation implements TypeInstrumentation {
@Override
public Map<String, String> contextStore() {
Map<String, String> map = new HashMap<>();
map.put("org.hibernate.SharedSessionContract", Context.class.getName());
map.put("org.hibernate.Query", Context.class.getName());
map.put("org.hibernate.Transaction", Context.class.getName());
map.put("org.hibernate.Criteria", Context.class.getName());
return Collections.unmodifiableMap(map);
public ElementMatcher<ClassLoader> classLoaderMatcher() {
// Optimization for expensive typeMatcher.
return hasClassesNamed("org.hibernate.SharedSessionContract");
}
@Override

View File

@ -5,19 +5,19 @@
package io.opentelemetry.javaagent.instrumentation.hibernate.v4_0;
import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface;
import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import com.google.auto.service.AutoService;
import io.opentelemetry.context.Context;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope;
import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Map;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription;
@ -25,12 +25,12 @@ import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
import org.hibernate.Transaction;
@AutoService(Instrumenter.class)
public class TransactionInstrumentation extends AbstractHibernateInstrumentation {
final class TransactionInstrumentation implements TypeInstrumentation {
@Override
public Map<String, String> contextStore() {
return singletonMap("org.hibernate.Transaction", Context.class.getName());
public ElementMatcher<ClassLoader> classLoaderMatcher() {
// Optimization for expensive typeMatcher.
return hasClassesNamed("org.hibernate.Transaction");
}
@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.named;
import com.google.auto.service.AutoService;
import io.opentelemetry.context.Context;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope;
import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Map;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription;
@ -25,30 +24,12 @@ import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
import org.hibernate.procedure.ProcedureCall;
@AutoService(Instrumenter.class)
public class ProcedureCallInstrumentation extends Instrumenter.Default {
public ProcedureCallInstrumentation() {
super("hibernate", "hibernate-core");
}
@Override
public Map<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",
};
}
final class ProcedureCallInstrumentation implements TypeInstrumentation {
@Override
public ElementMatcher<ClassLoader> classLoaderMatcher() {
// Optimization for expensive typeMatcher.
return hasClassesNamed("org.hibernate.Session");
return hasClassesNamed("org.hibernate.procedure.ProcedureCall");
}
@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.returns;
import com.google.auto.service.AutoService;
import io.opentelemetry.context.Context;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import java.util.Collections;
import java.util.HashMap;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.util.Map;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription;
@ -29,33 +26,12 @@ import net.bytebuddy.matcher.ElementMatcher;
import org.hibernate.SharedSessionContract;
import org.hibernate.procedure.ProcedureCall;
@AutoService(Instrumenter.class)
public class SessionInstrumentation extends Instrumenter.Default {
public SessionInstrumentation() {
super("hibernate", "hibernate-core");
}
@Override
public Map<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",
};
}
final class SessionInstrumentation implements TypeInstrumentation {
@Override
public ElementMatcher<ClassLoader> classLoaderMatcher() {
// Optimization for expensive typeMatcher.
return hasClassesNamed("org.hibernate.Session");
return hasClassesNamed("org.hibernate.SharedSessionContract");
}
@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.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass;
import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
@ -21,8 +22,10 @@ import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap;
import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import io.opentelemetry.javaagent.tooling.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
import java.net.HttpURLConnection;
import java.util.List;
import java.util.Map;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription;
@ -30,46 +33,56 @@ import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers;
@AutoService(Instrumenter.class)
public class HttpUrlConnectionInstrumentation extends Instrumenter.Default {
@AutoService(InstrumentationModule.class)
public class HttpUrlConnectionInstrumentationModule extends InstrumentationModule {
public HttpUrlConnectionInstrumentation() {
public HttpUrlConnectionInstrumentationModule() {
super("httpurlconnection");
}
@Override
public ElementMatcher<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
public String[] helperClassNames() {
return new String[] {
packageName + ".HttpUrlConnectionTracer",
packageName + ".HeadersInjectAdapter",
HttpUrlConnectionInstrumentation.class.getName() + "$HttpUrlState",
HttpUrlConnectionInstrumentation.class.getName() + "$HttpUrlState$1",
HttpUrlConnectionInstrumentationModule.class.getName() + "$HttpUrlState",
HttpUrlConnectionInstrumentationModule.class.getName() + "$HttpUrlState$1",
};
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new HttpUrlConnectionInstrumentation());
}
@Override
public Map<String, String> contextStore() {
return singletonMap("java.net.HttpURLConnection", getClass().getName() + "$HttpUrlState");
}
@Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap(
isMethod().and(isPublic()).and(namedOneOf("connect", "getOutputStream", "getInputStream")),
HttpUrlConnectionInstrumentation.class.getName() + "$HttpUrlConnectionAdvice");
private static final class HttpUrlConnectionInstrumentation implements TypeInstrumentation {
@Override
public ElementMatcher<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
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 {

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

View File

@ -50,15 +50,6 @@ public final class MuzzleGradlePluginUtil {
throws Exception {
// muzzle validate all instrumenters
for (Object instrumenter : loadAllInstrumenters(agentClassLoader)) {
if (instrumenter.getClass().getName().endsWith("TraceConfigInstrumentation")) {
// TraceConfigInstrumentation doesn't do muzzle checks
// check on TracerClassInstrumentation instead
instrumenter =
agentClassLoader
.loadClass(instrumenter.getClass().getName() + "$TracerClassInstrumentation")
.getDeclaredConstructor()
.newInstance();
}
if (!(instrumenter instanceof Instrumenter.Default
|| instrumenter instanceof InstrumentationModule)) {
// only default Instrumenters and modules use muzzle. Skip custom instrumenters.
@ -107,15 +98,6 @@ public final class MuzzleGradlePluginUtil {
// run helper injector on all instrumenters
if (assertPass) {
for (Object instrumenter : loadAllInstrumenters(agentClassLoader)) {
if (instrumenter.getClass().getName().endsWith("TraceConfigInstrumentation")) {
// TraceConfigInstrumentation doesn't do muzzle checks
// check on TracerClassInstrumentation instead
instrumenter =
agentClassLoader
.loadClass(instrumenter.getClass().getName() + "$TracerClassInstrumentation")
.getDeclaredConstructor()
.newInstance();
}
if (!(instrumenter instanceof Instrumenter.Default
|| instrumenter instanceof InstrumentationModule)) {
// only default Instrumenters and modules use muzzle. Skip custom instrumenters.

View File

@ -19,11 +19,6 @@ class MuzzleBytecodeTransformTest extends Specification {
List<Class> nonLazyFields = []
List<Class> unInitFields = []
for (Object instrumenter : SafeServiceLoader.load(IntegrationTestUtils.getAgentClassLoader().loadClass("io.opentelemetry.javaagent.tooling.Instrumenter"), IntegrationTestUtils.getAgentClassLoader())) {
if (instrumenter.getClass().getName().endsWith("TraceConfigInstrumentation")) {
// TraceConfigInstrumentation doesn't do muzzle checks
// check on TracerClassInstrumentation instead
instrumenter = IntegrationTestUtils.getAgentClassLoader().loadClass(instrumenter.getClass().getName() + '$TracerClassInstrumentation').newInstance()
}
if (!IntegrationTestUtils.getAgentClassLoader().loadClass('io.opentelemetry.javaagent.tooling.Instrumenter$Default').isAssignableFrom(instrumenter.getClass())) {
// muzzle only applies to default instrumenters
continue