Using Finatra, I'm trying to activate traceID logging, but nothing ends up in Log4J2 output.
Finatra supports SLF4J MDC. SLF4J MDC is supposed to support Log4J (2?). Log4J2 is supposed to support MDC and SLF4J.
But in the end, the MDC data is always empty reaching the message construction.
I tested with Logback as the log implementation and I had the MDC logged correctly, and it is actually relying on SLF4J MDC. I do have to use log4J2 here (cannot be questioned).
Is this just not working because Log4J2 does not work correctly with SLF4J MDC?
To get it to work with Finatra, I just have to remove the LoggingMDCFilter which pretty must only replaces the MDCAdapter with the FinagleMDCAdapter own implementation, backed by Finagle Contexts.
As you noticed in your question
FinagleMDCInitializerreplaces the MDC used by the logging backend with its own.Logback uses SLF4J as their internal API (i.e. just Logback) so it will work with any
MDCAdapterimplementation installed, but all the remaining SLF4J backends won't.The same hack that permits Logback to work with Finagle can be used in Log4j2 Core. Log4j2 Core is a native implementation of Log4j2 API and it will work with any implementation of
ThreadContextMap.We want to use a
ThreadContextMapimplementation that delegates all methods to SLF4J'sMDC. Fortunately such an implementation is included in the Apache Log4j2 API to SLF4J Adapter (another implementation of the Log4j2 API). So we can use the following trick:add both
log4j-coreandlog4j-to-slf4jto your application's classpath. Since now there are two implementations of the Log4j2 API available, we need to specify the one we actually want to use. We can do it by adding a file calledlog4j2.component.propertiesat the root of your classpath with:in the same property file we specify that we want to use the
ThreadContextMapimplementation included inlog4j-to-slf4j:I assume that you already have
log4j-slf4j-impl(Apache SLF4J to Log4j2 API Adapter) on your classpath.Remark: the proposed solution assumes that
FinagleMDCInitializeris called as soon as possible. SLF4J does not have an equivalent of thelog4j2.threadContexMapproperty to force it to use a concrete implementation ofMDCAdapter. Until Finagle replaces the implementations, your application will use theMDCAdapterfromlog4j-slf4j-implthat delegates everything to theThreadContextMap, that delegates everything toMDCAdapter, ... You'll have a guaranteed StackOverflow.Edit: If you end up with a StackOverflow, you can:
start with NOOP
ThreadContextMap:replace the
MDCAdapterandThreadContextMapall in one place: