Explain Codes LogoExplain Codes Logo

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

java
logging
spring-boot
exception-handling
Nikita BarsukovbyNikita BarsukovยทAug 25, 2024
โšกTLDR

Start by implementing a HandlerInterceptor that acts as your one-stop-shop for logging. Override preHandle to log every request, postHandle logs each response, and afterCompletion logs exceptions, if any. This method ensures cohesive and comprehensive logging without redundancy.

Interception in action:

@Component public class RequestResponseLoggingInterceptor implements HandlerInterceptor { // Your logger, the "gatekeeper" of your logs private static final Logger LOG = LoggerFactory.getLogger(RequestResponseLoggingInterceptor.class); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { // ๐Ÿ‘ฎโ€โ™€๏ธ Officer LOG reporting for duty, noting each request detail for future reference LOG.info("Request: {} {}", request.getMethod(), request.getRequestURI()); return true; // Carry on. Nothing to see here. } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) { // ๐Ÿ•ต๏ธโ€โ™‚๏ธ Inspector LOG on the case, noting each response detail because "the devil is in the details" LOG.info("Response: {} {}", response.getStatus(), request.getRequestURI()); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { // ๐Ÿš‘ Dr. LOG, first responder to exceptions, bringing clarity to an otherwise chaotic situation if (ex != null) LOG.error("Exception: {}", ex.getMessage()); } }

Registration is just as essential:

@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { // Imagine your logging interceptor as a superhero, this method is its "Bat Signal" registry.addInterceptor(new RequestResponseLoggingInterceptor()); } }

Just like that, route traffic through the interceptor for efficient logging.

Actuating finer logs

Spring Boot's very own Actuator has built-in HTTP request/response logging that can be finely tuned for your needs. A simple addition of the spring-boot-starter-actuator dependency lets you access a plethora of operational information via /actuator/httptrace.

Don't forget to whitelist endpoints and secure Actuator itself to avoid offering a free buffet to your adversaries.

Catch 'em all - exceptions

Use a @ControllerAdvice class along with an @ExceptionHandler method to handle and neatly log all thrown exceptions:

@ControllerAdvice public class GlobalExceptionHandler { private static final Logger LOG = LoggerFactory.getLogger(GlobalExceptionHandler.class); @ExceptionHandler(Exception.class) public ResponseEntity<String> handleException(Exception exception) { // It's a dirty job, but someone's got to log it LOG.error("Exception: ", exception); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("An error occurred"); } }

Logbook - your logging ledger

Zalando's Logbook is yet another option for precise HTTP logging. Integrate it using the logbook-spring-boot-starter for preferred parameters such as status, path, method, client IP, and authentication tokens.

Getting hands dirty with custom logging

Dive deeper and extend DispatcherServlet or use ContentCachingRequestWrapper and ContentCachingResponseWrapper to tailor your logging:

Caveat: Don't forget to set maxPayloadLength. Or else, you might unleash an avalanche of logs.

Fine-tune logging via properties

Devise desired logging level in application.properties and define log patterns for more refined logging. A DEBUG level log view via CommonsRequestLoggingFilter gives comprehensive insight.

Conscious logging in production

Beware! Logging every request in a busy production environment can choke your system and raise security concerns. Whitelist necessary endpoints, employ built-in services from platform-as-a-service (PaaS) vendors like Heroku, or tune libraries like Logbook for efficient logging.