32

在 Log4j 中,NDC 和 MDC 有什么区别?我可以举一个简单的例子吗?

4

2 回答 2

36

要扩展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 可能会导致内存泄漏。

于 2013-02-28T17:43:32.240 回答
8

MDC 允许您为 log4j 添加自定义标签。例如:

%X{mytag} in log4j.xml

被引用

MDC.put("mytag","StackOverflow");

MDC 子线程自动继承其父级的映射诊断上下文的副本。

NDC 操作如pushpopcleargetDepthsetMaxDepth影响当前线程的 NDC。

于 2013-01-03T08:02:19.993 回答