【发布时间】:2021-08-23 11:16:36
【问题描述】:
我在多线程应用程序中使用跟踪时遇到问题。
背景:
在我的 SpringBoot 应用程序中,我有一个函数“service”,它调用另一个函数“innerService”,我想用自己的 span 跟踪每个函数。 我正在通过以下方式使用 Jaeger 实现 OpenTracing:
AppConfig.java:
@Bean
public static JaegerTracer getTracer() {
io.jaegertracing.Configuration.SamplerConfiguration samplerConfig = io.jaegertracing.Configuration.SamplerConfiguration.fromEnv().withType("const").withParam(1);
io.jaegertracing.Configuration.ReporterConfiguration reporterConfig = io.jaegertracing.Configuration.ReporterConfiguration.fromEnv().withLogSpans(true);
io.jaegertracing.Configuration config = new io.jaegertracing.Configuration("myService").withSampler(samplerConfig).withReporter(reporterConfig);
return config.getTracer();
}
然后我在我的一个应用服务中使用它:
@GrpcService
public class ServiceA extends ServiceAGrpc.ServiceAImplBase {
private final Tracer tracer;
@Autowired
public ServiceA(Tracer tracer) {
this.tracer = tracer;
}
@Override
public void service(Request request, StreamObserver<ResultGrpc> responseObserver) {
Span span = startSpanInScope(this.tracer, "service");
...
innerService();
...
span.finish();
}
返回范围的函数:
public static Span startSpanInScope(Tracer tracer, String spanName) {
if (tracer == null) {
return null;
}
Span span = tracer.buildSpan(spanName).start();
Scope scope = tracer.scopeManager().activate(span);
return span;
}
向服务发送单个请求时,一切似乎都很好,跨度出现在另一个中:
我猜这是因为每当一个跨度启动时,它就会成为当前活动跨度的子级,即使这个跨度来自另一个线程。我不明白为什么,因为我读到 ScopeManager 默认是一个 ThreadLocal 对象。
任何人都可以提出解决方案吗?我希望每个线程都有一个单独的跟踪,它将显示“服务”和“内部服务”的跨度作为其子项。
【问题讨论】:
-
您应该使用
try { ... } finally { }确保启动的范围随后关闭。
标签: java multithreading spring-boot jaeger opentracing