Spring Boot + SLF4J : Enhance the Application logging with SLF4J Mapped Diagnostic Context (MDC)

 

 

What is SLF4J?

I believe that SLF4J is not a new concept for most of the java developers. Here we are going to look at the MDC feature of the logging framework. If you need to brush up your knowledge on SLF4J,  here it is the time.

The Simple Logging Facade for Java (SLF4J) serves as a simple facade or abstraction for various logging frameworks, such as java.util.logginglogback and log4j.

SLF4J allows the end-user to plug in the desired logging framework at deployment time.

The problem with in-proper log entries

It’s a simple yet useful concept. Before I explain what is MDC, lets assume that we are going to develop a simple web application with one servlet MyServlet that serves requests from multiple clients. And, this servlet uses log4j framework for logging. A file appender has been defined for this servlet, so all the log messages will be logged into a text file.

With the above said configuration, all the log messages from MyServlet will go into a single log file. And when this servlet is serving more than one clients at the same time, the log statements will be mixed and there’s  no way to differentiate which log statement is belongs to which client’s processing. This’ll make it difficult to trace and debug if any processing error occurred in MyServlet life cycle.

 

How to differentiate log statements with respective to each clients?

To avoid the mix up of the log statements, we can add a client identifier (anything that can be uniquely identify the client) to the log statements. Therefore we need to make sure that client identifier is added  to the each and every log statements of the application.

Assume that the application contains thousands of log entries (even more) in hundred of source files. If we are going add this manually, this will be a tedious and repetitive work that consumes more time and resources.

Dont worry! This can be done within few seconds with  MDC (Mapped Diagnostic Context) support of the logging framework that you are using.

 

What is Mapped Diagnostic Context (MDC)?

Mapped Diagnostic Context (MDC) is used to enhance the application logging by adding some meaningful information to log entries.

Mapped Diagnostic Context” is essentially a map maintained by the logging framework where the application code provides key-value pairs which can then be inserted by the logging framework in log messages. MDC data can also be highly helpful in filtering messages or triggering certain actions.

SLF4J supports MDC, or mapped diagnostic context. If the underlying logging framework offers MDC functionality, then SLF4J will delegate to the underlying framework’s MDC.

 

Lets look at some code examples with Spring Boot. Please follow the instructions given below.

 

 

Create the Spring Boot Project.

Here i have added the web dependency.

 

Screen Shot 2018-04-17 at 5.17.22 PM.png

 

Then create a simple controller as follows.

 

Now run the spring boot application and access the /welcome endpoint.

You can use following command to run the application.

mvn spring-boot:run 

 

Then access the /welcome endpoint as follows.

Screen Shot 2018-04-17 at 10.22.39 PM.png

 

If you look at the application log, you will notice the below log entry.

Screen Shot 2018-04-17 at 10.24.38 PM.png

2018-04-17 22:24:34.171  INFO 42251 --- [nio-8080-exec-2] c.s.e.s.m.s.c.WelcomeController   : inside the welcomeMessage

 

If  the  “welcome” endpoint is accessed by multiple clients, you will see a set of similar log entries (as above log entry) in the log file. Since all the log entries are identical and no distinguishable information it is impossible to say which log entry is belonging to which client request. all of them are mixed up.

As we discuss above, the solution is to enhance the log entries by adding meaningful information with MDC.

 

 

Enhance the logging with MDC (Mapped Diagnostic Context)

MDC is a key value pair store (similar to java Map) and the stored values are used to enhance the log entries ( add meaningful information to log entries). The logging framework may generate the log entries by adding the data/information stored in the MDC.

Therefore we need to make sure that MDC (Mapped Diagnostic Context) is populated with related entries before generating the log entries.

If you look at the source code of this article, you may notice that this application is a Restful web api. All application related log entries are added inside each Restful endpoint. Therefore we need to make sure that MDC is properly initialized and populated with related data before the request reach the targeted endpoint. In order to achieve this, we can use Servlet Filters.

The Servlet Filter will be the excellent centralized place to configure the MDC data store. This will guarantee that MDC is properly populated with relevant data before any request reach its designated endpoint.

 

 

This is a just sample demonstration of how to add the values to the MDC (Mapped Diagnostic Context) store. So i have added a hard coded value as below.

MDC.put("userId", "www.SpringBootDev.com");

In real implementation, you can write your own and most appropriate implementations to get the client identifier.  MDC Store can have multiple key-value pairs.

 

After adding all the above mentioned source files, your project structure should looks like below.

Screen Shot 2018-04-17 at 11.03.35 PM.png

 

 

Did we miss something?

Yes.  Adding the key-value pairs in the MDC store is not just enough to add those values to the log entries.  we need to tell the Spring Boot about what MDC data should be added to the log entry and where it should be added. This can be achieved with declaring the logging pattern.

add the logging pattern to the application.properties as follows.

logging.pattern.level = %X{userId}%5p

 

In properties file, when defining the conversionPattern, add a pattern %X{key} to retrieve the values that are present in the MDC. The key will be userId in our example.

The more of pattern conversation characters can be found at https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html

This conversationPattern tells Spring Boot to render the MDC data variable userId just before the priority field in the log output. The priority field is the logging level (DEBUG, INFO, etc…) that you are used to see.

 

Now again run the spring boot application and access the /welcome endpoint.

Screen Shot 2018-04-17 at 10.22.39 PM.png

 

Then you can notice that MDC data (http://www.SpringBootDev.com – userId) is added before the priority field (INFO) by looking at following log entry.

Screen Shot 2018-04-17 at 11.27.39 PM.png

2018-04-17 23:27:29.162 www.SpringBootDev.com INFO 42535 --- [nio-8080-exec-3] c.s.e.s.m.s.c.WelcomeController          : inside the welcomeMessage

 

Here we have enhanced the application logging with MDC (Mapped Diagnostic Context) feature of the underlying logging framework.

 

The full source code related to this article can be found at GitHub. Click here to download it.

 

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s