How to Log HTTP Requests & Responses with Spring Boot Actuator (Full Code Guide)
This article explains how to use Spring Boot Actuator's HTTP trace feature to record request and response metadata, shows the required dependencies and configuration, demonstrates a custom Redis repository, and provides complete code examples for testing the logging functionality.
Introduction
In a microservice architecture, logging API request and response data is essential for system monitoring, debugging, and security auditing. Spring Boot Actuator offers a built‑in filter that can easily record request/response information.
The /actuator/httptrace endpoint records the last 100 HTTP requests' metadata (method, URI, status code, duration, etc.), but it does not include request or response bodies by default.
Practical Example
1. Add Dependency
<code><dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency></code>2. Enable Recording
<code>management:
endpoints:
web:
base-path: /ac
httpexchanges:
recording:
enabled: true</code>3. Configure Repository
After enabling the feature, an HttpExchangeRepository must be provided. Spring Boot supplies InMemoryHttpExchangeRepository which stores up to 100 entries in memory.
4. Custom Repository (Redis)
<code>@Component
public class RedisHttpExchangeRepository implements HttpExchangeRepository {
private final StringRedisTemplate stringRedisTemplate;
private final ObjectMapper objectMapper;
public RedisHttpExchangeRepository(StringRedisTemplate stringRedisTemplate, ObjectMapper objectMapper) {
this.stringRedisTemplate = stringRedisTemplate;
this.objectMapper = objectMapper;
}
@Override
public List<HttpExchange> findAll() {
List<String> list = stringRedisTemplate.opsForList().range("http:request:list", 0, -1);
return list.stream().map(str -> {
try {
HttpLog log = objectMapper.readValue(str, HttpLog.class);
HttpLog.Request req = log.getRequest();
HttpExchange.Request request = new HttpExchange.Request(req.getUri(), req.getRemoteAddress(), req.getMethod(), req.getHeaders());
HttpLog.Response resp = log.getResponse();
HttpExchange.Response response = new HttpExchange.Response(resp.getStatus(), resp.getHeaders());
return new HttpExchange(log.getTimestamp().atZone(ZoneId.systemDefault()).toInstant(), request, response, log.getPrincipal(), null, log.getTimeTaken());
} catch (JsonProcessingException e) {
return null;
}
}).filter(Objects::nonNull).toList();
}
@Override
public void add(HttpExchange httpExchange) {
try {
HttpLog log = new HttpLog();
log.setPrincipal(httpExchange.getPrincipal());
log.setTimestamp(httpExchange.getTimestamp().atZone(ZoneId.systemDefault()).toLocalDateTime());
log.setTimeTaken(httpExchange.getTimeTaken());
HttpLog.Request request = new HttpLog.Request();
BeanUtils.copyProperties(httpExchange.getRequest(), request);
HttpLog.Response response = new HttpLog.Response();
BeanUtils.copyProperties(httpExchange.getResponse(), response);
log.setRequest(request);
log.setResponse(response);
stringRedisTemplate.opsForList().leftPush("http:request:list", objectMapper.writeValueAsString(log));
} catch (JsonProcessingException e) {
// handle exception
}
}
}</code>5. Test API
<code>@RestController
@RequestMapping("/api")
public class ApiController {
@GetMapping("/{id}")
public ResponseEntity<User> query(@PathVariable Long id) {
return ResponseEntity.ok(new User(id, "Name - " + id));
}
@GetMapping("")
public ResponseEntity<List<User>> list(String name) {
return ResponseEntity.ok(List.of(new User(1L, name + " - 1"), new User(2L, name + " - 2")));
}
@GetMapping("/s/{type}")
public ResponseEntity<String> s(@PathVariable String type, String name) {
return ResponseEntity.ok(String.format("type: %s, name: %s", type, name));
}
}</code>After invoking the three sample endpoints, accessing /ac/httptrace displays the recorded traces (see image).
For production environments, replace the default in‑memory repository with a persistent implementation such as the Redis repository shown above.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.