I am trying the opentelemetry auto-instrumentation. But it appears that the trace is being lost when using CompletableFuture.handle
. Could anyone please assist me with this issue?
@GetMapping("/future3")
public CompletableFuture<ResponseEntity<String>> future3() {
LOGGER.info("future1 "); // <- we have trace here
LOGGER.info("trace={}", Span.current().getSpanContext().getTraceId()); // <- we have trace here
SqsAsyncClient sqsAsyncClient = SqsAsyncClient.builder().build();
CompletableFuture<ResponseEntity<String>> aa = sqsAsyncClient
.sendMessage(build -> build.queueUrl(queueUrl).messageBody("hello"))
.handle((response, error) -> {
LOGGER.info("trace response={}", Span.current().getSpanContext().getTraceId()); // <- we lost trace
LOGGER.info("test response={}", response); // <- we lost trace
return new ResponseEntity<>("success", HttpStatus.OK);
});
LOGGER.info("future1_1"); // <- we have trace id
return aa;
}
I did have the same issue and luckily i can provide you the solution from your code I see that the issue you're have with losing the trace context when using CompletableFuture.handle. and as a solution I suggest that you can use Context, or maybe I see Span a good choice to propagation feature of OpenTelemetry explicitly to ensure that the trace context is propagated into the asynchronous callback. So first of all, Context can capture and pass explicitly to asynchronous tasks, and for me I suggest to Capture the current Context at the beginning of the method, and then use this captured context inside your .handle method
Well I did as well make some modification the code to help you to have fast product and this is the code:
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
@GetMapping("/future3")
public CompletableFuture<ResponseEntity<String>> future3() {
LOGGER.info("future1 ");
LOGGER.info("trace={}", Span.current().getSpanContext().getTraceId());
SqsAsyncClient sqsAsyncClient = SqsAsyncClient.builder().build();
// Capture the current OpenTelemetry context
Context currentContext = Context.current();
CompletableFuture<ResponseEntity<String>> aa = sqsAsyncClient
.sendMessage(build -> build.queueUrl(queueUrl).messageBody("hello"))
.handle((response, error) -> {
// Make the OpenTelemetry context current within this handle block
try (Scope scope = currentContext.makeCurrent()) {
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;
}
So this all I have to help I hope it works. Good Luck 😉🙏