📘 Understanding MDC and NDC in Logging

When debugging production issues, logs are your best friends. But in multi-threaded applications or systems handling multiple requests, logs can quickly become messy and hard to trace. This is where MDC (Mapped Diagnostic Context) and NDC (Nested Diagnostic Context) come in.


🔹 What is MDC?

MDC (Mapped Diagnostic Context) allows you to store key-value pairs that are automatically added to your log entries.

👉 Example use case:

  • Storing userId, transactionId, or requestId in MDC so every log line contains this contextual information.

  • This makes tracing requests across distributed services much easier.

Code Example (SLF4J with Logback):

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

public class MDCExample {
    private static final Logger log = LoggerFactory.getLogger(MDCExample.class);

    public static void main(String[] args) {
        MDC.put("userId", "12345");
        MDC.put("transactionId", "txn-9876");

        log.info("Processing started");
        log.info("Processing in progress");

        MDC.clear(); // Always clear after use
    }
}

Sample Log Output:

2025-08-26 12:45:12 INFO  [userId=12345, transactionId=txn-9876] Processing started
2025-08-26 12:45:12 INFO  [userId=12345, transactionId=txn-9876] Processing in progress

🔹 What is NDC?

NDC (Nested Diagnostic Context) stores contextual information in a stack-like structure.

👉 Example use case:

  • If you want to track logs in a hierarchical process (e.g., request → method → sub-method), you can push and pop contexts.

Code Example:

import org.apache.log4j.Logger;
import org.apache.log4j.NDC;

public class NDCExample {
    private static final Logger log = Logger.getLogger(NDCExample.class);

    public static void main(String[] args) {
        NDC.push("User=12345");
        NDC.push("Order=9876");

        log.info("Starting order processing");
        
        NDC.pop(); // remove last
        log.info("Finished processing");

        NDC.remove(); // clear stack
    }
}

Sample Log Output:

2025-08-26 12:46:10 INFO  [User=12345 Order=9876] Starting order processing
2025-08-26 12:46:12 INFO  [User=12345] Finished processing

🔹 MDC vs NDC

Feature MDC (Mapped Diagnostic Context) NDC (Nested Diagnostic Context)
Data structure Key-Value Map Stack
Best for Adding metadata like userId, sessionId, transactionId Hierarchical trace (nested calls, sub-flows)
Usage Widely used in SLF4J & Logback Older Log4j concept
Thread-local Yes Yes

✅ Best Practices

  • Always clear MDC/NDC at the end of a request to prevent context leakage between threads.

  • Use MDC for distributed tracing (e.g., correlation IDs in microservices).

  • Use NDC only if you need nested contextual tracking (though MDC has largely replaced it in modern logging frameworks).


🔚 Conclusion

Both MDC and NDC help make logs more meaningful and traceable. In today’s distributed, microservice-driven world, MDC with correlation IDs is a must-have for debugging complex issues.


👉 Would you like me to make this blog more code-heavy with step-by-step setup (Logback/Log4j config), or keep it conceptual and beginner-friendly?

Comments

Popular posts from this blog

Handling Apple "Hide My Email" in Your Login System: Best Practices

Understanding the failedLogin() Method with Sequence Diagram