📘 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, orrequestIdin 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
Post a Comment