private static AgentBuilder applyAdvice()

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