reactor / reactor-netty

TCP/HTTP/UDP/QUIC client/server with Reactor over Netty

Home Page:https://projectreactor.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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 @RepeatedTests 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.