in apm-agent-core/src/main/java/co/elastic/apm/agent/bci/ElasticApmAgent.java [388:456]
private static AgentBuilder applyAdvice(final ElasticApmTracer tracer, final AgentBuilder agentBuilder,
final ElasticApmInstrumentation instrumentation, final ElementMatcher<? super TypeDescription> typeMatcher) {
final Logger logger = getLogger();
logger.debug("Applying instrumentation {}", instrumentation.getClass().getName());
final boolean classLoadingMatchingPreFilter = tracer.getConfig(CoreConfigurationImpl.class).isClassLoadingMatchingPreFilter();
final boolean typeMatchingWithNamePreFilter = tracer.getConfig(CoreConfigurationImpl.class).isTypeMatchingWithNamePreFilter();
final ElementMatcher.Junction<ClassLoader> classLoaderMatcher = instrumentation.getClassLoaderMatcher();
final ElementMatcher<? super NamedElement> typeMatcherPreFilter = instrumentation.getTypeMatcherPreFilter();
final ElementMatcher.Junction<ProtectionDomain> versionPostFilter = instrumentation.getProtectionDomainPostFilter();
final ElementMatcher<? super MethodDescription> methodMatcher = new ElementMatcher.Junction.Conjunction<>(instrumentation.getMethodMatcher(), not(isAbstract()));
final AgentBuilder.RawMatcher matcher = new AgentBuilder.RawMatcher() {
@Override
public boolean matches(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, Class<?> classBeingRedefined, ProtectionDomain protectionDomain) {
if (classLoadingMatchingPreFilter && !classLoaderMatcher.matches(classLoader)) {
return false;
}
if (typeMatchingWithNamePreFilter && !typeMatcherPreFilter.matches(typeDescription)) {
return false;
}
boolean typeMatches;
try {
typeMatches = typeMatcher.matches(typeDescription) && versionPostFilter.matches(protectionDomain);
} catch (Exception ignored) {
// could be because of a missing type
typeMatches = false;
}
if (typeMatches) {
logger.debug("Type match for instrumentation {}: {} matches {}",
instrumentation.getClass().getSimpleName(), typeMatcher, typeDescription);
try {
instrumentation.onTypeMatch(typeDescription, classLoader, protectionDomain, classBeingRedefined);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
if (logger.isTraceEnabled()) {
logClassLoaderHierarchy(classLoader, logger, instrumentation);
}
}
return typeMatches;
}
};
AgentBuilder.RawMatcher statsCollectingMatcher = new AgentBuilder.RawMatcher() {
@Override
public boolean matches(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, Class<?> classBeingRedefined, ProtectionDomain protectionDomain) {
long start = System.nanoTime();
try {
return matcher.matches(typeDescription, classLoader, module, classBeingRedefined, protectionDomain);
} finally {
instrumentationStats.getOrCreateTimer(instrumentation.getClass()).addTypeMatchingDuration(System.nanoTime() - start);
}
}
};
return agentBuilder
.type(instrumentationStats.shouldMeasureMatching() ? statsCollectingMatcher : matcher)
.transform(new PatchBytecodeVersionTo51Transformer())
.transform(getTransformer(instrumentation, logger, methodMatcher))
.transform(new AgentBuilder.Transformer() {
@Override
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription,
ClassLoader classLoader, JavaModule module, ProtectionDomain protectionDomain) {
if (!ancientBytecodeInstrumentationEnabled) {
builder = builder.visit(MinimumClassFileVersionValidator.V1_4);
}
// As long as we allow 1.4 bytecode, we need to add this constant pool adjustment as well
return builder.visit(TypeConstantAdjustment.INSTANCE);
}
});
}