You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenTelemetry扩展中TypeTransformer applyAdviceToMethod的isConstructor()失效问题

问题描述

我尝试用OpenTelemetry JavaAgent及扩展,在某个类的构造方法被调用时添加Span实现追踪。配置代码后,给构造方法加的日志没有输出,但给普通方法(比如dummyMethod)配置时正常生效,请问我的配置哪里有问题?

相关代码

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");
        
    }
}
问题分析与解决

你的配置问题主要出在构造方法的织入时机和匹配细节上:

  • 类加载顺序冲突:如果ServiceManagerDummy在OpenTelemetry Agent及你的扩展加载之前就被类加载器初始化了,构造方法的Advice根本没机会织入。普通方法是懒加载的,后续调用时才会触发织入,所以能正常生效。
  • 构造方法匹配精度不足:isConstructor()会匹配所有构造方法,若你的类存在多个构造方法,或者织入逻辑没覆盖到当前调用的构造,就会无输出。建议明确匹配无参构造:isConstructor().and(ElementMatchers.takesArguments(0))。
  • 扩展未正确注册:检查你的扩展Jar中是否存在META-INF/services/io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation文件,文件内容必须写入你的Instrumentation类全限定名(比如org.example.ClassConstructorInstrumentation),否则Agent找不到你的扩展逻辑。
  • Agent启动参数缺失:启动应用时,要确保扩展Jar通过--otel-javaagent-extensions参数传给JavaAgent,示例命令:
    java -javaagent:opentelemetry-javaagent.jar --otel-javaagent-extensions=your-extension.jar -jar your-app.jar
    

另外,把日志替换成OpenTelemetry的Span创建逻辑,能更准确验证织入是否成功:

@SuppressWarnings("unused")
public static class ConstructorSpanCreateAdvice {
    private static final Tracer TRACER = GlobalOpenTelemetry.getTracer("service-manager-instrumentation");

    @Advice.OnMethodEnter
    public static void onEnter() {
        Span span = TRACER.spanBuilder("ServiceManagerDummy.constructor").startSpan();
        span.makeCurrent();
        System.out.println("构造方法Span已启动: " + span.getSpanContext().getSpanId());
    }

    @Advice.OnMethodExit(onThrowable = Throwable.class)
    public static void onExit(@Advice.Thrown Throwable throwable) {
        Span currentSpan = Span.current();
        if (throwable != null) {
            currentSpan.recordException(throwable);
        }
        currentSpan.end();
        System.out.println("构造方法Span已结束: " + currentSpan.getSpanContext().getSpanId());
    }
}

内容的提问来源于stack exchange,提问作者Valeriy K.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 04:31:01