6

回到旧项目并四处更新其依赖项后,我不得不意识到 logback 不再将 MDC 传播给子版本1.1.5https ://github.com/qos-ch/logback/commit/aa7d584ecdb1638bfc4c7223f4a5ff92d5ee6273

此更改使大多数日志几乎无用。

虽然我可以理解链接问题中给出的论点,但我不明白为什么不能以更向后兼容的方式进行此更改(这在 java 中通常是常见的..)。

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

4

2 回答 2

4

我认为没有直接的方法可以改变这一点。想到的两个替代方案是:

方式#1:包装所有Runnables

引入一个抽象类,它将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 内部

恢复在该提交之前使用的原始LogbackMDCAdapter实现,InheritableThreadLocal并将其以其他名称放在代码中的某个位置。然后在启动附近的某个地方使用反射来覆盖MDC.mdcAdapter属性和该自定义实现的实例。这显然是一个肮脏的黑客,但与#1相比,它节省了很多麻烦。

注意:出于性能原因,它会从现有版本继承您的复活版本,LogbackMDCAdapter并使用旧实现覆盖所有方法。有关详细信息,请参阅LoggingEvent.javaLogbackMDCAdapter.getPropertyMap内部方法。

方式#3:弄乱logback jar(甚至更奇怪的选择)

这对我来说听起来是一个非常糟糕的计划,但为了完整起见,它就是这样。

再次复活原始LogbackMDCAdapter文件,但这次不要重命名,编译它并覆盖 logback.jar 中的那个 .class 文件。

或者通过重命名来复活原始LogbackMDCAdapter文件,从 logback.jar 中删除 .class 文件org.slf4j.impl.StaticMDCBinder并添加您自己的类,该类将返回LogbackMDCAdapterlogback.jar 或您的代码的复活版本。MDC似乎按名称绑定到该类以创建MDCAdapter要使用的实现。

或者,您可以通过使用ClassLoader映射org.slf4j.impl.StaticMDCBinder到您的类而不是 logback.jar 中的类来实现类似的结果。注意:这可能是不可能在将添加自己的自定义类加载器的 Web 容器中实现的。

于 2017-04-16T21:18:07.857 回答
0

方式4:滥用TurboFilter

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

方式5:修改日志编码器/提供者 虽然这意味着日志事件不会更新,但日志输出会。

于 2021-01-18T13:50:19.550 回答