HTTP Request and Response Logging Using Logbook in Spring
Zalando Logbook is a popular Java library that provides detailed HTTP request and response logging capabilities. It’s highly customizable and can be easily integrated into Spring Boot applications. Let us delve into understanding how to set up and use Zalando Logbook for HTTP logging in the Spring application for various logging needs, and ensure that your HTTP traffic is logged efficiently and securely.
1. Introduction
In modern software development, effective logging is a crucial aspect of maintaining and troubleshooting applications. Logging helps developers understand what’s happening inside an application by recording details of its execution. When it comes to web applications, especially those built using RESTful services, logging HTTP requests and responses can be invaluable. This is where Zalando Logbook comes into play.
Zalando Logbook is an open-source Java library designed to provide comprehensive and customizable HTTP request and response logging. It is particularly useful in microservices architectures, where tracking the flow of requests across multiple services is essential for monitoring, debugging, and auditing. The library is flexible, allowing developers to configure what gets logged, how it gets logged, and even mask sensitive data to protect privacy. Whether you’re building a new application or enhancing an existing one, Zalando Logbook can be a powerful addition to your logging toolkit.
1.1 Why Use Zalando Logbook?
Zalando Logbook offers several advantages:
- Detailed Logging: It logs the complete HTTP request and response, including headers, body, and status.
- Customizability: You can configure which parts of the request/response to log and even modify the log format.
- Compatibility: It integrates seamlessly with Spring Boot and other frameworks.
- Security: Sensitive data can be masked before logging.
1.2 Sink
In Zalando Logbook, a Sink is a critical component responsible for handling how HTTP request and response logs are processed and output. The Sink combines two primary functions: formatting the logs and writing them to a destination. Different types of sinks can be used depending on the desired format and output for the logs.
- DefaultSink: This is the most commonly used sink in the Zalando Logbook. It combines a log formatter and a log writer to process the HTTP logs. For example, the
DefaultSink
can use theDefaultHttpLogFormatter
to format logs as plain text, which is useful for simple logging scenarios where human readability is the priority. The formatted logs are then written using theDefaultHttpLogWriter
, which typically writes to the console or a file. - JsonHttpLogFormatter: Another type of sink involves the use of the
JsonHttpLogFormatter
. This formatter converts HTTP request and response logs into a structured JSON format, which is ideal for systems that prefer JSON for log aggregation, searching, or further processing. When paired with theDefaultHttpLogWriter
in aDefaultSink
, this setup ensures that the logs are output in a JSON format, making them easier to parse and analyze in tools like ELK stack or Splunk. - CurlHttpLogFormatter: A more specialized sink configuration might use the
CurlHttpLogFormatter
, which formats HTTP requests as cURL commands. This can be particularly useful for debugging or reproducing requests in command-line environments. Developers can copy the generated cURL command from the logs and execute it directly in a terminal to replicate the HTTP request, which can be valuable during development or troubleshooting.
In addition to the standard sinks provided by Zalando Logbook, such as DefaultSink and sinks utilizing JsonHttpLogFormatter
or CurlHttpLogFormatter
, there are also specialized sinks like CommonsLogFormatSink and ExtendedLogFormatSink. These sinks cater to specific logging requirements and formats.
- CommonsLogFormatSink: This sink formats HTTP logs in a way that is compatible with the Apache Commons Logging framework. It uses the
CommonsLogHttpLogFormatter
to generate logs in a format that integrates well with applications or systems that rely on Apache Commons Logging. This format is particularly useful if you are working with legacy systems or frameworks that expect logs in a Commons Logging format. The logs produced byCommonsLogFormatSink
are typically more aligned with the structure and style used by Commons Logging, making it easier to integrate and maintain consistency with existing logging practices. - ExtendedLogFormatSink: The
ExtendedLogFormatSink
is designed for scenarios where more detailed and customizable logging is required. This sink uses an extended log formatter that allows for a more granular and customizable log output compared to the standard log formatters. TheExtendedLogFormatSink
provides greater flexibility in how HTTP requests and responses are logged, including additional metadata and custom formatting options. This can be beneficial for applications that need to capture detailed logging information or require a specific log structure for integration with external systems or analysis tools.
Both CommonsLogFormatSink and ExtendedLogFormatSink offer specialized features that cater to different logging needs. By using these sinks, developers can ensure that their logging setup meets the specific requirements of their application environment and integrates seamlessly with other logging frameworks or systems.
2. Code Example
2.1 Dependencies
Add the following dependencies to your pom.xml
file or if you have created a spring project from start.spring.io the Spring dependencies will be automatically populated. To start using Zalando Logbook, add the other Maven dependency to your pom.xml
file
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!—Zalando Logbook dependencies --> <dependency> <groupId>org.zalando</groupId> <artifactId>logbook-spring-boot-starter</artifactId> <version>3.9.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
2.2 Configure application and database properties
Add the following properties to the application.properties
file present in the resources
folder.
spring.application.name=springlogbook server.port=9500 spring.main.banner-mode=off # Logbook logging.level.org.zalando.logbook.Logbook=TRACE
2.3 Create a Controller file
Create a controller class responsible for interacting with the user.
@RestController @RequestMapping("/logbook") public class Mycontroller { // http://localhost:9500/logbook/health @GetMapping("/health") public String health() { return "I am healthy"; } // http://localhost:9500/logbook/do-no-log @GetMapping("/do-not-log") public String doNotLog() { return "I am not logged"; } // http://localhost:9500/logbook/lorem @GetMapping("/lorem") public String getLoreumIpsum() { return List.of("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.").toString(); } }
The provided code is a simple Spring Boot controller that defines three HTTP GET endpoints under the base path /logbook
. The controller is annotated with @RestController
and @RequestMapping("/logbook")
, indicating that it is a REST controller and all endpoints within it will have the base path /logbook
.
- The first endpoint,
/health
, is mapped to thehealth
method, which returns the string “I am healthy.” This can be accessed via an HTTP GET request tohttp://localhost:9500/logbook/health
. This endpoint could be used for health checks to determine if the application is running properly. - The second endpoint,
/do-not-log
, is mapped to thedoNotLog
method, which returns the string “I am not logged.” This can be accessed via an HTTP GET request tohttp://localhost:9500/logbook/do-not-log
. The method name suggests that this endpoint might be configured in Logbook not to be logged, though the actual exclusion logic would need to be configured separately. - The third endpoint,
/lorem
, is mapped to thegetLoreumIpsum
method, which returns a string containing a Lorem Ipsum placeholder text. This can be accessed via an HTTP GET request tohttp://localhost:9500/logbook/lorem
. The placeholder text is wrapped in aList
and then converted to a string using thetoString()
method before being returned.
2.4 Basic Configuration
Once you have added the dependency, Logbook will automatically start logging HTTP requests and responses. However, you can further customize its behavior by creating a configuration class.
@Configuration public class LogbookLibConfig { @Bean public Logbook logbook() { Predicate<HttpRequest> exclude = Conditions.exclude( Conditions.requestTo("/logbook/health").or( Conditions.requestTo("/logbook/do-not-log")) ); //DefaultSink httpSink = new DefaultSink(new DefaultHttpLogFormatter(), new DefaultHttpLogWriter()); //DefaultSink curlSink = new DefaultSink(new CurlHttpLogFormatter(), new DefaultHttpLogWriter()); DefaultSink jsonSink = new DefaultSink(new JsonHttpLogFormatter(), new DefaultHttpLogWriter()); return Logbook.builder() .condition(exclude) .sink(jsonSink) .build(); } }
The provided code defines a Spring Boot configuration class named LogbookLibConfig
, which customizes the behavior of Zalando Logbook, a library used for logging HTTP requests and responses in Java applications. This class is annotated with @Configuration
, indicating that it contains one or more Spring beans that will be managed by the Spring container.
The logbook
method is annotated with @Bean
, which means it will return a configured Logbook
instance that can be used throughout the application for logging purposes. The method begins by defining a Predicate
named exclude
using Logbook’s Conditions.exclude
method. This predicate is configured to exclude logging for HTTP requests made to the paths /logbook/health
and /logbook/do-not-log
. This exclusion logic is achieved by combining two conditions using the or
method.
The code then defines different types of sinks which are responsible for formatting and writing the logs. The DefaultSink
class is used to create these sinks. The jsonSink
formats the HTTP logs as JSON using the JsonHttpLogFormatter
and writes them using the DefaultHttpLogWriter
.
Finally, the method returns a Logbook
instance configured with the exclusion condition and the jsonSink
. This Logbook
instance will log all HTTP requests and responses, except those matching the excluded paths, and will format the logs in JSON format before writing them out.
2.5 Create the Main file
The SpringlogbookApplication
class is the main entry point of a Spring Boot application.
@SpringBootApplication public class SpringlogbookApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(SpringlogbookApplication.class, args); System.out.println("Spring Boot Application Started at = " + context.getStartupDate()); } }
2.6 Run the application
Run your Spring Boot application and the application will be started on a port number specified in the application properties file. As soon as the application is started trigger the endpoints and the following logs will be shown on the IDE console.
…… 2024-08-15T14:59:28.173+05:30 INFO 25096 --- [springlogbook] [ main] j.s.SpringlogbookApplication : Started SpringlogbookApplication in 2.954 seconds (process running for 4.192) 2024-08-15T14:59:51.183+05:30 INFO 25096 --- [springlogbook] [nio-9500-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet' 2024-08-15T14:59:51.183+05:30 INFO 25096 --- [springlogbook] [nio-9500-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet' 2024-08-15T14:59:51.185+05:30 INFO 25096 --- [springlogbook] [nio-9500-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 2 ms …… 2024-08-15T14:59:51.334+05:30 TRACE 25096 --- [springlogbook] [nio-9500-exec-1] org.zalando.logbook.Logbook : {"origin":"remote","type":"request","correlation":"dcacb5b682fe6ca0","protocol":"HTTP/1.1","remote":"0:0:0:0:0:0:0:1","method":"GET","uri":"http://localhost:9500/logbook/lorem","host":"localhost","path":"/logbook/lorem","scheme":"http","port":"9500","headers":{"accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"],"accept-encoding":["gzip, deflate, br, zstd"],"accept-language":["en-US,en;q=0.9"],"cache-control":["max-age=0"],"connection":["keep-alive"],"cookie":["Pycharm-58bde449=798190aa-d5d9-4cbf-8dd2-c088f229f130; Webstorm-a1fbc3c1=78f1f608-9dbb-4f13-b188-3eee36e9258e; Idea-62fc47a=527f9477-6099-4267-9953-aa209d38ecd3"],"host":["localhost:9500"],"sec-ch-ua":["\"Not)A;Brand\";v=\"99\", \"Google Chrome\";v=\"127\", \"Chromium\";v=\"127\""],"sec-ch-ua-mobile":["?0"],"sec-ch-ua-platform":["\"Windows\""],"sec-fetch-dest":["document"],"sec-fetch-mode":["navigate"],"sec-fetch-site":["none"],"sec-fetch-user":["?1"],"upgrade-insecure-requests":["1"],"user-agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"]}} 2024-08-15T14:59:51.412+05:30 TRACE 25096 --- [springlogbook] [nio-9500-exec-1] org.zalando.logbook.Logbook : {"origin":"local","type":"response","correlation":"dcacb5b682fe6ca0","duration":191,"protocol":"HTTP/1.1","status":200,"headers":{"Connection":["keep-alive"],"Content-Length":["125"],"Content-Type":["text/html;charset=UTF-8"],"Date":["Thu, 15 Aug 2024 09:29:51 GMT"],"Keep-Alive":["timeout=60"]},"body":"[Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.]"}
3. Conclusion
Zalando Logbook is a powerful tool for HTTP logging in Java applications. It provides detailed logs that can be customized to fit the needs of your application. By following the steps outlined in this article, you can easily integrate and configure Zalando Logbook to improve your application’s observability and debugging capabilities.
4. Download the source code
You can download the full source code of this example here: HTTP Request and Response Logging Using Logbook in Spring