The Mapped Diagnostic Context (MDC) is a concept, saying that from the Java code, we can pass some information to the log message beside the message that we need to log using the Logging Framework such as Log4J, Log4J2, Logback, SLF4J. Using this function will help us in some cases, such as tracking the application’s performance according to certain criteria through the message log, … How it is in detail, let’s learn together in this tutorial.
First, I will create a new Maven project:
and use SLF4J for Log4J as an example:
1 2 3 4 5 |
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>2.0.16</version> </dependency> |
For simplicity, we will configure Log4J with simple content as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <!-- Appenders --> <appender name="console" class="org.apache.log4j.ConsoleAppender"> <param name="Target" value="System.out" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%-5p: %c - %m%n" /> </layout> </appender> <!-- Root Logger --> <root> <priority value="info" /> <appender-ref ref="console" /> </root> </log4j:configuration> |
With the configuration of PatternLayout above, each log message will have the format: logging level + category + message need to log + line break.
Then, if I want to log a message:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package com.huongdanjava.slf4j; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Example { private static Logger LOGGER = LoggerFactory.getLogger(Example.class); public static void main(String[] args) { LOGGER.info("An example with Mapped Diagnostic Context"); } } |
The results are as follows:
Now, if I want to identify the log message come from which user, if I do not use the Mapped Diagnostic Context, I need to add that code to every message I need to log. Eg:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package com.huongdanjava.slf4j; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Example { private static Logger LOGGER = LoggerFactory.getLogger(Example.class); public static void main(String[] args) { String user = "Khanh"; LOGGER.info("An example with Mapped Diagnostic Context"); LOGGER.info(user + ": Messsage 1"); LOGGER.info(user + ": Messsage 2"); LOGGER.info(user + ": Messsage 3"); user = "Quan"; LOGGER.info(user + ": Messsage 1"); LOGGER.info(user + ": Messsage 2"); LOGGER.info(user + ": Messsage 3"); } } |
Result:
If now, I use the Mapped Diagnostic Context by modifying the code using the SLF4J org.slf4j.MDC object:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
package com.huongdanjava.slf4j; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; public class Example { private static Logger LOGGER = LoggerFactory.getLogger(Example.class); public static void main(String[] args) { LOGGER.info("An example with Mapped Diagnostic Context"); String user = "Khanh"; MDC.put("user", user); LOGGER.info(": Messsage 1"); LOGGER.info(": Messsage 2"); LOGGER.info(": Messsage 3"); user = "Quan"; MDC.put("user", user); LOGGER.info(": Messsage 1"); LOGGER.info(": Messsage 2"); LOGGER.info(": Messsage 3"); } } |
and declares the user keyword to PatternLayout in Log4J’s configuration file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <!-- Appenders --> <appender name="console" class="org.apache.log4j.ConsoleAppender"> <param name="Target" value="System.out" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%-5p: %c - %X{user}%m%n" /> </layout> </appender> <!-- Root Logger --> <root> <priority value="info" /> <appender-ref ref="console" /> </root> </log4j:configuration> |
The result is the same:
As you can see, using the SLF4J MDC object allows us to define a key with its value. Then, declare this key in the configuration file of Log4J with the syntax:
1 |
%X{key} |
This helps us to pass the information we need to the log message separated from the message to the log, reducing the effort a lot.