1

我为 SLF4J MDC 编写了一个小包装器。

import org.slf4j.MDC;

import java.util.UUID;


public final class MdcWrapperUtility {



    public static final String MDC_TRANSACTION_ID_KEY_NAME = "MDC_TRANSACTION_ID";

    private MdcWrapperUtility() {
    }

    public static String getId() {
        String threadName = Thread.currentThread().getName();
        String returnValue = MDC.get(MDC_TRANSACTION_ID_KEY_NAME);
        return returnValue;
    }

    public static String setId() {
        String threadName = Thread.currentThread().getName();
        String uuid = UUID.randomUUID().toString();
        String setAndReturnValue = threadName + uuid;
        MDC.put(MDC_TRANSACTION_ID_KEY_NAME, setAndReturnValue);

        String sanityCheck = MDC.get(MDC_TRANSACTION_ID_KEY_NAME);
        if (null == sanityCheck || sanityCheck.length() <= 0)
        {
            throw new NullPointerException("MDC did not persist. How is this even happening?????");
        }

        return setAndReturnValue;
    }
}

起初,在我调用“setId()”之后......我稍后会调用“getId”,它会为空。您可以看到我确实验证了线程名称......理解“线程”是允许 MDC 工作的“魔法”。

所以我在 MDC.put 之后立即做了一个 MDC.get,它返回为空。

???

嘎嘎。

在我的概念验证项目中,我有:

implementation group: 'org.slf4j', name: 'slf4j-api', version: slf4jVersion
implementation group: 'org.slf4j', name: 'slf4j-simple', version: slf4jSimpleVersion

下面的确切版本:

    slf4jSimpleVersion = '1.7.30'
    slf4jVersion = '1.7.30'

概念验证和“真实”都给了我一个空 MDC.get(又名,我得到“MDC 没有持续存在。这怎么会发生??????”异常。

我能提供的唯一其他线索是我没有巨石。我有一个多模块 gradle 项目。

https://docs.gradle.org/current/userguide/multi_project_builds.html

我正在为我的版本使用变量(在我的根 build.gradle 中定义),所以我在任何模块中都没有不匹配的版本。

附加一个:

好的,所以我知道它为什么返回“null”。它使用混凝土

public class NOPMDCAdapter implements MDCAdapter {

    public void clear() {
    }

    public String get(String key) {
        return null;
    }

    public void put(String key, String val) {
    }

    public void remove(String key) {
    }

    public Map<String, String> getCopyOfContextMap() {
        return null;
    }

    public void setContextMap(Map<String, String> contextMap) {
        // NOP
    }

}

…………

4

1 回答 1

0

好的,我想通了。

当然,事后看来是 20/20。

我应该更多地关注“'slf4j-simple'”的“简单”部分

那不(真的)支持 MDC,它转到 NOPMDCAdapter。

当我为 SLF4J 添加一个“真正的”混凝土(如 logback)时,我得到了“真正的”MDC 功能。

所以删除“简单”并添加一个“真实”(如logback)

implementation group: 'ch.qos.logback', name: 'logback-classic', version: logbackClassicVersion
implementation group: 'org.slf4j', name: 'slf4j-api', version: slf4jVersion


    logbackClassicVersion = '1.2.3'

现在我用我的“get”得到了一个 MDC。

添加“logback-classic”引用后的“具体”MDCAdapter 变为下面的,它确实有效。

public class LogbackMDCAdapter implements MDCAdapter {
}

重要的文档块:

(来自http://www.slf4j.org/manual.html

映射诊断上下文 (MDC) 支持 “映射诊断上下文”本质上是由日志框架维护的映射,其中应用程序代码提供键值对,然后可以由日志框架插入日志消息中。MDC 数据在过滤消息或触发某些操作方面也非常有用。

SLF4J 支持 MDC 或映射诊断上下文。如果底层日志框架提供 MDC 功能,那么 SL​​F4J 将委托给底层框架的 MDC。请注意,目前只有 log4j 和 logback 提供 MDC 功能。如果底层框架不提供 MDC,例如 java.util.logging,那么 SL​​F4J 仍将存储 MDC 数据,但其中的信息需要通过自定义用户代码检索。

因此,作为 SLF4J 用户,您可以在存在 log4j 或 logback 的情况下利用 MDC 信息,但不会将这些日志框架作为依赖项强加给您的用户。

于 2020-11-11T20:29:13.313 回答