如何获得MDC的“继承性"?与现代的logback? [英] How to get back MDC "inheritance" with modern logback?

查看:279
本文介绍了如何获得MDC的“继承性"?与现代的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 Runnables

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

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆