From 068337111057c7bc020315481ba3618e2b8ec3c8 Mon Sep 17 00:00:00 2001 From: Nikita Salnikov-Tarnovski Date: Wed, 6 Oct 2021 19:52:54 +0300 Subject: [PATCH] Add supported way to add additional helper classes to instrumentation without interfering with muzzle (#4302) * Add supported way to add additional helper classes to instrumentation without interfering with muzzle * Better javadoc --- .../lambda/LambdaInstrumentationModule.java | 3 +- .../methods/MethodInstrumentationModule.java | 3 +- .../InstrumentationModule.java | 16 +++++++++++ .../InstrumentationModuleInstaller.java | 2 +- .../tooling/muzzle/ClassLoaderMatcher.java | 2 +- .../muzzle/InstrumentationModuleMuzzle.java | 28 +++++++++++++++---- .../tooling/muzzle/ReferenceMatcher.java | 2 +- 7 files changed, 45 insertions(+), 11 deletions(-) diff --git a/instrumentation/internal/internal-lambda/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/internal/lambda/LambdaInstrumentationModule.java b/instrumentation/internal/internal-lambda/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/internal/lambda/LambdaInstrumentationModule.java index 4594b0092a..a56125c59a 100644 --- a/instrumentation/internal/internal-lambda/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/internal/lambda/LambdaInstrumentationModule.java +++ b/instrumentation/internal/internal-lambda/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/internal/lambda/LambdaInstrumentationModule.java @@ -24,7 +24,8 @@ public class LambdaInstrumentationModule extends InstrumentationModule { return true; } - public List getMuzzleHelperClassNames() { + @Override + public List getAdditionalHelperClassNames() { // this instrumentation uses ASM not ByteBuddy so muzzle doesn't automatically add helper // classes return singletonList( diff --git a/instrumentation/methods/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentationModule.java b/instrumentation/methods/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentationModule.java index 58abe38faa..0ce45f8b94 100644 --- a/instrumentation/methods/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentationModule.java +++ b/instrumentation/methods/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentationModule.java @@ -49,7 +49,8 @@ public class MethodInstrumentationModule extends InstrumentationModule { // the default configuration has empty "otel.instrumentation.methods.include", and so doesn't // generate any TypeInstrumentation for muzzle to analyze - public List getMuzzleHelperClassNames() { + @Override + public List getAdditionalHelperClassNames() { return typeInstrumentations.isEmpty() ? emptyList() : singletonList("io.opentelemetry.javaagent.instrumentation.methods.MethodSingletons"); diff --git a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/extension/instrumentation/InstrumentationModule.java b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/extension/instrumentation/InstrumentationModule.java index 08c71b365b..3dc6ca3ea8 100644 --- a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/extension/instrumentation/InstrumentationModule.java +++ b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/extension/instrumentation/InstrumentationModule.java @@ -11,6 +11,7 @@ import static net.bytebuddy.matcher.ElementMatchers.any; import io.opentelemetry.instrumentation.api.config.Config; import io.opentelemetry.javaagent.extension.Ordered; import java.util.ArrayList; +import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -134,4 +135,19 @@ public abstract class InstrumentationModule implements Ordered { /** Returns a list of all individual type instrumentation in this module. */ public abstract List typeInstrumentations(); + + /** + * Returns a list of additional instrumentation helper classes, which are not automatically + * detected during compile time. + * + *

If your instrumentation module does not apply and you see warnings about missing classes in + * the logs, you may need to override this method and provide fully qualified classes names of + * helper classes that your instrumentation uses. + * + *

These helper classes will be injected into the application classloader after automatically + * detected ones. + */ + public List getAdditionalHelperClassNames() { + return Collections.emptyList(); + } } diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/InstrumentationModuleInstaller.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/InstrumentationModuleInstaller.java index 3d55af986a..39635afcdf 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/InstrumentationModuleInstaller.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/InstrumentationModuleInstaller.java @@ -59,7 +59,7 @@ public final class InstrumentationModuleInstaller { return parentAgentBuilder; } List helperClassNames = - InstrumentationModuleMuzzle.getMuzzleHelperClassNames(instrumentationModule); + InstrumentationModuleMuzzle.getHelperClassNames(instrumentationModule); HelperResourceBuilderImpl helperResourceBuilder = new HelperResourceBuilderImpl(); instrumentationModule.registerHelperResources(helperResourceBuilder); List typeInstrumentations = instrumentationModule.typeInstrumentations(); diff --git a/muzzle/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/ClassLoaderMatcher.java b/muzzle/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/ClassLoaderMatcher.java index 059e1c170a..7ff102e24a 100644 --- a/muzzle/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/ClassLoaderMatcher.java +++ b/muzzle/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/ClassLoaderMatcher.java @@ -78,7 +78,7 @@ public class ClassLoaderMatcher { try { // verify helper injector works List allHelperClasses = - InstrumentationModuleMuzzle.getMuzzleHelperClassNames(instrumentationModule); + InstrumentationModuleMuzzle.getHelperClassNames(instrumentationModule); HelperResourceBuilderImpl helperResourceBuilder = new HelperResourceBuilderImpl(); instrumentationModule.registerHelperResources(helperResourceBuilder); if (!allHelperClasses.isEmpty()) { diff --git a/muzzle/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/InstrumentationModuleMuzzle.java b/muzzle/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/InstrumentationModuleMuzzle.java index 5509fdc448..eed0290e81 100644 --- a/muzzle/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/InstrumentationModuleMuzzle.java +++ b/muzzle/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/InstrumentationModuleMuzzle.java @@ -7,6 +7,7 @@ package io.opentelemetry.javaagent.tooling.muzzle; import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; import io.opentelemetry.javaagent.tooling.muzzle.references.ClassRef; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; @@ -46,12 +47,27 @@ public interface InstrumentationModuleMuzzle { */ List getMuzzleHelperClassNames(); - /** See {@link #getMuzzleHelperClassNames()}. */ - static List getMuzzleHelperClassNames(InstrumentationModule module) { - if (module instanceof InstrumentationModuleMuzzle) { - return ((InstrumentationModuleMuzzle) module).getMuzzleHelperClassNames(); - } else { - return Collections.emptyList(); + /** + * Returns a concatenation of {@link #getMuzzleHelperClassNames()} and {@link + * InstrumentationModule#getAdditionalHelperClassNames()}. + */ + static List getHelperClassNames(InstrumentationModule module) { + List muzzleHelperClassNames = + module instanceof InstrumentationModuleMuzzle + ? ((InstrumentationModuleMuzzle) module).getMuzzleHelperClassNames() + : Collections.emptyList(); + + List additionalHelperClassNames = module.getAdditionalHelperClassNames(); + + if (additionalHelperClassNames.isEmpty()) { + return muzzleHelperClassNames; } + if (muzzleHelperClassNames.isEmpty()) { + return additionalHelperClassNames; + } + + List result = new ArrayList<>(muzzleHelperClassNames); + result.addAll(additionalHelperClassNames); + return result; } } diff --git a/muzzle/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/ReferenceMatcher.java b/muzzle/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/ReferenceMatcher.java index 1b7f492d2f..6c41e2c832 100644 --- a/muzzle/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/ReferenceMatcher.java +++ b/muzzle/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/ReferenceMatcher.java @@ -39,7 +39,7 @@ public final class ReferenceMatcher { public static ReferenceMatcher of(InstrumentationModule instrumentationModule) { return new ReferenceMatcher( - InstrumentationModuleMuzzle.getMuzzleHelperClassNames(instrumentationModule), + InstrumentationModuleMuzzle.getHelperClassNames(instrumentationModule), InstrumentationModuleMuzzle.getMuzzleReferences(instrumentationModule), instrumentationModule::isHelperClass); }