Revert "Prevent duplicate telemetry when using both library and auto instrumentation (#2661)" (#2689)

This commit is contained in:
Mateusz Rzeszutek 2021-04-02 01:11:15 +02:00 committed by GitHub
parent 4426e1d87b
commit 1406855bb7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 79 additions and 344 deletions

View File

@ -26,7 +26,7 @@ instrumentations (`InstrumentationModule#typeInstrumentations()`). The reference
starts from advice classes (values of the map returned by the
`TypeInstrumentation#transformers()` method) and traverses the class graph until it encounters a
reference to a non-instrumentation class (determined by `InstrumentationClassPredicate` and
the `InstrumentationModule#isLibraryInstrumentationClass(String)` predicate). Aside from references,
the `InstrumentationModule#isHelperClass(String)` predicate). Aside from references,
the collection process also builds a graph of dependencies between internal instrumentation helper
classes - this dependency graph is later used to construct a list of helper classes that will be
injected to the application classloader (`InstrumentationModule#getMuzzleHelperClassNames()`).

View File

@ -4,8 +4,8 @@ ext.relocatePackages = { shadowJar ->
// rewrite dependencies calling Logger.getLogger
shadowJar.relocate 'java.util.logging.Logger', 'io.opentelemetry.javaagent.bootstrap.PatchLogger'
// prevents conflict with library instrumentation, which uses its own instrumentation-api
shadowJar.relocate 'io.opentelemetry.instrumentation.api', 'io.opentelemetry.javaagent.shaded.instrumentation.api'
// rewrite library instrumentation dependencies
shadowJar.relocate "io.opentelemetry.instrumentation", "io.opentelemetry.javaagent.shaded.instrumentation"
// relocate OpenTelemetry API usage
shadowJar.relocate "io.opentelemetry.api", "io.opentelemetry.javaagent.shaded.io.opentelemetry.api"

View File

@ -79,12 +79,15 @@ shadowJar {
archiveFileName = 'agent-testing.jar'
// rewrite library instrumentation dependencies
relocate "io.opentelemetry.instrumentation", "io.opentelemetry.javaagent.shaded.instrumentation"
// Prevents conflict with other SLF4J instances. Important for premain.
relocate 'org.slf4j', 'io.opentelemetry.javaagent.slf4j'
// rewrite dependencies calling Logger.getLogger
relocate 'java.util.logging.Logger', 'io.opentelemetry.javaagent.bootstrap.PatchLogger'
// prevents conflict with library instrumentation, which uses its own instrumentation-api
// prevents conflict with library instrumentation
relocate 'io.opentelemetry.instrumentation.api', 'io.opentelemetry.javaagent.shaded.instrumentation.api'
// relocate OpenTelemetry API usage

View File

@ -32,11 +32,6 @@ public class DubboInstrumentationModule extends InstrumentationModule {
return hasClassesNamed("org.apache.dubbo.rpc.Filter");
}
@Override
public boolean isLibraryInstrumentationClass(String className) {
return className.startsWith("io.opentelemetry.instrumentation.apachedubbo.v2_7");
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return Collections.singletonList(new DubboInstrumentation());

View File

@ -26,11 +26,6 @@ public class ArmeriaInstrumentationModule extends InstrumentationModule {
return hasClassesNamed("com.linecorp.armeria.server.metric.PrometheusExpositionServiceBuilder");
}
@Override
public boolean isLibraryInstrumentationClass(String className) {
return className.startsWith("io.opentelemetry.instrumentation.armeria.v1_3");
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return asList(

View File

@ -23,11 +23,6 @@ public class AwsLambdaInstrumentationModule extends InstrumentationModule {
return new String[] {"io.opentelemetry.extension.aws.AwsXrayPropagator"};
}
@Override
public boolean isLibraryInstrumentationClass(String className) {
return className.startsWith("io.opentelemetry.instrumentation.awslambda.v1_0");
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new AwsLambdaRequestHandlerInstrumentation());

View File

@ -23,11 +23,6 @@ public class AwsSdkInstrumentationModule extends InstrumentationModule {
return new String[] {"io.opentelemetry.extension.aws.AwsXrayPropagator"};
}
@Override
public boolean isLibraryInstrumentationClass(String className) {
return className.startsWith("io.opentelemetry.instrumentation.awssdk.v1_11");
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return asList(

View File

@ -43,11 +43,6 @@ public class AwsSdkInstrumentationModule extends InstrumentationModule {
return hasClassesNamed("software.amazon.awssdk.core.interceptor.ExecutionInterceptor");
}
@Override
public boolean isLibraryInstrumentationClass(String className) {
return className.startsWith("io.opentelemetry.instrumentation.awssdk.v2_2");
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return Collections.singletonList(new AwsSdkInitializationInstrumentation());

View File

@ -21,9 +21,4 @@ dependencies {
testLibrary group: "com.couchbase.client", name: "java-client", version: "3.1.0"
testImplementation group: "org.testcontainers", name: "couchbase", version: versions.testcontainers
}
configurations {
// exclude lib from test classpath, otherwise the javaagent would be skipped
testImplementation.exclude group: 'com.couchbase.client', module: 'tracing-opentelemetry'
}
}

View File

@ -20,6 +20,11 @@ public class CouchbaseInstrumentationModule extends InstrumentationModule {
super("couchbase", "couchbase-3.1");
}
@Override
public boolean isHelperClass(String className) {
return className.startsWith("com.couchbase.client.tracing.opentelemetry");
}
@Override
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
// New class introduced in 3.1, the minimum version we support.
@ -28,11 +33,6 @@ public class CouchbaseInstrumentationModule extends InstrumentationModule {
return hasClassesNamed("com.couchbase.client.core.cnc.TracingIdentifiers");
}
@Override
public boolean isLibraryInstrumentationClass(String className) {
return className.startsWith("com.couchbase.client.tracing.opentelemetry");
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return Collections.singletonList(new CouchbaseEnvironmentInstrumentation());

View File

@ -18,11 +18,6 @@ public class GrpcInstrumentationModule extends InstrumentationModule {
super("grpc", "grpc-1.5");
}
@Override
public boolean isLibraryInstrumentationClass(String className) {
return className.startsWith("io.opentelemetry.instrumentation.grpc.v1_5");
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return asList(

View File

@ -61,12 +61,12 @@ shadowJar {
exclude(project(':javaagent-api'))
}
// rewrite library instrumentation dependencies
relocate "io.opentelemetry.instrumentation", "io.opentelemetry.javaagent.shaded.instrumentation"
// rewrite dependencies calling Logger.getLogger
relocate 'java.util.logging.Logger', 'io.opentelemetry.javaagent.bootstrap.PatchLogger'
// prevents conflict with library instrumentation, which uses its own instrumentation-api
relocate 'io.opentelemetry.instrumentation.api', 'io.opentelemetry.javaagent.shaded.instrumentation.api'
// relocate OpenTelemetry API usage
relocate "io.opentelemetry.api", "io.opentelemetry.javaagent.shaded.io.opentelemetry.api"
relocate "io.opentelemetry.semconv", "io.opentelemetry.javaagent.shaded.io.opentelemetry.semconv"

View File

@ -26,11 +26,6 @@ public class Axis2InstrumentationModule extends InstrumentationModule {
return hasClassesNamed("org.apache.axis2.jaxws.api.MessageAccessor");
}
@Override
public boolean isLibraryInstrumentationClass(String className) {
return className.startsWith("io.opentelemetry.instrumentation.axis2");
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return Collections.singletonList(new InvocationListenerRegistryTypeInstrumentation());

View File

@ -17,11 +17,6 @@ public class CxfInstrumentationModule extends InstrumentationModule {
super("cxf", "cxf-3.0");
}
@Override
public boolean isLibraryInstrumentationClass(String className) {
return className.startsWith("io.opentelemetry.instrumentation.cxf");
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return Collections.singletonList(new EndpointImplTypeInstrumentation());

View File

@ -36,11 +36,6 @@ public class LettuceInstrumentationModule extends InstrumentationModule {
return hasClassesNamed("io.lettuce.core.tracing.Tracing");
}
@Override
public boolean isLibraryInstrumentationClass(String className) {
return className.startsWith("io.opentelemetry.instrumentation.lettuce.v5_1");
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new DefaultClientResourcesInstrumentation());

View File

@ -37,11 +37,6 @@ public class Log4j2InstrumentationModule extends InstrumentationModule {
return hasClassesNamed("org.apache.logging.log4j.core.util.ContextDataProvider");
}
@Override
public boolean isLibraryInstrumentationClass(String className) {
return className.startsWith("io.opentelemetry.instrumentation.log4j.v2_13_2");
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return Arrays.asList(new BugFixingInstrumentation(), new EmptyTypeInstrumentation());

View File

@ -26,11 +26,6 @@ public class LogbackInstrumentationModule extends InstrumentationModule {
return asList(new LoggerInstrumentation(), new LoggingEventInstrumentation());
}
@Override
public boolean isLibraryInstrumentationClass(String className) {
return className.startsWith("io.opentelemetry.instrumentation.logback.v1_0");
}
@Override
public Map<String, String> contextStore() {
return singletonMap("ch.qos.logback.classic.spi.ILoggingEvent", Span.class.getName());

View File

@ -29,11 +29,6 @@ public class OkHttp3InstrumentationModule extends InstrumentationModule {
super("okhttp", "okhttp-3.0");
}
@Override
public boolean isLibraryInstrumentationClass(String className) {
return className.startsWith("io.opentelemetry.instrumentation.okhttp.v3_0");
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new OkHttpClientInstrumentation());

View File

@ -31,11 +31,6 @@ public class OshiInstrumentationModule extends InstrumentationModule {
super("oshi");
}
@Override
public boolean isLibraryInstrumentationClass(String className) {
return className.startsWith("io.opentelemetry.instrumentation.oshi");
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new SystemInfoInstrumentation());

View File

@ -15,13 +15,13 @@ class OshiTest extends AgentInstrumentationSpecification {
def "test system metrics is enabled"() {
expect:
// TODO (trask) is this the instrumentation library name we want?
findMetric("io.opentelemetry.instrumentation.oshi", "system.disk.io") != null
findMetric("io.opentelemetry.instrumentation.oshi", "system.disk.operations") != null
findMetric("io.opentelemetry.instrumentation.oshi", "system.memory.usage") != null
findMetric("io.opentelemetry.instrumentation.oshi", "system.memory.utilization") != null
findMetric("io.opentelemetry.instrumentation.oshi", "system.network.errors") != null
findMetric("io.opentelemetry.instrumentation.oshi", "system.network.io") != null
findMetric("io.opentelemetry.instrumentation.oshi", "system.network.packets") != null
findMetric("io.opentelemetry.javaagent.shaded.instrumentation.oshi", "system.disk.io") != null
findMetric("io.opentelemetry.javaagent.shaded.instrumentation.oshi", "system.disk.operations") != null
findMetric("io.opentelemetry.javaagent.shaded.instrumentation.oshi", "system.memory.usage") != null
findMetric("io.opentelemetry.javaagent.shaded.instrumentation.oshi", "system.memory.utilization") != null
findMetric("io.opentelemetry.javaagent.shaded.instrumentation.oshi", "system.network.errors") != null
findMetric("io.opentelemetry.javaagent.shaded.instrumentation.oshi", "system.network.io") != null
findMetric("io.opentelemetry.javaagent.shaded.instrumentation.oshi", "system.network.packets") != null
}
def findMetric(instrumentationName, metricName) {

View File

@ -26,11 +26,6 @@ public class ReactorInstrumentationModule extends InstrumentationModule {
super("reactor", "reactor-3.1");
}
@Override
public boolean isLibraryInstrumentationClass(String className) {
return className.startsWith("io.opentelemetry.instrumentation.reactor");
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new HooksInstrumentation());

View File

@ -18,11 +18,6 @@ public class RocketMqInstrumentationModule extends InstrumentationModule {
super("rocketmq-client", "rocketmq-client-4.8");
}
@Override
public boolean isLibraryInstrumentationClass(String className) {
return className.startsWith("io.opentelemetry.instrumentation.rocketmq");
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return asList(new RocketMqProducerInstrumentation(), new RocketMqConsumerInstrumentation());

View File

@ -27,11 +27,6 @@ public class RxJava2InstrumentationModule extends InstrumentationModule {
super("rxjava2");
}
@Override
public boolean isLibraryInstrumentationClass(String className) {
return className.startsWith("io.opentelemetry.instrumentation.rxjava2");
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return Collections.singletonList(new PluginInstrumentation());

View File

@ -29,11 +29,6 @@ public class WebfluxClientInstrumentationModule extends InstrumentationModule {
super("spring-webflux", "spring-webflux-5.0", "spring-webflux-client");
}
@Override
public boolean isLibraryInstrumentationClass(String className) {
return className.startsWith("io.opentelemetry.instrumentation.spring.webflux.client");
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new WebClientBuilderInstrumentation());

View File

@ -18,11 +18,6 @@ public class SpringWebMvcInstrumentationModule extends InstrumentationModule {
super("spring-webmvc", "spring-webmvc-3.1");
}
@Override
public boolean isLibraryInstrumentationClass(String className) {
return className.startsWith("io.opentelemetry.instrumentation.spring.webmvc");
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return asList(

View File

@ -5,9 +5,7 @@
package io.opentelemetry.javaagent.tooling;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.callWhenTrue;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.failSafe;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.ClassLoaderMatcher.hasAnyClassesNamed;
import static java.util.Arrays.asList;
import static net.bytebuddy.matcher.ElementMatchers.any;
import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith;
@ -31,7 +29,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.description.annotation.AnnotationSource;
import net.bytebuddy.description.method.MethodDescription;
@ -133,8 +130,7 @@ public abstract class InstrumentationModule {
return parentAgentBuilder;
}
ElementMatcher.Junction<ClassLoader> moduleClassLoaderMatcher =
createModuleClassLoaderMatcher(helperClassNames);
ElementMatcher.Junction<ClassLoader> moduleClassLoaderMatcher = classLoaderMatcher();
MuzzleMatcher muzzleMatcher = new MuzzleMatcher();
HelperInjector helperInjector =
new HelperInjector(mainInstrumentationName(), helperClassNames, helperResourceNames);
@ -179,40 +175,6 @@ public abstract class InstrumentationModule {
return helperClassNames;
}
/**
* Returns the matcher produced by {@link #classLoaderMatcher()} with an additional condition
* added: no library instrumentation classes defined by this module can be present in the
* application classloader. This disables the javaagent instrumentation if the library
* instrumentation is already used by the application.
*/
private ElementMatcher.Junction<ClassLoader> createModuleClassLoaderMatcher(
List<String> helperClassNames) {
// TODO: optimization: refactor matcher caching, only the matcher returned by this method should
// cache results, the intermediary ones don't need to cache anything
// right now every matcher returned from ClassLoaderMatcher caches separately
// this will also make those "Skipping ..." logs appear less
List<String> libraryHelperClasses =
helperClassNames.stream()
.filter(this::isLibraryInstrumentationClass)
.collect(Collectors.toList());
if (libraryHelperClasses.isEmpty()) {
return classLoaderMatcher();
}
ElementMatcher.Junction<ClassLoader> libraryMatcher =
callWhenTrue(
hasAnyClassesNamed(libraryHelperClasses), this::logLibraryInstrumentationDetected);
return classLoaderMatcher().and(not(libraryMatcher));
}
private void logLibraryInstrumentationDetected() {
log.debug(
"Skipping instrumentation {} because library instrumentation was detected on classpath",
mainInstrumentationName());
}
private AgentBuilder.Identified.Extendable applyInstrumentationTransformers(
Map<? extends ElementMatcher<? super MethodDescription>, String> transformers,
AgentBuilder.Identified.Extendable agentBuilder) {
@ -296,8 +258,23 @@ public abstract class InstrumentationModule {
* Java helper function here.
*/
@SuppressWarnings("unused")
protected final Predicate<String> isLibraryInstrumentationClassPredicate() {
return this::isLibraryInstrumentationClass;
protected final Predicate<String> additionalLibraryInstrumentationPackage() {
return this::isHelperClass;
}
/**
* Instrumentation modules can override this method to specify additional packages (or classes)
* that should be treated as "library instrumentation" packages. Classes from those packages will
* be treated by muzzle as instrumentation helper classes: they will be scanned for references and
* automatically injected into the application classloader if they're used in any type
* instrumentation. The classes for which this predicate returns {@code true} will be treated as
* helper classes, in addition to the default ones defined in {@link
* InstrumentationClassPredicate}.
*
* @param className The name of the class that may or may not be a helper class.
*/
public boolean isHelperClass(String className) {
return false;
}
/**
@ -328,8 +305,8 @@ public abstract class InstrumentationModule {
/**
* Instrumentation modules can override this method to provide additional helper classes that are
* not located in instrumentation packages described in {@link InstrumentationClassPredicate} and
* {@link #isLibraryInstrumentationClass(String)} (and not automatically detected by muzzle).
* These additional classes will be injected into the application classloader first.
* {@link #isHelperClass(String)} (and not automatically detected by muzzle). These additional
* classes will be injected into the application classloader first.
*/
protected String[] additionalHelperClassNames() {
return EMPTY;
@ -365,26 +342,6 @@ public abstract class InstrumentationModule {
return any();
}
/**
* Instrumentation modules that use existing library instrumentation should override this method
* to specify additional packages (or classes) that should be treated as "library instrumentation"
* packages/classes.
*
* <p>Classes marked as library instrumentation classes will be treated by muzzle as
* instrumentation helper classes: they will be scanned for references and automatically injected
* into the application classloader if they're used in any type instrumentation.
*
* <p>In addition to that, the javaagent will prevent the instrumentations from this module from
* being applied when it detects that the application classloader already contains one of the
* library classes. This behavior prevents interference between library and javaagent
* instrumentation (for example, duplicate telemetry).
*
* @param className The name of the class that may or may not be a library instrumentation class.
*/
public boolean isLibraryInstrumentationClass(String className) {
return false;
}
/** Returns a list of all individual type instrumentation in this module. */
public abstract List<TypeInstrumentation> typeInstrumentations();

View File

@ -92,10 +92,4 @@ public class AgentElementMatchers {
}
}
}
/** Execute {@code callback} action whenever decorated {@code matcher} returns true. */
public static <T> ElementMatcher.Junction<T> callWhenTrue(
ElementMatcher<? super T> matcher, Runnable callback) {
return new CallWhenTrueDecorator<>(matcher, callback);
}
}

View File

@ -1,27 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.tooling.bytebuddy.matcher;
import net.bytebuddy.matcher.ElementMatcher;
final class CallWhenTrueDecorator<T> extends ElementMatcher.Junction.AbstractBase<T> {
private final ElementMatcher<? super T> delegate;
private final Runnable callback;
CallWhenTrueDecorator(ElementMatcher<? super T> delegate, Runnable callback) {
this.delegate = delegate;
this.callback = callback;
}
@Override
public boolean matches(T target) {
if (delegate.matches(target)) {
callback.run();
return true;
}
return false;
}
}

View File

@ -5,13 +5,8 @@
package io.opentelemetry.javaagent.tooling.bytebuddy.matcher;
import static java.util.Arrays.asList;
import io.opentelemetry.instrumentation.api.caching.Cache;
import io.opentelemetry.javaagent.instrumentation.api.internal.InClassLoaderMatcher;
import io.opentelemetry.javaagent.tooling.Utils;
import java.util.List;
import java.util.stream.Collectors;
import net.bytebuddy.matcher.ElementMatcher;
public final class ClassLoaderMatcher {
@ -24,40 +19,45 @@ public final class ClassLoaderMatcher {
}
/**
* Creates a matcher that checks if all of the passed classes are in the passed {@link
* ClassLoader}. If {@code classNames} is empty the matcher will always return {@code true}.
*
* <p>NOTICE: Does not match the bootstrap classpath. Don't use with classes expected to be on the
* NOTICE: Does not match the bootstrap classpath. Don't use with classes expected to be on the
* bootstrap.
*
* @param classNames list of names to match. returns true if empty.
* @return true if class is available as a resource and not the bootstrap classloader.
*/
public static ElementMatcher.Junction<ClassLoader> hasClassesNamed(String... classNames) {
return new ClassLoaderHasAllClassesNamedMatcher(asList(classNames));
public static ElementMatcher.Junction.AbstractBase<ClassLoader> hasClassesNamed(
String... classNames) {
return new ClassLoaderHasClassesNamedMatcher(classNames);
}
/**
* Creates a matcher that checks if any of the passed classes are in the passed {@link
* ClassLoader}. If {@code classNames} is empty the matcher will always return {@code false}.
*
* <p>NOTICE: Does not match the bootstrap classpath. Don't use with classes expected to be on the
* bootstrap.
*/
public static ElementMatcher.Junction<ClassLoader> hasAnyClassesNamed(List<String> classNames) {
return new ClassLoaderHasAnyClassesNamedMatcher(classNames);
}
private abstract static class AbstractClassLoaderMatcher
private static class ClassLoaderHasClassesNamedMatcher
extends ElementMatcher.Junction.AbstractBase<ClassLoader> {
private final Cache<ClassLoader, Boolean> cache =
Cache.newBuilder().setWeakKeys().setMaximumSize(25).build();
protected final List<String> resources;
private final String[] resources;
private AbstractClassLoaderMatcher(List<String> classNames) {
resources = classNames.stream().map(Utils::getResourceName).collect(Collectors.toList());
private ClassLoaderHasClassesNamedMatcher(String... classNames) {
resources = classNames;
for (int i = 0; i < resources.length; i++) {
resources[i] = resources[i].replace(".", "/") + ".class";
}
}
protected abstract boolean doMatch(ClassLoader cl);
private boolean hasResources(ClassLoader cl) {
boolean priorValue = InClassLoaderMatcher.getAndSet(true);
try {
for (String resource : resources) {
if (cl.getResource(resource) == null) {
return false;
}
}
} finally {
InClassLoaderMatcher.set(priorValue);
}
return true;
}
@Override
public boolean matches(ClassLoader cl) {
@ -67,48 +67,5 @@ public final class ClassLoaderMatcher {
}
return cache.computeIfAbsent(cl, this::hasResources);
}
private boolean hasResources(ClassLoader cl) {
boolean priorValue = InClassLoaderMatcher.getAndSet(true);
boolean value;
try {
value = doMatch(cl);
} finally {
InClassLoaderMatcher.set(priorValue);
}
return value;
}
}
private static class ClassLoaderHasAllClassesNamedMatcher extends AbstractClassLoaderMatcher {
private ClassLoaderHasAllClassesNamedMatcher(List<String> classNames) {
super(classNames);
}
@Override
protected boolean doMatch(ClassLoader cl) {
for (String resource : resources) {
if (cl.getResource(resource) == null) {
return false;
}
}
return true;
}
}
private static class ClassLoaderHasAnyClassesNamedMatcher extends AbstractClassLoaderMatcher {
private ClassLoaderHasAnyClassesNamedMatcher(List<String> classNames) {
super(classNames);
}
@Override
protected boolean doMatch(ClassLoader cl) {
for (String resource : resources) {
if (cl.getResource(resource) != null) {
return true;
}
}
return false;
}
}
}

View File

@ -14,9 +14,8 @@ public final class InstrumentationClassPredicate {
private static final String JAVAAGENT_API_PACKAGE =
"io.opentelemetry.javaagent.instrumentation.api.";
// library instrumentation packages
// library instrumentation packages (both shaded in the agent)
private static final String LIBRARY_INSTRUMENTATION_PACKAGE = "io.opentelemetry.instrumentation.";
// note that instrumentation-api is shaded in the agent
private static final String INSTRUMENTATION_API_PACKAGE = "io.opentelemetry.instrumentation.api.";
private final Predicate<String> additionalLibraryInstrumentationPredicate;

View File

@ -147,8 +147,7 @@ class MuzzleCodeGenerator implements AsmVisitorWrapper {
.flatMap(typeInstrumentation -> typeInstrumentation.transformers().values().stream())
.collect(Collectors.toSet());
ReferenceCollector collector =
new ReferenceCollector(instrumentationModule::isLibraryInstrumentationClass);
ReferenceCollector collector = new ReferenceCollector(instrumentationModule::isHelperClass);
for (String adviceClass : adviceClassNames) {
collector.collectReferencesFromAdvice(adviceClass);
}
@ -207,7 +206,7 @@ class MuzzleCodeGenerator implements AsmVisitorWrapper {
* new Reference[]{
* // reference builders
* },
* this.isLibraryInstrumentationClassPredicate());
* this.additionalLibraryInstrumentationPackage());
* }
* return this.muzzleReferenceMatcher;
* }
@ -473,7 +472,7 @@ class MuzzleCodeGenerator implements AsmVisitorWrapper {
mv.visitMethodInsn(
Opcodes.INVOKEVIRTUAL,
instrumentationClassName,
"isLibraryInstrumentationClassPredicate",
"additionalLibraryInstrumentationPackage",
"()Ljava/util/function/Predicate;",
false);

View File

@ -1,52 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.tooling.bytebuddy.matcher;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.never;
import net.bytebuddy.matcher.ElementMatcher;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
class CallWhenTrueDecoratorTest {
@Mock ElementMatcher<String> delegateMatcher;
@Mock Runnable callback;
@Test
void shouldExecuteCallbackWhenMatcherReturnsTrue() {
// given
ElementMatcher<String> matcher = new CallWhenTrueDecorator<>(delegateMatcher, callback);
given(delegateMatcher.matches("true")).willReturn(true);
// when
boolean result = matcher.matches("true");
// then
assertTrue(result);
then(callback).should().run();
}
@Test
void shouldNotExecuteCallbackWhenMatcherReturnsFalse() {
// given
ElementMatcher<String> matcher = new CallWhenTrueDecorator<>(delegateMatcher, callback);
// when
boolean result = matcher.matches("not really true");
// then
assertFalse(result);
then(callback).should(never()).run();
}
}

View File

@ -87,7 +87,7 @@ tasks.withType(ShadowJar).configureEach {
// rewrite dependencies calling Logger.getLogger
relocate 'java.util.logging.Logger', 'io.opentelemetry.javaagent.bootstrap.PatchLogger'
// prevents conflict with library instrumentation, which uses its own instrumentation-api
// prevents conflict with library instrumentation
relocate 'io.opentelemetry.instrumentation.api', 'io.opentelemetry.javaagent.shaded.instrumentation.api'
// relocate OpenTelemetry API

View File

@ -43,12 +43,12 @@ shadowJar {
// Prevents conflict with other SLF4J instances. Important for premain.
relocate 'org.slf4j', 'io.opentelemetry.javaagent.slf4j'
// rewrite library instrumentation dependencies
relocate "io.opentelemetry.instrumentation", "io.opentelemetry.javaagent.shaded.instrumentation"
// rewrite dependencies calling Logger.getLogger
relocate 'java.util.logging.Logger', 'io.opentelemetry.javaagent.bootstrap.PatchLogger'
// prevents conflict with library instrumentation, which uses its own instrumentation-api
relocate 'io.opentelemetry.instrumentation.api', 'io.opentelemetry.javaagent.shaded.instrumentation.api'
// relocate OpenTelemetry API usage
relocate "io.opentelemetry.api", "io.opentelemetry.javaagent.shaded.io.opentelemetry.api"
relocate "io.opentelemetry.semconv", "io.opentelemetry.javaagent.shaded.io.opentelemetry.semconv"

View File

@ -59,7 +59,7 @@ shadowJar {
// rewrite dependencies calling Logger.getLogger
relocate 'java.util.logging.Logger', 'io.opentelemetry.javaagent.bootstrap.PatchLogger'
// prevents conflict with library instrumentation, which uses its own instrumentation-api
// prevents conflict with library instrumentation
relocate 'io.opentelemetry.instrumentation.api', 'io.opentelemetry.javaagent.shaded.instrumentation.api'
// relocate OpenTelemetry API