SLF4J put 和立即 get 失败

问题描述 投票:0回答: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,它返回为 null。

???

嘎啊。

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

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'

概念验证和“真实”都给了我一个 null 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
    }

}

.........

slf4j slf4j-api
1个回答
2
投票

好吧,我明白了。

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

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

这并不(真正)支持 MDC,而是转到 NOPMDCAdapter。 (我认为NOP-MDC-Adapter的意思是“无操作mdc适配器”)

当我为 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功能,然后SLF4J将委托 到底层框架的MDC。注意,此时只有log4j 和 logback 提供 MDC 功能。 如果底层框架 不提供MDC,例如java.util.logging,那么SLF4J将 仍然存储 MDC 数据,但其中的信息需要 通过自定义用户代码检索。

因此,作为 SLF4J 用户,您可以利用 MDC 信息 log4j 或 logback 的存在,但不强制这些日志记录 框架将您的用户作为依赖项。

© www.soinside.com 2019 - 2024. All rights reserved.