How to get back MDC "inheritance" with modern logback?

I see no straightforward way to change this back. Two alternatives that come to mind are:

Way #1: Wrap all Runnables

Introduce an abstract class that will copy MDC from the original Thread to a new Thread and use it instead of Runnable

public abstract class MdcAwareRunnable implements Runnable
{
    private Map<String, String> originalMdc;

    public MdcAwareRunnable()
    {
        this.originalMdc = MDC.getCopyOfContextMap();
    }

    @Override
    public void run()
    {
        MDC.setContextMap(originalMdc);
        runImpl();
    }

    protected abstract void runImpl();

    /**
     * In case some Runnable comes from external API and we can't change that code we can wrap it anyway.
     */
    public static MdcAwareRunnable wrap(Runnable runnable)
    {
        return new MdcAwareRunnable()
        {
            @Override
            protected void runImpl()
            {
                runnable.run();
            }
        };
    }
}

If some Runnable comes from an external API that you can't change that code, use wrap helper method.

Drawback: need to analyze and change whole code.

Way #2: Mess with slf4j internals

Resurrect the original LogbackMDCAdapter implementation that uses InheritableThreadLocal from before that commit and put it somewhere in your code under some other name. Then somewhere around startup use reflection to override MDC.mdcAdapter property with and instance of that custom implementation. This is obviously a dirty hack but it saves a lot of troubles comparing to #1.

Note: for performance reasons it makes to inherit your resurrected version from existing LogbackMDCAdapter and just override all the methods with old implementation. See LoggingEvent.java and LogbackMDCAdapter.getPropertyMap internal method for some details.

Way #3: Mess with logback jar (even stranger alternative)

This sounds to me as a quite bad plan but for completness here it is.

Again resurrect the original LogbackMDCAdapter but this time don't rename, compile it and override that .class file inside logback.jar.

Or resurrect the original LogbackMDCAdapter with renaming, remove .class file for org.slf4j.impl.StaticMDCBinder from logback.jar and add your own class that will return resurrected version of LogbackMDCAdapter either to logback.jar or to your code. MDC seems to be bound to that class by name to create an implementation of MDCAdapter to use.

Or you can achieve similar result by using custom ClassLoader that would map org.slf4j.impl.StaticMDCBinder to your class instead of the one inside logback.jar. Note: this is probably impossible to achieve inside a Web-container that will add its own custom ClassLoaders.

Tags:

Slf4J

Logback

Mdc