SLF4J放置和立即获取失败

问题描述

我为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”,并且它将为null。 您可以看到我DID验证了线程名称...了解“线程”是允许MDC工作的“魔术”。

因此,我在MDC.put之后立即执行了MDC.get,它又返回为空。

???

Gaaa。

在我的概念证明项目中,我有

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

我正在为我的版本使用变量(在root 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
    }

}

.........

解决方法

好,我知道了。

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

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

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

当我为SLF4J添加“真实的”混凝土(如登录)时,我获得了“真实的” 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'

现在我得到一个带有“获取”的MDC。

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

public class LogbackMDCAdapter implements MDCAdapter {
}

重要的文档块:

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

映射的诊断上下文(MDC)支持“映射的诊断上下文”为 本质上是由日志记录框架维护的地图,其中 应用程序代码提供了键值对,然后可以将其插入 由日志消息中的日志框架。 MDC数据也可以是高度 有助于过滤邮件或触发某些操作。

SLF4J支持MDC或映射的诊断上下文。 如果基础 日志框架提供MDC功能,然后SLF4J将委托 到基础框架的MDC。请注意,此时仅log4j 和登录功能提供MDC功能。如果是基础框架 不提供MDC,例如java.util.logging,则SLF4J将 仍存储MDC数据,但其中的信息需要 通过自定义用户代码检索。

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