使用CompletableFuture.handle时OpenTelemetry链路追踪丢失求助
解决OpenTelemetry在CompletableFuture.handle中链路追踪丢失问题
问题原因
CompletableFuture的异步回调默认不会自动传播OpenTelemetry的Context,线程切换时上下文无法传递到回调逻辑中,导致Trace丢失。另外如果未正确引入CompletableFuture的自动插桩依赖,也会导致上下文无法自动传播。
解决方案
1. 确保引入CompletableFuture自动插桩依赖
OpenTelemetry提供了专门的CompletableFuture插桩模块,用于自动处理上下文传播。如果使用Maven,添加以下依赖:
<dependency> <groupId>io.opentelemetry.instrumentation</groupId> <artifactId>opentelemetry-instrumentation-completable-future</artifactId> <version>适配你的OpenTelemetry版本</version> <scope>runtime</scope> </dependency>
如果是Spring Boot项目,也可通过opentelemetry-spring-boot-starter间接引入,但需确保版本兼容。
2. 手动上下文传播(自动插桩不生效时备用)
如果自动插桩无法生效,可手动在主线程保存当前上下文,然后用Context.wrap包裹回调函数,强制传递上下文:
@GetMapping("/future3") public CompletableFuture<ResponseEntity<String>> future3() { LOGGER.info("future1 "); LOGGER.info("trace={}", Span.current().getSpanContext().getTraceId()); // 保存主线程的OpenTelemetry上下文 Context currentContext = Context.current(); SqsAsyncClient sqsAsyncClient = SqsAsyncClient.builder().build(); CompletableFuture<ResponseEntity<String>> aa = sqsAsyncClient .sendMessage(build -> build.queueUrl(queueUrl).messageBody("hello")) // 用Context.wrap包裹回调,传递上下文 .handle(Context.wrap(currentContext, (response, error) -> { LOGGER.info("trace response={}", Span.current().getSpanContext().getTraceId()); LOGGER.info("test response={}", response); return new ResponseEntity<>("success", HttpStatus.OK); })); LOGGER.info("future1_1"); return aa; }
3. 验证SqsAsyncClient插桩生效
确保SqsAsyncClient的调用已被OpenTelemetry追踪,这样sendMessage生成的Span会自动关联到主线程的Trace中,形成完整链路。可通过检查Trace数据是否包含SQS调用的Span来验证。
内容的提问来源于stack exchange,提问作者user1684689
相关产品推荐
相关产品推荐

