问题描述
在log4j中,NDC和MDC有什么区别?我可以用一个简单的示例使用它们吗?
推荐答案
在 link 中/p>
NDC
在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
MDC
M代表映射,这为您提供了不同类型的控件.您使用名称/值对,而不是使用单个堆栈来控制单个上下文字符串.这对于跟踪多个上下文位很有用,例如将用户名和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使用可能会导致内存泄漏,如果您不定期调用NDC.remove()方法.
其他推荐答案
MDC允许您添加log4j的自定义标签.例如:
%X{mytag} in log4j.xml
由
引用MDC.put("mytag","StackOverflow");
MDC儿童线程自动继承其父母的映射诊断上下文的副本.
NDC操作,例如push,pop,clear,getDepth和setMaxDepth仅影响当前线程的NDC.
问题描述
In Log4j, what is the difference between NDC and MDC? Can I have a simple example where they are used?
推荐答案
To expand on the link which Sikorski put in the comments:
NDC
In NDC, the N stands for nested, meaning you control a single value with a Stack. You "push" a string, then you can "push" another whenever processing dictates; and when processing is complete you can pop it off to see the former value. This sort of contextual logging would be useful in some deeply-nested processing.
Setting the context string
NDC.push("processingLevel2"); log.info("success");
This will get output in your log where you have the %x (lowercase) pattern:
log4j.appender.CA.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSSS} %p %C %x = %m%n
MDC
The M stands for mapped, and this gives you a different type of control. Instead of using a single stack to control a single contextual string, you use name/value pairs. This is useful for tracking multiple contextual bits, such as putting username and IP into the log.
Setting the mapped values:
MDC.put("userIP", req.getRemoteAddr()); MDC.put("userName", foo.getName()); log.info("success");
Example MDC log4j pattern
Uppercase X with the example "userIP" and "userName" strings. These must match in your code and in the log4j config:
log4j.appender.CA.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSSS} %p %X{userIP} %C %X{userName} = %m%n
I would combine these into one )context string*.
Similarities and Differences
In both cases, whenever you do the log.info("success");, the output will have the additional context you have provided. This is much cleaner than concatenating strings like log.info(req.getRemoteAddr()) + " success"); every time you log.
Note that there are serious differences between the two with respect to threading and resources. In particular, NDC will keep handles to your threads which can affect the freeing of resources if you are not diligent about popping and clearing the NDC stack.
From the link: NDC use can lead to memory leaks if you do not periodically call the NDC.remove() method.
其他推荐答案
MDC allows you to add custom tags for log4j. eg:
%X{mytag} in log4j.xml
is referenced by
MDC.put("mytag","StackOverflow");
MDC child thread automatically inherits a copy of the mapped diagnostic context of its parent.
NDC operations such as push, pop, clear, getDepth and setMaxDepth affect the NDC of the current thread only.