log4j2slf4j-apifinatra

Does Log4j2 and SLF4J MDC get along?


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.


Solution

  • As you noticed in your question FinagleMDCInitializer replaces 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 MDCAdapter implementation 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 ThreadContextMap implementation that delegates all methods to SLF4J's MDC. 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:

    Remark: the proposed solution assumes that FinagleMDCInitializer is called as soon as possible. SLF4J does not have an equivalent of the log4j2.threadContexMap property to force it to use a concrete implementation of MDCAdapter. Until Finagle replaces the implementations, your application will use the MDCAdapter from log4j-slf4j-impl that delegates everything to the ThreadContextMap, that delegates everything to MDCAdapter, ... You'll have a guaranteed StackOverflow.

    Edit: If you end up with a StackOverflow, you can: