解决代码使用CompletableFuture做异步时spring-cloud-starter-sleuth的日志追踪号为空的情况

发布时间 2023-09-05 15:11:11作者: 品书读茶

产生问题原因

就是异步调用,导致spanId和traceId丢失了
@Async 注解的异步调用是没问题的

前提

关于追踪号的xml 配置为

<pattern>%yellow(%date{yyyy-MM-dd HH:mm:ss.SSS}) [%X{X-B3-TraceId:-},%X{X-B3-SpanId:-},%X{X-B3-ParentSpanId:-},%X{X-Span-Export:-}] %highlight(%-5level) %yellow(%thread) %green(%logger:%line)  %msg%n</pattern>

当CompletableFuture有一个任务时,代码的写法

import brave.Span;
import brave.Tracer;

@Autowired
private Tracer tracer;

public String completableFutureTestOne() {
    log.info("--------");
    Span span = tracer.nextSpan();
    CompletableFuture.supplyAsync(()->{
        try (Tracer.SpanInScope cleared = tracer.withSpanInScope(span)) {
            print("zhangsan");
            return "zhangsan";
        }catch (Exception e) {
            e.printStackTrace();
            return "zhangsan";
        }

    });
    return "ok111";
}

当CompletableFuture有多个任务时,代码的写法

import brave.Span;
import brave.Tracer;
import brave.propagation.TraceContext;

@Autowired
private Tracer tracer;

public String completableFutureTest() {
    log.info("--------");
    TraceContext context = tracer.nextSpan().context();
    CompletableFuture.supplyAsync(()->{
        Span span = tracer.newChild(context);
        try (Tracer.SpanInScope cleared = tracer.withSpanInScope(span)) {
            print("zhangsan");
            return "zhangsan";
        }catch (Exception e) {
            e.printStackTrace();
            return "zhangsan";
        }

    });

    CompletableFuture.supplyAsync(()->{
        Span span = tracer.newChild(context);
        try (Tracer.SpanInScope cleared = tracer.withSpanInScope(span)) {
            print("lisi");
            return "lisi";
        }catch (Exception e) {
            e.printStackTrace();
            return "lisi";
        }
    });
    return "ok";
}