zalando/logbook

Allow automatic context propagation when using Spring Webflux

grassehh opened this issue · 1 comments

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