如何使用现代的logback获取MDC“继承”?

6

回到一个老项目并更新其依赖后,我不得不意识到自从版本1.1.5起,logback不再将MDC传播到子级:

https://github.com/qos-ch/logback/commit/aa7d584ecdb1638bfc4c7223f4a5ff92d5ee6273

这个改变使大部分的日志信息几乎没用了。

虽然我可以理解链接问题中给出的论点,但我不明白为什么这个改变不能以更具有向后兼容性的方式进行(通常在Java中都是这样做的..)。

:现在除了必须从Runnables到Threads的所有内容进行子类化之外,还有什么其他正确的方法来实现相同的行为?

2个回答

5
我看不到直接将其改回的方法。两个想到的替代方案是: 方式1:包装所有Runnable 引入一个抽象类,将MDC从原始Thread复制到新的Thread中,并使用它来代替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辅助方法。
缺点:需要分析和更改整个代码。
方法2:干扰slf4j内部
将使用InheritableThreadLocal的原始LogbackMDCAdapter实现恢复到提交之前,并将其放在您的代码中的其他位置。然后,在启动时使用反射覆盖MDC.mdcAdapter属性,使用该自定义实现的实例。这显然是一种肮脏的黑客行为,但与第1种方法相比,它可以节省很多麻烦。
注意:出于性能原因,最好从现有的LogbackMDCAdapter继承您恢复的版本,并仅使用旧实现覆盖所有方法。请参见LoggingEvent.javaLogbackMDCAdapter.getPropertyMap内部方法以获取一些详细信息。
方法3:干扰logback jar(更奇怪的替代方案)
对我来说,这听起来像是一个相当糟糕的计划,但为了完整性,这里有它。
再次恢复原始LogbackMDCAdapter,但这次不要重命名,编译它并覆盖logback.jar中的.class文件。
或者使用重命名的方式恢复原始的LogbackMDCAdapter,从logback.jar中删除org.slf4j.impl.StaticMDCBinder的.class文件,并添加您自己的类,该类将返回恢复的LogbackMDCAdapter版本,无论是logback.jar还是您的代码。通过名称将MDC绑定到该类以创建要使用的MDCAdapter实现。
或者,您可以使用自定义ClassLoader来实现类映射,该映射将org.slf4j.impl.StaticMDCBinder映射到您的类,而不是logback.jar中的类。注意:在Web容器内可能无法实现此目标,因为它会添加其自己的自定义ClassLoader。

好的,由于你是唯一的回答者,你将获得悬赏。 - dot_Sp0T

0

方法四:误用TurboFilter

ch.qos.logback.classic.Logger在将日志事件传递给附加器之前会先将其传递给过滤器。

方法五:修改日志编码器/提供程序 虽然这意味着日志事件不会被更新,但日志输出会被更新。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接