GuanceCloud / dd-trace-java

Datadog APM client for Java
https://docs.datadoghq.com/tracing/languages/java
Apache License 2.0
9 stars 3 forks source link

咨询关于自定义instrumentation的问题 #53

Closed callmediaomao closed 6 months ago

callmediaomao commented 10 months ago

参考观测云https://docs.guance.com/best-practices/monitoring/ddtrace-instrumentation/#extract 文档进行自定义instrumentation组件。 遇到两个问题想请教下:

  1. static/构造器进行transformation.applyadvice无法成功 image

  2. 关于抽象类的埋点我使用了implements Instrumenter.ForTypeHierarchy来,但是无法捕获到,我看到打印了No maven dependency added spring-tx 和 Resolved dependency spring-tx。但是无法进入到对应的增强方法当中。 image image

lrwh commented 10 months ago

问题1:static/构造器进行transformation.applyadvice无法成功

建议输出下日志,用system.out.println();看看是否执行到了这里

如果执行到了,建议开启 debug 模式,可以从debug日志上分析出问题

关于抽象类的埋点我使用了implements Instrumenter.ForTypeHierarchy来,但是无法捕获到,我看到打印了No maven dependency added spring-txResolved dependency spring-tx。但是无法进入到对应的增强方法当中。

callmediaomao commented 10 months ago

@lrwh 1. 我打开了debug有出现报错问题,应该是缺少了某一步,但是发现和其他示例没有差别 8e0c603ecb43fe90b239c81ed46d890

  1. transformation.applyadvice我修改了发现还是不行,并且将ForTypeHierarchy修改为ForSingleType dependencies { compileOnly group: 'org.springframework', name: 'spring-tx', version: '[5.0.4.RELEASE,5.1.10.RELEASE]' } 我采用skywalking的测试用例来测试,里面使用的springboot是5.0.4 image 其中我在agentbuild.listener打印日志发现 image image image 猜测该插件应该没有集成进去。 但是datadog中Dependency的日志让我觉得依赖应该被解析了才对 image
lrwh commented 10 months ago

@callmediaomao

关于问题一,建议你把 druid 需要做探针的方法贴一下或者druid的源码链接贴一下

关于问题二,建议把 build.gradle全文贴一下,是否生效只需看下面类似的日志

[dd.trace 2023-09-14 15:39:14:441 +0800] [main] DEBUG datadog.trace.agent.tooling.InstrumenterState - Instrumentation applied - instrumentation.names=[java_concurrent,runnable] instrumentation.class=datadog.trace.instrumentation.java.concurrent.RunnableInstrumentation instrumentation.target.classloader=org.springframework.boot.loader.LaunchedURLClassLoader@20e3c449
callmediaomao commented 10 months ago

@lrwh 方便的话可以加微信沟通:17670520466

  1. 源码:

    @AutoService(Instrumenter.class)
    public class DruidAddDataSourceInstrumentation extends Instrumenter.Tracing
    implements Instrumenter.ForSingleType {
    
    public DruidAddDataSourceInstrumentation() {
    super("druidDatasource","datasource");
    }
    
    public String instrumentedType() {
    return "com.alibaba.druid.stat.DruidDataSourceStatManager";
    }
    
    public String[] helperClassNames() {
    return new String[]{
        packageName + ".DataSourceDecorator",
    };
    }
    
    public Map<String, String> contextStore() {
    return Collections.singletonMap("java.sql.Connection", DBInfo.class.getName());
    }
    
    public void adviceTransformations(AdviceTransformation transformation) {
    transformation.applyAdvice(
        isMethod()
            .and(isStatic())
            .and(named("addDataSource"))
            .and(takesArguments(2).and(takesArgument(0, Object.class)))
            .and(returns(named("javax.management.ObjectName"))),
    
        DruidAddDataSourceInstrumentation.class.getName() + "$DataSourceAdvice"
    );
    }
    
    public static class DataSourceAdvice {
    
    @Advice.OnMethodEnter(suppress = Throwable.class)
    public static AgentScope onEnter(
        @Advice.This final DruidDataSourceStatManager ds,
        @Advice.Argument(0) final Object druidDataSource
    ) {
      try {
        AgentSpan span = startSpan("datasource", "datasource.addDataSource");
        DataSourceDecorator.DECORATE.afterStart(span);
        Connection connection = ((DruidDataSource)druidDataSource).getConnection();
        DataSourceDecorator.DECORATE.onConnection(span,connection, InstrumentationContext.get(Connection.class, DBInfo.class));
        AgentScope agentScope = activateSpan(span);
        connection.close();
        return agentScope;
      } catch (SQLException e) {
        return null;
      }
    }
    
    @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
    public static void stopSpan(
        @Advice.Enter final AgentScope scope,
        @Advice.Thrown final Throwable throwable) {
      if (scope == null) {
        return;
      }
      DataSourceDecorator.DECORATE.onError(scope, throwable);
      DataSourceDecorator.DECORATE.beforeFinish(scope);
      scope.close();
      scope.span().finish();
    }
    }
    }
  2. Gradle全文,打印未发现对应的日志

    
    apply from: "$rootDir/gradle/java.gradle"
    apply plugin: 'call-site-instrumentation'

dependencies { compileOnly group: 'org.springframework', name: 'spring-tx', version: '[5.0.4.RELEASE,5.1.10.RELEASE]' }

callmediaomao commented 10 months ago

@lrwh 第一个问题我发现我写了@Advice.This是导致报错的原因,我修改了,然后出现了类加载器阻塞😫 [dd.trace 2023-09-14 18:54:26:429 +0800] [main] DEBUG datadog.trace.agent.tooling.InstrumenterState - Instrumentation blocked - instrumentation.names=[druidDatasource,datasource] instrumentation.class=datadog.trace.instrumentation.datasource.DruidAddDataSourceInstrumentation instrumentation.target.classloader=sun.misc.Launcher$AppClassLoader@18b4aac2

lrwh commented 10 months ago

@callmediaomao 问题1: 建议调整下DruidAddDataSourceInstrumentation,看看是否有日志输出

 public void adviceTransformations(AdviceTransformation transformation) {
    transformation.applyAdvice(
        isMethod()
            .and(isStatic())
            .and(named("addDataSource"))),

        DruidAddDataSourceInstrumentation.class.getName() + "$DataSourceAdvice"
    );
  }

  public static class DataSourceAdvice {

    @Advice.OnMethodEnter(suppress = Throwable.class)
    public static AgentScope onEnter( ) {
       System.out.println("do DataSourceAdvice")
     return null;
    }

  }

问题2: gradle 文件缺少了 muzzle部分,所以不会生效,可参考文档 ddtrace 系列篇之实战:自定义 Apache-Dubbo Instrumentation.

callmediaomao commented 10 months ago

@lrwh 问题2的build.gradle我添加了还是不生效

muzzle {
  pass {
    group = 'org.springframework'
    module = 'spring-tx'
    versions = "5.0.4.RELEASE"
    // assertInverse = true
  }
}
lrwh commented 10 months ago

@callmediaomao

试试以下配置

muzzle {
  pass {
    group = 'org.springframework'
    module = 'spring-tx'
    versions = "[5.0.0,]"
    // assertInverse = true
  }
}
callmediaomao commented 10 months ago

@lrwh 也不行,我怀疑是没有依赖注入进去。进入了 listener onignore方法当中