In my Spring Webflux application to have tracing headers in the logs (MDC) I have followed the FAQ from Reactor (https://projectreactor.io/docs/core/release/reference/#faq.mdc). It works nice. However, it is not suitable when I need to add logs with synchronous processing (like within map).
To solve this problem I have created a decorator for slf4j Logger which takes as a parameter the ContextView:
public class LoggerWithMDC {
private final Logger logger;
public void info(String message, ContextView context, Object... args) {
logWithTracingHeaders(context, () -> logger.info(message, args));
}
private static void logWithTracingHeaders(ContextView context, Runnable logStatement) {
final Map<String, String> mdcTracingValues = extractTracingValuesFromContext(context);
try {
mdcTracingValues.forEach(MDC::put);
logStatement.run();
} finally {
mdcTracingValues.keySet().forEach(MDC::remove);
}
}
}
and the sample usage:
Mono.deferContextual(Mono::just)
.flatMap(
contextView ->
Mono.just("value")
.map(
value -> {
loggerWithMDC.info("Received value to convert: {}", contextView, value);
return value.toUpperCase();
})
.contextWrite(Context.of("traceid", ULID.random())))
It works fine but is there any better way to do this without passing contextView?