Quarkus中RestClient调用API时TraceID无法传递问题排查
问题
我有一个QuarkusMain应用,通过RestClient调用另一个Quarkus API。我在run()方法上添加了@WithSpan注解,能在QuarkusMain应用中获取到spanId和traceId:
@Override @WithSpan public int run(String... args) { // 业务逻辑 }
但run方法通过RestClient调用另一Quarkus应用的REST服务时,API端无法获取到相同的traceId。根据Quarkus OpenTelemetry文档,上下文应该自动传递,请问我遗漏了什么配置?
补充信息1
QuarkusMain应用日志:
{"spanId":"1e0a6b40db4a3e24","traceId":"d9a4bc00ab3b2f576223de16f1026fc7","sampled":"true"}
Quarkus API日志:
{"spanId":"6b490589e3a7650d","parentId":"d7b1d6a2ab520e84","traceId":"079089560b1a4d0af84252a86bfa0e74","sampled":"true"}
API收到的traceparent头:
00-079089560b1a4d0af84252a86bfa0e74-d7b1d6a2ab520e84-01
可见traceparent头与API日志匹配,说明在主类日志和API调用之间生成了新的spanId/traceId。
补充信息2
- Quarkus版本:2.16.4.Final
- 依赖:
<dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-opentelemetry</artifactId> </dependency>
- 配置:
quarkus.opentelemetry.enabled=true
解决方案
核心问题是QuarkusMain的主线程Span上下文没有正确传递到RestClient的调用链路中,可通过以下步骤修复:
- 添加RestClient的OpenTelemetry扩展依赖
当前仅引入了基础OpenTelemetry依赖,但RestClient的上下文传递需要专属扩展支持。在pom.xml中添加:
<dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-rest-client-opentelemetry</artifactId> </dependency>
该扩展会自动在RestClient请求中注入traceparent等上下文头,实现链路传递。
- 确保Span上下文在主线程中正确传播
QuarkusMain的启动线程存在上下文隔离可能,可手动绑定上下文确保传递:
@Override @WithSpan public int run(String... args) { Context currentContext = Context.current(); // 将业务逻辑和RestClient调用包裹在当前上下文内执行 return currentContext.wrap(() -> { // 此处执行你的业务逻辑与RestClient调用 return 0; }).call(); }
- 完善OpenTelemetry配置
在application.properties中添加以下配置,强制启用标准上下文传播协议:
quarkus.opentelemetry.propagators=tracecontext,baggage
tracecontext是W3C标准的traceparent传递协议,必须开启才能保证跨服务的链路上下文共享。
- 排查自定义拦截器干扰
如果你的RestClient接口有自定义拦截器,需确保没有覆盖或清除traceparent头。添加上述扩展后,无需手动处理头传递,若存在自定义拦截逻辑,需避免修改HTTP请求头中的trace相关字段。
原理说明
主应用run()方法生成的Span,因缺少RestClient的OpenTelemetry扩展,无法自动将上下文注入到HTTP请求头中,导致API端生成了全新的Trace链路。添加扩展并配置后,RestClient调用会继承主应用的Span上下文,API端的Span将成为主应用Span的子Span,共享同一个traceId。
内容的提问来源于stack exchange,提问作者godo57
相关产品推荐
相关产品推荐

