Tracing Context not logged in access-log when replacing ReactorNettyHttpTracing with standard HttpClient/HttpServer integration
sandra-markerud opened this issue · comments
Describe the Bug
Spring Boot 2 with Spring Sleuth -> Spring Boot 3 with Micrometer migration
Hello, I try to upgrade our reactive spring-cloud-gateway from Spring Boot 2 with Sleuth to Spring Boot 3 with Micrometer Tracing.
Due to the findings and fixes in #2850 and https://github.com/grassehh/spring-boot-3-tracing-coroutine I already came a long way in fixing all our problems.
However, one problem remains:
In 9 of 10 cases the Netty access-log does not contain the traceId and spanId.
Steps to Reproduce
- Clone this project.
- Checkout any of the
spring-boot-3
branches (both kotlin and java available) - Either start the app and call the server as explained in the README or run the provided tests
- The tests concerning the tracing context of the access-log are
@RepeatedTest
s and executed 10 times. Here it occasionally happens that in one out of ten runs the access-log does contain the tracing context
Expected Result
The Netty access-log should always contain the Tracing Context
Thank you in advance for your help!
@sandra-markerud For your use case you need to add the change below to your de.markerud.upgrade.configuration.TracingChannelDuplexHandler
@Override
public void flush(ChannelHandlerContext ctx) {
try (Scope scope = contextSnapshotFactory.setThreadLocalsFrom(ctx.channel())) {
ctx.flush();
}
}
@violetagg Thank you so much!
I can confirm, that the access-log now shows the tracing context.
I have one more question though:
The TracingChannelDuplexHandler is always coupled with Logbook.
How could I separate this?
Say, I always want the tracing-context logged in the access-log, but I need to be able to disable logbook.
@sandra-markerud Can you try the code below?
class TracingChannelDuplexHandler extends ChannelDuplexHandler {
private final ContextSnapshotFactory contextSnapshotFactory;
public TracingChannelDuplexHandler(ContextSnapshotFactory contextSnapshotFactory) {
this.contextSnapshotFactory = contextSnapshotFactory;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
try (Scope scope = contextSnapshotFactory.setThreadLocalsFrom(ctx.channel())) {
ctx.fireChannelRead(msg);
}
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
try (Scope scope = contextSnapshotFactory.setThreadLocalsFrom(ctx.channel())) {
ctx.write(msg, promise);
}
}
@Override
public void flush(ChannelHandlerContext ctx) {
try (Scope scope = contextSnapshotFactory.setThreadLocalsFrom(ctx.channel())) {
ctx.flush();
}
}
}
@violetagg this would still work for the access-log. Yes.
But now the logbook logs would not be written.
I need to instrument the TracingChannelDuplexHandler either with or without logbook, depending on if logbook is enabled or not
@sandra-markerud I don't understand ... you can use different ChannelDuplexHandler implementations depending on whether you want to use logbook or not.
@violetagg You're right of course. My bad!
Thank you a lot for your quick response.