如何获得MDC的“继承性"?与现代的logback? [英] How to get back MDC "inheritance" with modern logback?
问题描述
回到较旧的项目并更新其依赖项后,我不得不意识到自版本1.1.5
起,logback不再将MDC传播给子对象:
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 1.1.5
: https://github.com/qos-ch/logback/commit/aa7d584ecdb1638bfc4c7223f4a5ff92d5ee6273
此更改使大多数日志几乎无用.
This change makes most of the logs nigh useless.
虽然我可以理解链接问题中给出的参数,但我不明白为什么不能以更向后兼容的方式进行此更改(在Java中通常如此.)
While I can understand the arguments given in the linked issues, I can not understand why this change could not have been made in a more backwards compatible manner (as is generally usual in java..).
Q :除了必须从Runnables到Threads子类化所有子类之外,现在实现相同行为的正确方法是什么?
Q: What is the now correct way to achieve the same behaviour other than having to subclass everything from Runnables to Threads?
推荐答案
我看不出将其改回原样的简单方法.我想到了两种选择:
I see no straightforward way to change this back. Two alternatives that come to mind are:
方法1:包装所有Runnable
s
Way #1: Wrap all Runnable
s
引入一个抽象类,它将抽象MDC
从原始Thread
复制到新的Thread
并使用它代替Runnable
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();
}
};
}
}
如果某些Runnable
来自外部API,并且您无法更改该代码,请使用wrap
帮助器方法.
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.
方法2:使用slf4j内部结构混乱
从该提交之前恢复使用InheritableThreadLocal
的原始LogbackMDCAdapter
实现,并以其他名称将其放置在代码中的某个位置.然后在启动周围使用反射来覆盖 MDC.mdcAdapter 属性与该自定义实现的实例.这显然是一个肮脏的hack,但是与#1相比,它节省了很多麻烦.
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.
注意:出于性能方面的考虑,它使您可以从现有的LogbackMDCAdapter
继承复活的版本,并仅使用旧的实现覆盖所有方法.参见 LoggingEvent.java 和
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.
方法3:使用logback jar混乱(甚至更陌生的选择)
Way #3: Mess with logback jar (even stranger alternative)
在我看来,这是一个非常糟糕的计划,但出于完整性考虑,这是一个不错的选择.
This sounds to me as a quite bad plan but for completness here it is.
再次恢复原始的LogbackMDCAdapter
,但是这次不重命名,编译它并覆盖logback.jar中的.class文件.
Again resurrect the original LogbackMDCAdapter
but this time don't rename, compile it and override that .class file inside logback.jar.
或通过重命名恢复原始的LogbackMDCAdapter
,从logback.jar中删除org.slf4j.impl.StaticMDCBinder
的.class文件,然后添加您自己的类,该类将使LogbackMDCAdapter
的恢复版本返回到logback.jar或您的代码中. MDC
似乎已按名称绑定到该类,以创建要使用的MDCAdapter
的实现.
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.
或者您可以通过使用自定义ClassLoader
来实现类似的结果,该自定义ClassLoader
会将org.slf4j.impl.StaticMDCBinder
映射到您的类,而不是logback.jar中的一个.注意:在Web容器中添加自己的自定义ClassLoader可能无法实现.
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.
这篇关于如何获得MDC的“继承性"?与现代的logback?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!