问题描述
我为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,但不强制执行这些日志记录 依赖用户的框架。