Backend Development 9 min read

Master HTTP Request/Response Logging in Spring Boot with Logbook

This guide explains how to integrate the Logbook library into Spring Boot applications to capture detailed HTTP request and response logs, covering dependency setup, configuration options, output formats, Logback file logging, custom sinks, and RestTemplate interception for comprehensive monitoring and debugging.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Master HTTP Request/Response Logging in Spring Boot with Logbook

1. Introduction

Recording HTTP API request and response logs is essential for monitoring, debugging, and performance optimization. It helps developers trace API usage, including request sources, parameters, response status codes, and latency, enabling quick issue identification, user behavior analysis, and system performance evaluation.

This article introduces the powerful Logbook library, which provides complete request and response logging for various client and server technologies in Spring Boot.

2. Dependency Management

<code>&lt;properties&gt;
  &lt;!-- Use version 2.16.0 for Spring Boot 2.x --&gt;
  &lt;logbook.version&gt;2.16.0&lt;/logbook.version&gt;
  &lt;!-- Use version 3.9.0 for Spring Boot 3.x --&gt;
  &lt;logbook.version&gt;3.9.0&lt;/logbook.version&gt;
&lt;/properties&gt;
&lt;dependency&gt;
  &lt;groupId&gt;org.zalando&lt;/groupId&gt;
  &lt;artifactId&gt;logbook-spring-boot-starter&lt;/artifactId&gt;
  &lt;version&gt;${logbook.version}&lt;/version&gt;
&lt;/dependency&gt;</code>

After adding the appropriate dependency, configure the logging level:

<code>logging:
  level:
    org.zalando.logbook.Logbook: TRACE</code>

2.1 Basic Usage

With the TRACE level set, no additional configuration is required. Access any endpoint and detailed request/response information will appear in the console.

<code>@GetMapping("/query")
public Object query(String name, Integer id) {
  return String.format("name = %s, id = %d", name, id);
}</code>

Console output (example):

Similarly, a POST endpoint logs request and response details:

<code>@PostMapping("/save")
public Book save(@RequestBody Book book) {
  return book;
}</code>

2.2 Output Format Configuration

Logbook supports multiple output styles such as curl, JSON, and Splunk. Switch to JSON format with:

<code>logbook:
  format:
    style: json</code>

2.3 Log Output Strategy

Control what is logged; for example, omit the request body:

<code>logbook:
  strategy: without-body</code>

2.4 Excluding URLs

Exclude specific URL patterns from logging:

<code>logbook:
  exclude:
    - /users/*
    - /products/*</code>

2.5 Integration with Logback

Redirect Logbook output to a file using Logback:

<code>&lt;appender name="RequestLogger" class="ch.qos.logback.core.rolling.RollingFileAppender"&gt;
  &lt;file&gt;logs/log_api_info.log&lt;/file&gt;
  &lt;rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"&gt;
    &lt;fileNamePattern&gt;${LOG_PATH}/log-api_info-%d{yyyy-MM-dd}.%i.log&lt;/fileNamePattern&gt;
    &lt;timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"&gt;
      &lt;maxFileSize&gt;20MB&lt;/maxFileSize&gt;
    &lt;/timeBasedFileNamingAndTriggeringPolicy&gt;
  &lt;/rollingPolicy&gt;
&lt;/appender&gt;
&lt;logger name="org.zalando.logbook" level="TRACE" additivity="false"&gt;
  &lt;appender-ref ref="RequestLogger"/&gt;
&lt;/logger&gt;</code>

2.6 Custom Core Logbook Bean

<code>@Bean
public Logbook logbook() {
  Logbook logbook = Logbook.builder()
    .condition(Conditions.exclude(Conditions.requestTo("/users/*")
      .and(Conditions.contentType("application/json"))))
    .sink(new DefaultSink(new DefaultHttpLogFormatter(), new DefaultHttpLogWriter()))
    .build();
  return logbook;
}</code>

2.7 Custom Sink Implementation

Implement the Sink interface for advanced use cases such as persisting logs to a database:

<code>@Bean
Logbook logbook() {
  Logbook logbook = Logbook.builder()
    .condition(Conditions.exclude(Conditions.requestTo("/users/*")))
    .sink(new Sink() {
      public void write(Correlation correlation, HttpRequest request, HttpResponse response) throws IOException {
        System.err.println("==============================");
        System.err.println("request header:\t" + request.getHeaders());
        System.err.println("request body:\t" + request.getBodyAsString());
        System.err.println("response header:\t" + response.getHeaders());
        System.err.println("response body:\t" + response.getBodyAsString());
        System.err.println("==============================");
      }
    })
    .build();
  return logbook;
}</code>

2.8 Integration with RestTemplate

Register Logbook's ClientHttpRequestInterceptor with a RestTemplate bean:

<code>@Bean
RestTemplate logbookRestTemplate(LogbookClientHttpRequestInterceptor interceptor) {
  RestTemplate restTemplate = new RestTemplate();
  restTemplate.setInterceptors(Arrays.asList(interceptor));
  return restTemplate;
}</code>

Use the configured RestTemplate to make remote calls; the request and response will be logged automatically:

<code>@GetMapping("/remote")
public Object remote() {
  return this.logbookRestTemplate.getForObject("http://localhost:8010/books/666", Map.class);
}</code>
Backend DevelopmentSpring BootLogbookHTTP logging
Spring Full-Stack Practical Cases
Written by

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.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.