Search code examples
javaaspectjtracebyte-buddyopen-telemetry

TypeTransformer applyAdviceToMethod(isConstructor() doesn't works in opentelemetry extensions


I'm trying to add spans when constructor of some class called. I'm using opentelemetry javaagent and extensions to add tracing to my application.

import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers;

import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
import static net.bytebuddy.matcher.ElementMatchers.named;

public class ClassConstructorInstrumentation implements TypeInstrumentation {

    @Override
    public ElementMatcher<TypeDescription> typeMatcher() {
        return ElementMatchers
                .namedOneOf("org.example.ServiceManagerDummy");
    }

    @Override
    public void transform(TypeTransformer transformer) {
        transformer.applyAdviceToMethod(
                isConstructor(),
                this.getClass().getName() + "$ConstructorSpanCreateAdvice");
//        transformer.applyAdviceToMethod(
//                named("dummyMethod"), 
//                this.getClass().getName() + "$ConstructorSpanCreateAdvice");
    }

    @SuppressWarnings("unused")
    public static class ConstructorSpanCreateAdvice {

        @Advice.OnMethodEnter
        public static void onEnter() {
            System.out.println("START SPAN ");
        }

        @Advice.OnMethodExit(onThrowable = Throwable.class)
        public static void onExit(
                @Advice.Thrown Throwable throwable
        ) {
            System.out.println("END SPAN ");
        }
    }
}

public class ServiceManagerDummy {
    public ServiceManagerDummy() {
        System.out.println("SERVICE MANAGER CONSTR");
        dummyMethod();
    }

    private void dummyMethod() {
        System.out.println("DUMMY METHOD CALLED");
        
    }

    
}

I'm using a simple configuration as above just to verify that when the constructor was called my advice method log it. But when it configured to add some logs when the constructor was called, I received nothing in the log. But when I add config for method calling (commented code) it works. What's wrong in my configuration?


Solution

  • What Byte Buddy would normally do would be to wrap the constructor in a try-finally-block. For a constructor, that is not possible as the super method call cannot be wrapped in such a block. "onThrowable" is therefore not possible for constructors.