zalando / logbook

An extensible Java library for HTTP request and response logging
MIT License
1.86k stars 261 forks source link

Allow automatic context propagation when using Spring Webflux #1745

Open grassehh opened 10 months ago

grassehh commented 10 months ago

Detailed Description

Important note: This issue is only about client calls, because even though this is also useful for server logs, there is currently an issue for server logs here

Currently, in order to have the MDC logged inside Spring WebClient request/response logs, when using logbook-logstash, it is necessary to wrap the LogbookClientHandler with a custom ChannelDuplexHandler

@Bean
fun logbookNettyClientCustomizer(logbook: Logbook, contextSnapshot: ContextSnapshotFactory) =
    ReactorNettyHttpClientMapper {
        it.proxyWithSystemProperties()
            .doOnConnected { connection: Connection ->
                connection.addHandlerLast(
                    TracingChannelDuplexHandler(LogbookClientHandler(logbook), contextSnapshot)
                )
            }
    }
class TracingChannelDuplexHandler(
    private val delegate: ChannelDuplexHandler,
    private val contextSnapshotFactory: ContextSnapshotFactory
) : ChannelDuplexHandler() {
    override fun channelRead(ctx: ChannelHandlerContext, msg: Any) {
        contextSnapshotFactory.setThreadLocalsFrom<String>(ctx.channel()).use {
            delegate.channelRead(ctx, msg)
        }
    }

    override fun write(ctx: ChannelHandlerContext, msg: Any, promise: ChannelPromise?) {
        contextSnapshotFactory.setThreadLocalsFrom<String>(ctx.channel()).use {
            delegate.write(ctx, msg, promise)
        }
    }
}

Context

This change would make it easier to configure context propagation when using Logbook Netty with Spring Webflux. Logging MDC context in logstash logs is particularly useful when combined with tool like Datadog, which natively parses JSON formatted logs and extracts event attributes as facets. When using observation library like micrometer-tracing, it is then as easy as adding a baggage before calling the logger. This baggage is then available in Datadog as an Event Attribute.

Possible Implementation

Maybe add a property like logbook.context-propagation: true which when enabled, instrumentate the WebClient to propagate the MDC context to be logged inside WebClient.

Your Environment

Sample available here

aldex32 commented 1 month ago

Yes definitely an important feature to have with regards to distributed tracing. Had the same issue and took me some time to figure it out.

@grassehh Does this solution logs twice the Outgoing Request and Incoming Response for you?