InstrumentationModule cleanup (#2925)
This commit is contained in:
parent
3b807e0efb
commit
871f9a0d24
|
@ -55,7 +55,7 @@ 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
|
||||
@Override
|
||||
protected String[] getMuzzleHelperClassNames() {
|
||||
public String[] getMuzzleHelperClassNames() {
|
||||
return typeInstrumentations.isEmpty()
|
||||
? new String[0]
|
||||
: new String[] {"io.opentelemetry.javaagent.instrumentation.methods.MethodTracer"};
|
||||
|
|
|
@ -33,12 +33,12 @@ import net.bytebuddy.matcher.ElementMatcher;
|
|||
*/
|
||||
public abstract class InstrumentationModule implements AgentExtension {
|
||||
private static final String[] EMPTY = new String[0];
|
||||
private static final Reference[] EMPTY_REFS = new Reference[0];
|
||||
|
||||
private static final boolean DEFAULT_ENABLED =
|
||||
Config.get().getBooleanProperty("otel.instrumentation.common.default-enabled", true);
|
||||
|
||||
private final Set<String> instrumentationNames;
|
||||
final boolean enabled;
|
||||
|
||||
/**
|
||||
* Creates an instrumentation module. Note that all implementations of {@link
|
||||
|
@ -75,7 +75,6 @@ public abstract class InstrumentationModule implements AgentExtension {
|
|||
throw new IllegalArgumentException("InstrumentationModules must be named");
|
||||
}
|
||||
this.instrumentationNames = new LinkedHashSet<>(instrumentationNames);
|
||||
this.enabled = Config.get().isInstrumentationEnabled(instrumentationNames, defaultEnabled());
|
||||
}
|
||||
|
||||
private static List<String> toList(String first, String[] rest) {
|
||||
|
@ -101,15 +100,17 @@ public abstract class InstrumentationModule implements AgentExtension {
|
|||
return instrumentationNames.iterator().next();
|
||||
}
|
||||
|
||||
/** Returns true if this instrumentation module should be installed. */
|
||||
public final boolean isEnabled() {
|
||||
return Config.get().isInstrumentationEnabled(instrumentationNames, defaultEnabled());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all helper classes that will be injected into the application classloader, both ones
|
||||
* provided by the implementation and ones that were collected by muzzle during compilation.
|
||||
* Allows instrumentation modules to disable themselves by default, or to additionally disable
|
||||
* themselves on some other condition.
|
||||
*/
|
||||
public final List<String> getAllHelperClassNames() {
|
||||
List<String> helperClassNames = new ArrayList<>();
|
||||
helperClassNames.addAll(asList(additionalHelperClassNames()));
|
||||
helperClassNames.addAll(asList(getMuzzleHelperClassNames()));
|
||||
return helperClassNames;
|
||||
protected boolean defaultEnabled() {
|
||||
return DEFAULT_ENABLED;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -127,83 +128,6 @@ public abstract class InstrumentationModule implements AgentExtension {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of references to helper and library classes used in this module's type
|
||||
* instrumentation advices.
|
||||
*
|
||||
* <p>The actual implementation of this method is generated automatically during compilation by
|
||||
* the {@code io.opentelemetry.javaagent.tooling.muzzle.collector.MuzzleCodeGenerationPlugin}
|
||||
* ByteBuddy plugin.
|
||||
*
|
||||
* <p><b>This method is generated automatically</b>: if you override it, the muzzle compile plugin
|
||||
* will not generate a new implementation, it will leave the existing one.
|
||||
*/
|
||||
public Reference[] getMuzzleReferences() {
|
||||
return new Reference[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of instrumentation helper classes, automatically detected by muzzle during
|
||||
* compilation. Those helpers will be injected into the application classloader.
|
||||
*
|
||||
* <p>The actual implementation of this method is generated automatically during compilation by
|
||||
* the {@code io.opentelemetry.javaagent.tooling.muzzle.collector.MuzzleCodeGenerationPlugin}
|
||||
* ByteBuddy plugin.
|
||||
*
|
||||
* <p><b>This method is generated automatically</b>: if you override it, the muzzle compile plugin
|
||||
* will not generate a new implementation, it will leave the existing one.
|
||||
*/
|
||||
protected String[] getMuzzleHelperClassNames() {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map of {@code class-name to context-class-name}. Keys (and their subclasses) will be
|
||||
* associated with a context class stored in the value.
|
||||
*
|
||||
* <p>The actual implementation of this method is generated automatically during compilation by
|
||||
* the {@code io.opentelemetry.javaagent.tooling.muzzle.collector.MuzzleCodeGenerationPlugin}
|
||||
* ByteBuddy plugin.
|
||||
*
|
||||
* <p><b>This method is generated automatically</b>: if you override it, the muzzle compile plugin
|
||||
* will not generate a new implementation, it will leave the existing one.
|
||||
*/
|
||||
protected Map<String, String> getMuzzleContextStoreClasses() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Instrumentation modules can override this method to provide additional helper classes that are
|
||||
* not located in instrumentation packages described in the {@code InstrumentationClassPredicate}
|
||||
* class and {@link #isHelperClass(String)} (and not automatically detected by muzzle). These
|
||||
* additional classes will be injected into the application classloader first.
|
||||
*
|
||||
* <p>Implementing {@link #isHelperClass(String)} is generally simpler and less error-prone
|
||||
* compared to implementing this method.
|
||||
*
|
||||
* @deprecated Use {@link #isHelperClass(String)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
protected String[] additionalHelperClassNames() {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@link #order()}.
|
||||
*
|
||||
* @deprecated use {@link #order()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public int getOrder() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int order() {
|
||||
return getOrder();
|
||||
}
|
||||
|
||||
/** Returns resource names to inject into the user's classloader. */
|
||||
public String[] helperResourceNames() {
|
||||
return EMPTY;
|
||||
|
@ -228,10 +152,47 @@ public abstract class InstrumentationModule implements AgentExtension {
|
|||
public abstract List<TypeInstrumentation> typeInstrumentations();
|
||||
|
||||
/**
|
||||
* Allows instrumentation modules to disable themselves by default, or to additionally disable
|
||||
* themselves on some other condition.
|
||||
* Returns a list of references to helper and library classes used in this module's type
|
||||
* instrumentation advices.
|
||||
*
|
||||
* <p>The actual implementation of this method is generated automatically during compilation by
|
||||
* the {@code io.opentelemetry.javaagent.tooling.muzzle.collector.MuzzleCodeGenerationPlugin}
|
||||
* ByteBuddy plugin.
|
||||
*
|
||||
* <p><b>This method is generated automatically</b>: if you override it, the muzzle compile plugin
|
||||
* will not generate a new implementation, it will leave the existing one.
|
||||
*/
|
||||
protected boolean defaultEnabled() {
|
||||
return DEFAULT_ENABLED;
|
||||
public Reference[] getMuzzleReferences() {
|
||||
return EMPTY_REFS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of instrumentation helper classes, automatically detected by muzzle during
|
||||
* compilation. Those helpers will be injected into the application classloader.
|
||||
*
|
||||
* <p>The actual implementation of this method is generated automatically during compilation by
|
||||
* the {@code io.opentelemetry.javaagent.tooling.muzzle.collector.MuzzleCodeGenerationPlugin}
|
||||
* ByteBuddy plugin.
|
||||
*
|
||||
* <p><b>This method is generated automatically</b>: if you override it, the muzzle compile plugin
|
||||
* will not generate a new implementation, it will leave the existing one.
|
||||
*/
|
||||
public String[] getMuzzleHelperClassNames() {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map of {@code class-name to context-class-name}. Keys (and their subclasses) will be
|
||||
* associated with a context class stored in the value.
|
||||
*
|
||||
* <p>The actual implementation of this method is generated automatically during compilation by
|
||||
* the {@code io.opentelemetry.javaagent.tooling.muzzle.collector.MuzzleCodeGenerationPlugin}
|
||||
* ByteBuddy plugin.
|
||||
*
|
||||
* <p><b>This method is generated automatically</b>: if you override it, the muzzle compile plugin
|
||||
* will not generate a new implementation, it will leave the existing one.
|
||||
*/
|
||||
public Map<String, String> getMuzzleContextStoreClasses() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import net.bytebuddy.matcher.ElementMatcher;
|
|||
/**
|
||||
* This class provides some custom ByteBuddy element matchers to use when applying instrumentation.
|
||||
*/
|
||||
public class AgentElementMatchers {
|
||||
public final class AgentElementMatchers {
|
||||
|
||||
public static ElementMatcher.Junction<TypeDescription> extendsClass(
|
||||
ElementMatcher<TypeDescription> matcher) {
|
||||
|
@ -92,4 +92,6 @@ public class AgentElementMatchers {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private AgentElementMatchers() {}
|
||||
}
|
||||
|
|
|
@ -74,4 +74,6 @@ public final class NameMatchers {
|
|||
return (include && contained) || (!include && !contained);
|
||||
}
|
||||
}
|
||||
|
||||
private NameMatchers() {}
|
||||
}
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.spi;
|
||||
|
||||
import io.opentelemetry.javaagent.extension.spi.AgentExtension;
|
||||
import java.lang.instrument.Instrumentation;
|
||||
import net.bytebuddy.agent.builder.AgentBuilder;
|
||||
|
||||
/**
|
||||
* {@link ByteBuddyAgentCustomizer} customizes ByteBuddy agent builder right before the agent is
|
||||
* installed - {@link AgentBuilder#installOn(Instrumentation)}. This SPI can be used to customize
|
||||
* {@link AgentBuilder} for vendor specific needs. For example install custom listeners or exclude
|
||||
* classes. Use this SPI carefully because it can change {@link net.bytebuddy.ByteBuddy} behaviour.
|
||||
*
|
||||
* <p>This is a service provider interface that requires implementations to be registered in {@code
|
||||
* META-INF/services} folder.
|
||||
*
|
||||
* @deprecated Use {@link AgentExtension} with correct {@link AgentExtension#order()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public interface ByteBuddyAgentCustomizer {
|
||||
|
||||
/**
|
||||
* Customize ByteBuddy agent builder before {@link AgentBuilder#installOn(Instrumentation)} is
|
||||
* called.
|
||||
*
|
||||
* @param agentBuilder ByteBuddy agent from {@code AgentInstaller}.
|
||||
* @return customized agent builder.
|
||||
*/
|
||||
AgentBuilder customize(AgentBuilder agentBuilder);
|
||||
}
|
|
@ -49,11 +49,11 @@ public final class ActualInstrumentationExtensionImplementation
|
|||
@Override
|
||||
AgentBuilder extend(
|
||||
InstrumentationModule instrumentationModule, AgentBuilder parentAgentBuilder) {
|
||||
if (!instrumentationModule.enabled) {
|
||||
if (!instrumentationModule.isEnabled()) {
|
||||
log.debug("Instrumentation {} is disabled", instrumentationModule.extensionName());
|
||||
return parentAgentBuilder;
|
||||
}
|
||||
List<String> helperClassNames = instrumentationModule.getAllHelperClassNames();
|
||||
List<String> helperClassNames = asList(instrumentationModule.getMuzzleHelperClassNames());
|
||||
List<String> helperResourceNames = asList(instrumentationModule.helperResourceNames());
|
||||
List<TypeInstrumentation> typeInstrumentations = instrumentationModule.typeInstrumentations();
|
||||
if (typeInstrumentations.isEmpty()) {
|
||||
|
@ -68,7 +68,7 @@ public final class ActualInstrumentationExtensionImplementation
|
|||
|
||||
ElementMatcher.Junction<ClassLoader> moduleClassLoaderMatcher =
|
||||
instrumentationModule.classLoaderMatcher();
|
||||
MuzzleMatcher muzzleMatcher = new MuzzleMatcher(instrumentationModule);
|
||||
MuzzleMatcher muzzleMatcher = new MuzzleMatcher(instrumentationModule, helperClassNames);
|
||||
AgentBuilder.Transformer helperInjector =
|
||||
new HelperInjector(
|
||||
instrumentationModule.extensionName(), helperClassNames, helperResourceNames);
|
||||
|
@ -135,11 +135,14 @@ public final class ActualInstrumentationExtensionImplementation
|
|||
*/
|
||||
private static class MuzzleMatcher implements AgentBuilder.RawMatcher {
|
||||
private final InstrumentationModule instrumentationModule;
|
||||
private final List<String> helperClassNames;
|
||||
private final AtomicBoolean initialized = new AtomicBoolean(false);
|
||||
private volatile ReferenceMatcher referenceMatcher;
|
||||
|
||||
private MuzzleMatcher(InstrumentationModule instrumentationModule) {
|
||||
private MuzzleMatcher(
|
||||
InstrumentationModule instrumentationModule, List<String> helperClassNames) {
|
||||
this.instrumentationModule = instrumentationModule;
|
||||
this.helperClassNames = helperClassNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -185,7 +188,7 @@ public final class ActualInstrumentationExtensionImplementation
|
|||
if (initialized.compareAndSet(false, true)) {
|
||||
referenceMatcher =
|
||||
new ReferenceMatcher(
|
||||
instrumentationModule.getAllHelperClassNames(),
|
||||
helperClassNames,
|
||||
instrumentationModule.getMuzzleReferences(),
|
||||
instrumentationModule::isHelperClass);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ import io.opentelemetry.javaagent.extension.spi.AgentExtension;
|
|||
import io.opentelemetry.javaagent.instrumentation.api.SafeServiceLoader;
|
||||
import io.opentelemetry.javaagent.instrumentation.api.internal.BootstrapPackagePrefixesHolder;
|
||||
import io.opentelemetry.javaagent.spi.BootstrapPackagesProvider;
|
||||
import io.opentelemetry.javaagent.spi.ByteBuddyAgentCustomizer;
|
||||
import io.opentelemetry.javaagent.spi.ComponentInstaller;
|
||||
import io.opentelemetry.javaagent.spi.IgnoreMatcherProvider;
|
||||
import io.opentelemetry.javaagent.tooling.config.ConfigInitializer;
|
||||
|
@ -170,7 +169,6 @@ public class AgentInstaller {
|
|||
}
|
||||
}
|
||||
|
||||
agentBuilder = customizeByteBuddyAgent(agentBuilder);
|
||||
log.debug("Installed {} instrumenter(s)", numInstrumenters);
|
||||
ResettableClassFileTransformer resettableClassFileTransformer = agentBuilder.installOn(inst);
|
||||
installComponentsAfterByteBuddy(componentInstallers, config);
|
||||
|
@ -221,15 +219,6 @@ public class AgentInstaller {
|
|||
}
|
||||
}
|
||||
|
||||
private static AgentBuilder customizeByteBuddyAgent(AgentBuilder agentBuilder) {
|
||||
Iterable<ByteBuddyAgentCustomizer> agentCustomizers = loadByteBuddyAgentCustomizers();
|
||||
for (ByteBuddyAgentCustomizer agentCustomizer : agentCustomizers) {
|
||||
log.debug("Applying agent builder customizer {}", agentCustomizer.getClass().getName());
|
||||
agentBuilder = agentCustomizer.customize(agentBuilder);
|
||||
}
|
||||
return agentBuilder;
|
||||
}
|
||||
|
||||
private static Iterable<ComponentInstaller> loadComponentProviders() {
|
||||
return ServiceLoader.load(ComponentInstaller.class, AgentInstaller.class.getClassLoader());
|
||||
}
|
||||
|
@ -245,11 +234,6 @@ public class AgentInstaller {
|
|||
return new NoopIgnoreMatcherProvider();
|
||||
}
|
||||
|
||||
private static Iterable<ByteBuddyAgentCustomizer> loadByteBuddyAgentCustomizers() {
|
||||
return ServiceLoader.load(
|
||||
ByteBuddyAgentCustomizer.class, AgentInstaller.class.getClassLoader());
|
||||
}
|
||||
|
||||
private static List<? extends AgentExtension> loadAgentExtensions() {
|
||||
// TODO: InstrumentationModule should no longer be an SPI
|
||||
Stream<? extends AgentExtension> extensions =
|
||||
|
|
|
@ -195,7 +195,7 @@ class MuzzleCodeGenerator implements AsmVisitorWrapper {
|
|||
|
||||
private void generateMuzzleHelperClassNamesMethod(ReferenceCollector collector) {
|
||||
/*
|
||||
* protected String[] getMuzzleHelperClassNames() {
|
||||
* public String[] getMuzzleHelperClassNames() {
|
||||
* return new String[] {
|
||||
* // sorted helper class names
|
||||
* };
|
||||
|
@ -203,7 +203,7 @@ class MuzzleCodeGenerator implements AsmVisitorWrapper {
|
|||
*/
|
||||
MethodVisitor mv =
|
||||
super.visitMethod(
|
||||
Opcodes.ACC_PROTECTED,
|
||||
Opcodes.ACC_PUBLIC,
|
||||
MUZZLE_HELPER_CLASSES_METHOD_NAME,
|
||||
"()[Ljava/lang/String;",
|
||||
null,
|
||||
|
@ -236,7 +236,7 @@ class MuzzleCodeGenerator implements AsmVisitorWrapper {
|
|||
|
||||
private void generateMuzzleReferencesMethod(ReferenceCollector collector) {
|
||||
/*
|
||||
* protected synchronized Reference[] getMuzzleReferences() {
|
||||
* public synchronized Reference[] getMuzzleReferences() {
|
||||
* if (null == this.muzzleReferences) {
|
||||
* this.muzzleReferences = new Reference[] {
|
||||
* // reference builders
|
||||
|
@ -248,7 +248,7 @@ class MuzzleCodeGenerator implements AsmVisitorWrapper {
|
|||
try {
|
||||
MethodVisitor mv =
|
||||
super.visitMethod(
|
||||
Opcodes.ACC_PROTECTED + Opcodes.ACC_SYNCHRONIZED,
|
||||
Opcodes.ACC_PUBLIC + Opcodes.ACC_SYNCHRONIZED,
|
||||
MUZZLE_REFERENCES_METHOD_NAME,
|
||||
"()[Lio/opentelemetry/javaagent/extension/muzzle/Reference;",
|
||||
null,
|
||||
|
@ -534,7 +534,7 @@ class MuzzleCodeGenerator implements AsmVisitorWrapper {
|
|||
|
||||
private void generateMuzzleContextStoreClassesMethod(ReferenceCollector collector) {
|
||||
/*
|
||||
* protected Map<String, String> getMuzzleContextStoreClasses() {
|
||||
* public Map<String, String> getMuzzleContextStoreClasses() {
|
||||
* Map<String, String> contextStore = new HashMap();
|
||||
* contextStore.put(..., ...);
|
||||
* return contextStore;
|
||||
|
@ -542,7 +542,7 @@ class MuzzleCodeGenerator implements AsmVisitorWrapper {
|
|||
*/
|
||||
MethodVisitor mv =
|
||||
super.visitMethod(
|
||||
Opcodes.ACC_PROTECTED,
|
||||
Opcodes.ACC_PUBLIC,
|
||||
MUZZLE_CONTEXT_STORE_CLASSES_METHOD_NAME,
|
||||
"()Ljava/util/Map;",
|
||||
null,
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
package io.opentelemetry.javaagent.tooling.muzzle.matcher;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
|
||||
import io.opentelemetry.javaagent.extension.muzzle.Reference;
|
||||
import io.opentelemetry.javaagent.tooling.HelperInjector;
|
||||
|
@ -49,7 +51,7 @@ public final class MuzzleGradlePluginUtil {
|
|||
ServiceLoader.load(InstrumentationModule.class, agentClassLoader)) {
|
||||
ReferenceMatcher muzzle =
|
||||
new ReferenceMatcher(
|
||||
instrumentationModule.getAllHelperClassNames(),
|
||||
asList(instrumentationModule.getMuzzleHelperClassNames()),
|
||||
instrumentationModule.getMuzzleReferences(),
|
||||
instrumentationModule::isHelperClass);
|
||||
List<Mismatch> mismatches = muzzle.getMismatchedReferenceSources(userClassLoader);
|
||||
|
@ -88,7 +90,7 @@ public final class MuzzleGradlePluginUtil {
|
|||
ServiceLoader.load(InstrumentationModule.class, agentClassLoader)) {
|
||||
try {
|
||||
// verify helper injector works
|
||||
List<String> allHelperClasses = instrumentationModule.getAllHelperClassNames();
|
||||
List<String> allHelperClasses = asList(instrumentationModule.getMuzzleHelperClassNames());
|
||||
if (!allHelperClasses.isEmpty()) {
|
||||
new HelperInjector(
|
||||
MuzzleGradlePluginUtil.class.getSimpleName(),
|
||||
|
|
|
@ -6,13 +6,19 @@
|
|||
package io.opentelemetry.javaagent.testing.bytebuddy;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import io.opentelemetry.javaagent.spi.ByteBuddyAgentCustomizer;
|
||||
import io.opentelemetry.javaagent.extension.spi.AgentExtension;
|
||||
import net.bytebuddy.agent.builder.AgentBuilder;
|
||||
|
||||
@AutoService(ByteBuddyAgentCustomizer.class)
|
||||
public class TestByteBuddyAgentCustomizer implements ByteBuddyAgentCustomizer {
|
||||
@AutoService(AgentExtension.class)
|
||||
public class TestAgentExtension implements AgentExtension {
|
||||
|
||||
@Override
|
||||
public AgentBuilder customize(AgentBuilder agentBuilder) {
|
||||
public AgentBuilder extend(AgentBuilder agentBuilder) {
|
||||
return agentBuilder.with(TestAgentListener.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String extensionName() {
|
||||
return "test";
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue