Spring Boot - How to log all requests and responses with exceptions in single place?

Introduction:

In a Spring Boot application, you can log all requests and responses, along with exceptions, in a single place by using a combination of Spring Boot's logging framework and request/response interceptors. Here's an example of how you can achieve this:

How to do it?

1- Configure logging in your Spring Boot application. You can use a logging framework like Logback or Log4j2, which are supported by Spring Boot out of the box. You can configure logging properties in your application.properties or application.yml file, such as log file location, log levels, and log patterns. For example:

# application.properties
logging.file=/path/to/logs/my-app.log
logging.level.org.springframework=INFO
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n

2- Create a custom request/response interceptor that logs requests, responses, and exceptions. You can implement the HandlerInterceptor interface provided by Spring MVC, which allows you to intercept incoming requests and outgoing responses. You can then log the relevant information using your configured logging framework. Here's an example:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LoggingInterceptor implements HandlerInterceptor {

    private static final Logger logger = LoggerFactory.getLogger(LoggingInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // Log request details
        logger.info("Received request: {} {} from {}", request.getMethod(), request.getRequestURI(), request.getRemoteAddr());
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // Log response details
        logger.info("Sent response: {} {} with status {} and exception {}", request.getMethod(), request.getRequestURI(), response.getStatus(), ex);
    }
}

3- Register the custom interceptor in your Spring Boot application. You can do this by adding a @Bean method in one of your configuration classes or by using the WebMvcConfigurer interface to configure the interceptors. 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 MyWebMvcConfigurer implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoggingInterceptor());
    }
}

With these steps, the LoggingInterceptor will intercept all incoming requests and outgoing responses in your Spring Boot application. You can then configure your logging framework to log the intercepted information according to your desired log format and level. Additionally, you can modify the LoggingInterceptor to suit your specific logging requirements, such as logging only specific types of requests or responses, or customizing the log messages. Remember to also handle exceptions appropriately in your interceptor to avoid disrupting the normal flow of request processing.