在 Log4j 中,NDC 和 MDC 有什么区别?我可以举一个简单的例子吗?
2 回答
要扩展Sikorski 在评论中添加的链接:
国家数据中心
在 NDC 中,N 代表嵌套,这意味着您可以使用 Stack 控制单个值。您“推送”一个字符串,然后您可以在处理要求时“推送”另一个字符串;处理完成后,您可以将其弹出以查看以前的值。这种上下文日志记录在一些深度嵌套的处理中很有用。
设置上下文字符串
NDC.push("processingLevel2");
log.info("success");
这将在您具有%x
(小写)模式的日志中获得输出:
log4j.appender.CA.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSSS} %p %C %x = %m%n
数据中心
M 代表mapped,这为您提供了不同类型的控制。您不使用单个堆栈来控制单个上下文字符串,而是使用名称/值对。这对于跟踪多个上下文位很有用,例如将用户名和 IP 放入日志。
设置映射值:
MDC.put("userIP", req.getRemoteAddr());
MDC.put("userName", foo.getName());
log.info("success");
示例 MDC log4j 模式
"userIP"
带有示例和"userName"
字符串的大写 X。这些必须在您的代码和 log4j 配置中匹配:
log4j.appender.CA.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSSS} %p %X{userIP} %C %X{userName} = %m%n
我会将它们组合成一个)上下文字符串*。
相同点和不同点
在这两种情况下,无论何时执行log.info("success");
,输出都会包含您提供的附加上下文。log.info(req.getRemoteAddr()) + " success");
这比每次登录时连接字符串要干净得多。
请注意,两者在线程和资源方面存在严重差异。特别是,如果您不勤于弹出和清除 NDC 堆栈,NDC 将保留您的线程的句柄,这可能会影响资源的释放。
来自链接:如果您不定期调用该NDC.remove()
方法,则使用 NDC 可能会导致内存泄漏。
MDC 允许您为 log4j 添加自定义标签。例如:
%X{mytag} in log4j.xml
被引用
MDC.put("mytag","StackOverflow");
MDC 子线程自动继承其父级的映射诊断上下文的副本。
NDC 操作如push
、pop
、clear
和getDepth
仅setMaxDepth
影响当前线程的 NDC。