After going back to an older project and getting around to update its dependencies I had to realize that logback does not anymore propagate MDCs to children since version
I see no straightforward way to change this back. Two alternatives that come to mind are:
Way #1: Wrap all Runnable
s
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.
Way 4: Misuse TurboFilter
ch.qos.logback.classic.Logger
passes the logging event to a filter before passing it along to the appenders.
Way 5: Modify log Encoder / provider Although this would mean the logging event is not updated, but the log output will be.