Core Java

Java Logging with MDC

In this article, we will show you how to use MDC logging in java using detailed examples and suggestions.

1. Introduction

Most of the current real-world applications have more than one client. These clients talk to the servers simultaneously. In a typical scenario on the server we will have different threads dealing with these separate clients. One way to separate the logs of one client from another is to instantiate the logger for every client. We can clearly see that this is not a scalable solution as it will make the code ugly, will affect performance, and is a big management overhead.

Another more efficient way is to uniquely stamp each log request serving the given client.

2. MDC class

This class hides and serves as a substitute for the underlying logging system’s MDC implementation. If the underlying logging system offers MDC functionality, then SLF4J’s MDC, i.e. this class, will delegate to the underlying system’s MDC. Note that at this time, only two logging systems, namely log4j and logback, offer MDC functionality. For java.util.logging which does not support MDC, BasicMDCAdapter will be used. For other systems, i.e. slf4j-simple and slf4j-nop, NOPMDCAdapter will be used.

Thus, as a SLF4J user, you can take advantage of MDC in the presence of log4j, logback, or java.util.logging, but without forcing these systems as dependencies upon your users. The MDC class contains only static methods. It lets the developer place information in a diagnostic context that can be subsequently retrieved by certain logback components. The MDC manages contextual information on a per thread basis. Typically, while starting to service a new client request, the developer will insert pertinent contextual information, such as the client id, client’s IP address, request parameters etc. into the MDC. Logback components, if appropriately configured, will automatically include this information in each log entry.

3. Example

In this section we will see a working example of using MDC for logging. We will create a simple java maven project. Use your favorite IDE – I am using IntelliJ IDEA. Open a new Project

Figure 1. New Project

Choose project name and location

Figure 2. Project name

IntelliJ will create a sample maven project for you with a directory structure similar to below:

Figure 3. Directory structure

Now first let us add the dependencies in our pom file. We will need logback and slf4j:

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>JCG-logging-with-mdc</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>16</maven.compiler.source>
        <maven.compiler.target>16</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.2.6</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.6</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.23</version>
        </dependency>
    </dependencies>

</project>

Now add a logback.xml file in the resources folder so that it is available in the classpath:

logback.xml

<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%X{project} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="debug">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

Make note of <pattern> we are using here. We are using a placeholder {project}, this will be populated via MDC.

Now let us create a very simple main class:

LogbackMdcExample.java

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

public class LogbackMdcExample {

    private static final Logger LOG = LoggerFactory.getLogger(LogbackMdcExample.class);

    public static void main(String[] args) {
        MDC.put("project", "Java Code Geeks");
        LOG.info("Test logging");
    }
}

The first line in the main method puts a diagnostic context value (second parameter) as identified with the key (first) parameter into the current thread’s diagnostic context map. The key parameter cannot be null. The val (second) parameter can be null only if the underlying implementation supports it. This method delegates all work to the MDC of the underlying logging system – in this case logback.

You can place as many value/key associations in the MDC as you wish. Multiple insertions with the same key will overwrite older values.

Let’s run this class and see the results. You will see in the console something similar to as below:

Java Code Geeks - Test logging

The part before the hyphen is being populated via MDC.

4. Summary

Mapped Diagnostic Contexts shine brightest within client-server architectures. Typically, multiple clients will be served by multiple threads on the server. Although the methods in the MDC class are static, the diagnostic context is managed on a per thread basis, allowing each server thread to bear a distinct MDC stamp. MDC operations such as put() and get() affect only the MDC of the current thread, and the children of the current thread. The MDC in other threads remain unaffected. Given that MDC information is managed on a per thread basis, each thread will have its own copy of the MDC. Thus, there is no need for the developer to worry about thread-safety or synchronization when programming with the MDC because it handles these issues safely and transparently.

5. Download

This was an example of using MDC for logging in Java application.

Download
You can download the full source code of this example here: Java Logging with MDC

Mohammad Meraj Zia

Senior Java Developer
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button