在Log4j中,NDC和MDC有什么区别?我可以用一个简单的例子来使用它们吗?
答案 0 :(得分:28)
扩展Sikorski在评论中提出的link:
在NDC中,N代表嵌套,这意味着您使用堆栈控制单个值。你“推”一个字符串,然后你可以在处理指令时“推”另一个字符串;处理完成后,您可以将其弹出以查看以前的值。这种上下文日志记录在一些深度嵌套的处理中很有用。
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代表映射,这为您提供了不同类型的控件。您可以使用名称/值对,而不是使用单个堆栈来控制单个上下文字符串。这对于跟踪多个上下文位非常有用,例如将用户名和IP放入日志中。
MDC.put("userIP", req.getRemoteAddr());
MDC.put("userName", foo.getName());
log.info("success");
带有示例"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使用可能会导致内存泄漏。
答案 1 :(得分:6)
MDC允许您为log4j添加自定义标记。例如:
%X{mytag} in log4j.xml
引用
MDC.put("mytag","StackOverflow");
MDC子线程自动继承其父级的映射诊断上下文的副本。
push
,pop
,clear
,getDepth
和setMaxDepth
等NDC操作仅影响当前线程的NDC。