Learn how to customize the logging format in Spring Boot using application.properties and add custom logging properties using Mapped Diagnostic Context (MDC).
Context
Logging is an essential aspect of software development. It helps developers to debug and troubleshoot issues in applications. Spring Boot provides a flexible and powerful logging framework that makes it easy to add logging to your applications. In this blog post, we will look at how to customize the logging format in Spring Boot using the application.properties file and add custom logging properties using Mapped Diagnostic Context (MDC).
Mapped Diagnostic Context (MDC)
Mapped Diagnostic Context (MDC) is a logging feature that allows developers to enrich log statements with additional contextual information. It works by creating a map-like structure where developers can store key-value pairs of contextual information. These pairs can be used to track additional information such as user IDs, request IDs, or other details that can help with debugging or analysis of the logs. By using MDC, developers can easily include contextual information in their logs without cluttering the log statements with unnecessary information. This can help with troubleshooting, identifying issues, and debugging problems in complex applications.
Customizing Logging Format using application.properties
By default, Spring Boot logs messages in a standard format that includes the log level, date and time, logger name, and the message. However, you can customize this format as per your needs. To modify the logging format in Spring Boot using application.properties, you need to add the following property to your application.properties file:
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} %5p %c{1}:%L - %m%n
application.propertiesIn the above example, the %d
, %5p
, %c
, %L
, %m
, and %n
are conversion patterns that represent the date and time, the log level, the class name, the line number, the message, and a new line, respectively. You can modify these conversion patterns to suit your needs.
Logging Format Parameters
Here are the most commonly used parameters in the logging format:
%d
: The date and time the message was logged.%p
: The log level of the message (e.g., DEBUG, INFO, WARN, ERROR, etc.).%t
: The name of the thread that logged the message.%c
: The name of the class that logged the message.%m
: The message that was logged.%n
: A new line character.%L
: The line number where the log statement was called.%M
: The method name where the log statement was called.%X
: The value of a custom logging property stored in MDC.
You can use these parameters to create a custom logging format that includes the information you need.
Adding Custom Logging Properties using MDC
To use MDC in your application, you can call the MDC.put() method to add contextual information to the map. For example, to add the user ID to the MDC map, you can do the following:
MDC.put("userId", "12345");
JavaYou can also remove contextual information from the map using the MDC.remove() method. For example, to remove the user ID from the MDC map, you can do the following:
MDC.remove("userId");
JavaOnce you have added contextual information to the MDC map, you can use it in the logging format by referencing the corresponding parameter. For example, to include the user ID in the logging format, you can use the %X{userId}
parameter in the logging.pattern.console
property:
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} %5p [%X{userId}] %c{1}:%L - %m%n
application.propertiesIn the above example, %X{userId}
retrieves the value of the userId
key from the MDC map and includes it in the logging format.
You can add as many custom logging properties to the MDC map as you need. However, you should be careful not to store too much information in the MDC map as it can consume a significant amount of memory.
Example
Below is an example of Spring Boot app with an interceptor that adds a request ID to the MDC map and removes it in the afterCompletion
method:
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import java.util.UUID;
@Component
public class CustomizeApplicationLoggingInterceptor implements HandlerInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(CustomizeApplicationLoggingInterceptor.class);
private static final String REQUEST_ID = "requestId";
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String requestId = UUID.randomUUID().toString().substring(0,6);
MDC.put(REQUEST_ID, requestId);
LOGGER.info("Received request with ID: {}", requestId);
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
String requestId = MDC.get(REQUEST_ID);
LOGGER.info("Request with ID {} completed", requestId);
MDC.remove(REQUEST_ID);
}
}
JavaIn the above code, we have defined a CustomizeApplicationLoggingInterceptor
class that implements the HandlerInterceptor
interface. The preHandle
method is called before the request is processed, and it generates a unique request ID using the UUID.randomUUID()
method. It then adds the request ID to the MDC map using the MDC.put()
method and logs the request ID using a logger.
The afterCompletion
method is called after the response has been sent back to the client. In this method, we retrieve the request ID from the MDC map using the MDC.get()
method, log the completion of the request, and remove the request ID from the MDC map using the MDC.remove()
method.
To use this interceptor in your Spring Boot application, you need to register it with the InterceptorRegistr
y in your WebMvcConfigurer
implementation. Here’s an example:
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new CustomizeApplicationLoggingInterceptor());
}
}
JavaIn the above code, we have defined a WebMvcConfig
class that implements the WebMvcConfigurer
interface. In the addInterceptors
method, we register the CustomizeApplicationLoggingInterceptor
with the InterceptorRegistry
. This will cause the interceptor to be called for every request that is processed by the Spring MVC dispatcher servlet.
In order to test the above changes, we have created a REST controller with one endpoint that sends a greeting to the user.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class CustomizeApplicationLoggingController {
private static final Logger LOGGER = LoggerFactory.getLogger(CustomizeApplicationLoggingController.class);
@GetMapping("/hello")
public String sendGreetings() {
LOGGER.info("Sending greeting to user");
return "Hello User!";
}
}
JavaOutput:
That’s it! With this code, you can add a request ID to the MDC map using an interceptor and remove it after the request has been completed.
Source Code
The source code for this example can be found on GitHub. Link: click here
Conclusion
In this blog post, we have learned how to customize the logging format in Spring Boot using application.properties file and add custom logging properties using Mapped Diagnostic Context (MDC). Customizing the logging format and using MDC can help you to get more meaningful and useful logs, which can make it easier to diagnose issues in your applications. By using the tips and techniques discussed in this blog post, you can customize the logging format in your Spring Boot applications to suit your needs.
Add a Comment