通过OpenTelemetry Java SDK实现进程内异步场景上下文传递

接入ARMS应用监控以后,ARMS探针对常见的Java框架进行了自动埋点,因此不需要修改任何代码,就可以实现调用链信息的采集。但如果您需要在进程内的异步场景下传递上下文,可以引入OpenTelemetry Java SDK实现。

ARMS探针支持的组件和框架,请参见ARMS应用监控支持的Java组件和框架

使用场景

接入ARMS应用监控以后,如果您的应用通过以下方式进行异步编程,由于ARMS探针对这些Java框架进行了埋点,Trace上下文会自动进行异步透传,此时无需改造代码。

  • 使用JDK线程池、Spring线程池、Netty线程池提交异步任务。

  • 使用React、RxJava框架编程。

  • 使用Spring @Async注解。

  • 使用Spring Webflux、Spring Gateway等框架编程。

但如果您的应用存在以下异步处理场景,则需要在进程内通过OpenTelemetry Java SDK手动传递Trace上下文:

  • 生产者消费者场景。

    线程T1在处理逻辑中将消息放入队列后,线程T2从队列中拉取消息处理,此时线程T2需要复用线程T1Trace上下文。

  • 数据库批处理场景。

    进程P1在处理逻辑中将一批数据写入数据库后,进程P2从数据库中读取该批数据并处理,此时进程P2需要复用进程P1Trace上下文。

前提条件

引入依赖

请先参考如下Maven代码引入OpenTelemetry Java SDK。更多信息,请参见OpenTelemetry官方文档

<dependencies>
    <dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-api</artifactId>
    </dependency>
    <dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-sdk-trace</artifactId>
    </dependency>
    <dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-sdk</artifactId>
    </dependency>
</dependencies>

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>io.opentelemetry</groupId>
      <artifactId>opentelemetry-bom</artifactId>
      <version>1.23.0</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

异步上下文传递

下方是一个简单的生产者消费者模式代码示例,在生产者中生产事件时,将生产者线程的Trace上下文记录到事件中,在消费事件时,取出上下文并还原。

class Event {
    private Context context;
    private String msg;

    public Event(Context context, String msg) {
        this.context = context;
        this.msg = msg;
    }
}

private final LinkedBlockingQueue<Event> linkedBlockingQueue = new LinkedBlockingQueue<Event>();

public void produce(String msg) {
    linkedBlockingQueue.add(new Event(Context.current(), msg));
}

public void consume() throws Exception {
    Event event = linkedBlockingQueue.take();
    try(Scope scope = event.context.makeCurrent()) {
        processEvent(event);
    }
}

public void processEvent(Event event) {
    //todo process event
}

相关文档

您可以在应用的业务日志中关联调用链的TraceId信息,从而在应用出现问题时,能够通过调用链的TraceId快速关联到业务日志,及时定位、分析解决问题。更多信息,请参见Java应用业务日志关联调用链TraceId