Skip to content

Commit 4a7ec0a

Browse files
BAEL-8954 - How to log all requests and responses with an exception in a single place
1 parent b34d507 commit 4a7ec0a

File tree

9 files changed

+201
-0
lines changed

9 files changed

+201
-0
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
<parent>
6+
<groupId>org.springframework.boot</groupId>
7+
<artifactId>spring-boot-starter-parent</artifactId>
8+
<version>3.4.1</version>
9+
<relativePath/>
10+
</parent>
11+
<groupId>com.baeldung</groupId>
12+
<artifactId>log-all-requests</artifactId>
13+
<version>0.0.1-SNAPSHOT</version>
14+
<name>log-all-requests</name>
15+
<description>log-all-requests</description>
16+
17+
<properties>
18+
<java.version>17</java.version>
19+
</properties>
20+
<dependencies>
21+
<dependency>
22+
<groupId>org.springframework.boot</groupId>
23+
<artifactId>spring-boot-starter-actuator</artifactId>
24+
</dependency>
25+
<dependency>
26+
<groupId>org.springframework.boot</groupId>
27+
<artifactId>spring-boot-starter-web</artifactId>
28+
</dependency>
29+
30+
<dependency>
31+
<groupId>org.springframework.boot</groupId>
32+
<artifactId>spring-boot-starter-test</artifactId>
33+
<scope>test</scope>
34+
</dependency>
35+
</dependencies>
36+
37+
<build>
38+
<plugins>
39+
<plugin>
40+
<groupId>org.springframework.boot</groupId>
41+
<artifactId>spring-boot-maven-plugin</artifactId>
42+
</plugin>
43+
</plugins>
44+
</build>
45+
46+
</project>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.baeldung.logallrequests;
2+
3+
import org.slf4j.Logger;
4+
import org.slf4j.LoggerFactory;
5+
import org.springframework.http.HttpStatus;
6+
import org.springframework.http.ResponseEntity;
7+
import org.springframework.web.bind.annotation.ControllerAdvice;
8+
import org.springframework.web.bind.annotation.ExceptionHandler;
9+
10+
@ControllerAdvice
11+
public class GlobalExceptionHandler {
12+
13+
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
14+
15+
@ExceptionHandler(Exception.class)
16+
public ResponseEntity<String> handleException(Exception ex) {
17+
logger.error("Exception caught: {}", ex.getMessage(), ex);
18+
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("An error occurred");
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.baeldung.logallrequests;
2+
3+
import org.springframework.boot.actuate.web.exchanges.InMemoryHttpExchangeRepository;
4+
import org.springframework.context.annotation.Bean;
5+
import org.springframework.context.annotation.Configuration;
6+
7+
@Configuration
8+
public class HttpTraceActuatorConfiguration {
9+
10+
@Bean
11+
public InMemoryHttpExchangeRepository createTraceRepository() {
12+
return new InMemoryHttpExchangeRepository();
13+
}
14+
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.baeldung.logallrequests;
2+
3+
import org.springframework.boot.SpringApplication;
4+
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
6+
@SpringBootApplication
7+
public class LogAllRequestsApplication {
8+
9+
public static void main(String[] args) {
10+
SpringApplication.run(LogAllRequestsApplication.class, args);
11+
}
12+
13+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package com.baeldung.logallrequests;
2+
3+
import jakarta.servlet.Filter;
4+
import jakarta.servlet.FilterChain;
5+
import jakarta.servlet.ServletException;
6+
import jakarta.servlet.http.HttpServletRequest;
7+
import jakarta.servlet.http.HttpServletResponse;
8+
import org.slf4j.Logger;
9+
import org.slf4j.LoggerFactory;
10+
import org.springframework.stereotype.Component;
11+
12+
import java.io.IOException;
13+
14+
@Component
15+
public class LoggingFilter implements Filter {
16+
17+
private static final Logger logger = LoggerFactory.getLogger(LoggingFilter.class);
18+
19+
@Override
20+
public void doFilter(jakarta.servlet.ServletRequest request, jakarta.servlet.ServletResponse response, FilterChain chain)
21+
throws IOException, ServletException {
22+
23+
if (request instanceof HttpServletRequest && response instanceof HttpServletResponse) {
24+
HttpServletRequest httpRequest = (HttpServletRequest) request;
25+
HttpServletResponse httpResponse = (HttpServletResponse) response;
26+
27+
logRequest(httpRequest);
28+
29+
ResponseWrapper responseWrapper = new ResponseWrapper(httpResponse);
30+
31+
chain.doFilter(request, responseWrapper);
32+
33+
logResponse(httpRequest, responseWrapper);
34+
} else {
35+
chain.doFilter(request, response);
36+
}
37+
}
38+
39+
private void logRequest(HttpServletRequest request) {
40+
logger.info("Incoming Request: [{}] {}", request.getMethod(), request.getRequestURI());
41+
request.getHeaderNames().asIterator().forEachRemaining(header ->
42+
logger.info("Header: {} = {}", header, request.getHeader(header))
43+
);
44+
}
45+
46+
private void logResponse(HttpServletRequest request, ResponseWrapper responseWrapper) throws IOException {
47+
logger.info("Outgoing Response for [{}] {}: Status = {}",
48+
request.getMethod(), request.getRequestURI(), responseWrapper.getStatus());
49+
logger.info("Response Body: {}", responseWrapper.getBodyAsString());
50+
}
51+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.baeldung.logallrequests;
2+
3+
import java.io.CharArrayWriter;
4+
import java.io.PrintWriter;
5+
6+
import jakarta.servlet.http.HttpServletResponse;
7+
import jakarta.servlet.http.HttpServletResponseWrapper;
8+
9+
public class ResponseWrapper extends HttpServletResponseWrapper {
10+
11+
private final CharArrayWriter charArrayWriter = new CharArrayWriter();
12+
private final PrintWriter writer = new PrintWriter(charArrayWriter);
13+
14+
public ResponseWrapper(HttpServletResponse response) {
15+
super(response);
16+
}
17+
18+
@Override
19+
public PrintWriter getWriter() {
20+
return writer;
21+
}
22+
23+
public String getBodyAsString() {
24+
return charArrayWriter.toString();
25+
}
26+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.baeldung.logallrequests;
2+
3+
import org.springframework.web.bind.annotation.GetMapping;
4+
import org.springframework.web.bind.annotation.RequestMapping;
5+
import org.springframework.web.bind.annotation.RestController;
6+
7+
@RestController
8+
@RequestMapping("/api")
9+
public class TestController {
10+
11+
@GetMapping("/hello")
12+
public String hello() {
13+
return "Hello, World!";
14+
}
15+
16+
@GetMapping("/error")
17+
public String error() {
18+
throw new RuntimeException("This is a test exception");
19+
}
20+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
spring:
2+
application:
3+
name: log-all-requests
4+
5+
management:
6+
endpoints:
7+
web:
8+
exposure:
9+
include: httpexchanges

logging-modules/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
<module>logging-techniques</module>
2424
<module>solarwinds-loggly</module>
2525
<module>splunk-with-log4j2</module>
26+
<module>log-all-requests</module>
2627
</modules>
2728

2829
</project>

0 commit comments

Comments
 (0)