Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between Log4j's NDC and MDC facilities?

Tags:

logging

log4j

In Log4j, what is the difference between NDC and MDC? Can I have a simple example where they are used?

like image 688
senthil Avatar asked Jan 03 '13 07:01

senthil


People also ask

What is MDC and NDC?

"MDC" stands for "Mapped Diagnostic Context". NDC has been part of the log4j framework longer than MDC. If you haven't already, you may want to review the javadoc information for each class.

What is MDC in Log4j2?

Log4j2, Logback. Java Logging, MDC. A Mapped Diagnostic Context, or MDC in short, is an instrument for distinguishing interleaved log output from different sources. Log output is typically interleaved when a server handles multiple clients near-simultaneously.

What is ThreadContext in Log4j?

The ThreadContext allows applications to store information either in a Map or a Stack. The MDC is managed on a per thread basis. To enable automatic inheritance of copies of the MDC to newly created threads, enable the "isThreadContextMapInheritable" Log4j system property.

What is ThreadContext?

A ThreadContext is a map of string headers and a transient map of keyed objects that are associated with a thread. It allows to store and retrieve header information across method calls, network calls as well as threads spawned from a thread that has a ThreadContext associated with.

What is NDC in Java logging?

Nested Diagnostic Context (NDC) is a mechanism to help distinguish interleaved log messages from different sources. NDC does this by providing the ability to add distinctive contextual information to each log entry. In this article, we will explore the use of NDC and its usage/support in various Java logging frameworks. 2. Diagnostic Contexts

What is MDC in Log4j?

MDC in Log4j Let's introduce MDC. MDC in Log4j allows us to fill a map-like structure with pieces of information that are accessible to the appender when the log message is actually written. The MDC structure is internally attached to the executing thread in the same way a ThreadLocal variable would be.

What is nested diagnostic context (NDC)?

Nested Diagnostic Context (NDC) manages a stack of contextual information, on a per thread basis. The data in NDC is available to every log request in the code and can be configured to log with every log message – even at places where the data is not in scope.

Is it possible to use MDC in SLF4J?

MDC is available in SLF4J, too, under the condition that it is supported by the underlying logging library. Both Logback and Log4j support MDC as we've just seen, so we need nothing special to use it with a standard set up.


2 Answers

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.

like image 188
Leo Lansford Avatar answered Oct 08 '22 10:10

Leo Lansford


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.

like image 44
S Kr Avatar answered Oct 08 '22 08:10

S Kr