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
This commit is contained in:
Nikita Salnikov-Tarnovski 2021-10-06 19:52:54 +03:00 committed by GitHub
parent fda4779127
commit 0683371110
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 45 additions and 11 deletions

View File

@ -24,7 +24,8 @@ public class LambdaInstrumentationModule extends InstrumentationModule {
return true;
}
public List<String> getMuzzleHelperClassNames() {
@Override
public List<String> getAdditionalHelperClassNames() {
// this instrumentation uses ASM not ByteBuddy so muzzle doesn't automatically add helper
// classes
return singletonList(

View File

@ -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<String> getMuzzleHelperClassNames() {
@Override
public List<String> getAdditionalHelperClassNames() {
return typeInstrumentations.isEmpty()
? emptyList()
: singletonList("io.opentelemetry.javaagent.instrumentation.methods.MethodSingletons");

View File

@ -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<TypeInstrumentation> typeInstrumentations();
/**
* Returns a list of additional instrumentation helper classes, which are not automatically
* detected during compile time.
*
* <p>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.
*
* <p>These helper classes will be injected into the application classloader after automatically
* detected ones.
*/
public List<String> getAdditionalHelperClassNames() {
return Collections.emptyList();
}
}

View File

@ -59,7 +59,7 @@ public final class InstrumentationModuleInstaller {
return parentAgentBuilder;
}
List<String> helperClassNames =
InstrumentationModuleMuzzle.getMuzzleHelperClassNames(instrumentationModule);
InstrumentationModuleMuzzle.getHelperClassNames(instrumentationModule);
HelperResourceBuilderImpl helperResourceBuilder = new HelperResourceBuilderImpl();
instrumentationModule.registerHelperResources(helperResourceBuilder);
List<TypeInstrumentation> typeInstrumentations = instrumentationModule.typeInstrumentations();

View File

@ -78,7 +78,7 @@ public class ClassLoaderMatcher {
try {
// verify helper injector works
List<String> allHelperClasses =
InstrumentationModuleMuzzle.getMuzzleHelperClassNames(instrumentationModule);
InstrumentationModuleMuzzle.getHelperClassNames(instrumentationModule);
HelperResourceBuilderImpl helperResourceBuilder = new HelperResourceBuilderImpl();
instrumentationModule.registerHelperResources(helperResourceBuilder);
if (!allHelperClasses.isEmpty()) {

View File

@ -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<String> getMuzzleHelperClassNames();
/** See {@link #getMuzzleHelperClassNames()}. */
static List<String> 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<String> getHelperClassNames(InstrumentationModule module) {
List<String> muzzleHelperClassNames =
module instanceof InstrumentationModuleMuzzle
? ((InstrumentationModuleMuzzle) module).getMuzzleHelperClassNames()
: Collections.emptyList();
List<String> additionalHelperClassNames = module.getAdditionalHelperClassNames();
if (additionalHelperClassNames.isEmpty()) {
return muzzleHelperClassNames;
}
if (muzzleHelperClassNames.isEmpty()) {
return additionalHelperClassNames;
}
List<String> result = new ArrayList<>(muzzleHelperClassNames);
result.addAll(additionalHelperClassNames);
return result;
}
}

View File

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