我为 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
}
}
.........
好吧,我明白了。
当然,事后看来是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 的存在,但不强制这些日志记录 框架将您的用户作为依赖项。