Efficient HTTP Request Logging in Spring with Zalando: A Developer's Guide

 Logging internal HTTP requests using RestTemplate with Zalando library.

1. Overview

In some cases, it is critical that we log both internal and external HTTP requests. This is very useful for debugging communication between microservices. But this feature is already available with other Spring boot libraries. What I wanted to show in this exercise is the flexibility of logging or saving in a database of particular data.

2. Prerequisites

2.1 Dependencies

For this exercise, I will use the following dependencies:

  • Spring Boot 3
  • logbook-spring-boot-starter v3.x

2.2 The Spring Project

The project that we will work on will run on Spring Boot 3.x.

3. Hands On

3.1 Controller

We will start with our controller.

public class LoggingController {

  private final RestTemplate restTemplate;

  public void logBody() {

    log.debug("Logging internal request");

    restTemplate.getForEntity("http://localhost:8080/call-me", Computer.class);

  public Computer callMe() {
    log.debug("calling internal url");

    return Computer.builder()
        .model("Macbook Pro")

This class exposes a REST endpoint /logs/internal-requests that will trigger an HTTP request to another endpoint /call-me. This call will be intercepted by the logbook.

Let's see how it works.

3.2 Web Configuration

We need to create the following beans for the logbook to intercept the HTTP requests.

public class WebBeansConfig {

  private final Logbook logbook;

  public Logbook getLogbook() {
    return Logbook.builder()
        .strategy(new StatusAtLeastStrategy(200))
        .sink(new LogSink(new LogFormatter(), new LogWriter()))

  public RestTemplate restTemplate() {

    RestTemplate restTemplate = new RestTemplate();

    return restTemplate;

  private LogbookClientHttpRequestInterceptor getLogbookInterceptor() {
    return new LogbookClientHttpRequestInterceptor(logbook);

3.3 Logbook and Logging Classes

Here are the skeletons of the classes needed by the logbook.

After the logbook intercepts the request, it will cause this class to perform pre and post request data manipulation.

public class LogSink implements Sink {

  private final LogFormatter formatter;
  private final LogWriter writer;

  public void write(Precorrelation preCorrelation, HttpRequest request) throws IOException {


  public void write(Correlation correlation, HttpRequest request, HttpResponse response) throws IOException {


  public void writeBoth(Correlation correlation, HttpRequest request, HttpResponse response) throws IOException {
    writer.write(formatter.format(correlation.getId(), request, response));

This class extracts the necessary values from the HTTP request and response object. We can also deduce whether the request is incoming or outgoing.

// Customizeable message model
public class LogFormatter {

  public Message format(String correlationId, HttpRequest request, HttpResponse response) throws IOException {

    return Message.builder()


Finally, this class logs the message object in the console. We can also save the Message object in the database by injecting a mapper and converting the Message to an entity, then inject a repository that we can use to insert the entity in the database.

// Log writer
public class LogWriter {

  // you can autowire a service here
  public void write(Message message) {
    log.debug("Http intercepted message={}", message);

4. GitHub Repository


spring-rest 205117495696468907

Post a Comment Default Comments