### Precorrelation getStart() Method Example Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Correlation.md Shows how to get the timestamp indicating when the HTTP request began. ```java Instant requestStart = precorr.getStart(); ``` -------------------------------- ### Robust Logbook Initialization with Error Handling Source: https://github.com/zalando/logbook/blob/main/_autodocs/errors.md Configure Logbook with robust error handling during initialization. This example includes a safe condition predicate and catches general exceptions during builder setup, falling back to a default Logbook instance if creation fails. ```java @Configuration public class RobustLogbookConfiguration { private static final Logger logger = LoggerFactory.getLogger( RobustLogbookConfiguration.class); @Bean public Logbook logbook() { try { return Logbook.builder() .condition(request -> { try { return !request.getPath().startsWith("/health"); } catch (Exception e) { logger.warn("Condition evaluation failed", e); return true; } }) .bodyFilter(BodyFilters.oauthRequest()) .build(); } catch (Exception e) { logger.error("Failed to create Logbook, using default", e); return Logbook.create(); } } } ``` -------------------------------- ### Accessing the Logbook Builder Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/LogbookBuilder.md Get an instance of the Logbook builder to start configuring logging. ```java LogbookCreator.Builder builder = Logbook.builder(); Logbook logbook = builder.build(); ``` -------------------------------- ### Logbook Configuration Example Source: https://github.com/zalando/logbook/blob/main/README.md Example of Logbook configuration using YAML, specifying predicates for including/excluding requests, obfuscation rules, and formatting strategies. ```yaml logbook: predicate: include: - path: /api/** methods: - GET - POST - path: /actuator/** exclude: - path: /actuator/health - path: /api/admin/** methods: - POST filter.enabled: true secure-filter.enabled: true format.style: http strategy: body-only-if-status-at-least minimum-status: 400 obfuscate: headers: - Authorization - X-Secret parameters: - access_token - password write: chunk-size: 1000 attribute-extractors: - type: JwtFirstMatchingClaimExtractor claim-names: [ "sub", "subject" ] claim-key: Principal - type: JwtAllMatchingClaimsExtractor claim-names: [ "sub", "iat" ] ``` -------------------------------- ### cURL Request Example Source: https://github.com/zalando/logbook/blob/main/README.md An example of an HTTP request formatted as an executable cURL command. ```bash curl -v -X GET 'http://localhost/test' -H 'Accept: application/json' ``` -------------------------------- ### Filter Hierarchy Example Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/CoreConcepts.md Illustrates the sequential application of filters in Logbook, starting from header filtering and progressing through body, query, path, and finally request/response filters. ```text Original request/response ↓ HeaderFilter (remove/mask headers) ↓ BodyFilter (transform body) ↓ QueryFilter (mask query parameters) ↓ PathFilter (mask path segments) ↓ RequestFilter/ResponseFilter (transform entire object) ↓ Filtered request/response ``` -------------------------------- ### Ktor Server with LogbookServer Source: https://github.com/zalando/logbook/blob/main/README.md Install LogbookServer for logging HTTP server requests in Ktor. ```kotlin private val server = embeddedServer(CIO) { install(LogbookServer) { logbook = logbook } } ``` -------------------------------- ### HTTP Logbook Request Example Source: https://github.com/zalando/logbook/blob/main/README.md Example of an incoming HTTP request formatted for local development and debugging. ```http Incoming Request: 2d66e4bc-9a0d-11e5-a84c-1f39510f0d6b GET http://example.org/test HTTP/1.1 Accept: application/json Host: localhost Content-Type: text/plain Hello world! ``` -------------------------------- ### Ktor Logbook Feature Installation Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/OtherIntegrations.md Installs the Logbook feature in a Ktor application. This is the simplest way to enable logging for Ktor. ```kotlin install(LogbookFeature) { logbook = Logbook.create() } ``` -------------------------------- ### Ktor Client with LogbookClient Source: https://github.com/zalando/logbook/blob/main/README.md Install LogbookClient for logging HTTP client requests in Ktor. ```kotlin private val client = HttpClient(CIO) { install(LogbookClient) { logbook = logbook } } ``` -------------------------------- ### Logbook Setup with FastJson and Logstash Writer Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Formatters.md Demonstrates configuring Logbook for structured logging with FastJsonHttpLogFormatter and LogstashLogbookWriter. ```java import org.zalando.logbook.Logbook; import org.zalando.logbook.HttpLogFormatter; import org.zalando.logbook.HttpLogWriter; import org.zalando.logbook.json.FastJsonHttpLogFormatter; import org.zalando.logbook.core.DefaultSink; import org.zalando.logbook.LogstashLogbookWriter; HttpLogFormatter formatter = new FastJsonHttpLogFormatter(); HttpLogWriter writer = new LogstashLogbookWriter(); Logbook logbook = Logbook.builder() .sink(new DefaultSink(formatter, writer)) .build(); ``` -------------------------------- ### JSON Logbook Request Example Source: https://github.com/zalando/logbook/blob/main/README.md Example of a JSON formatted incoming request, suitable for production use and machine readability. ```json { "origin": "remote", "type": "request", "correlation": "2d66e4bc-9a0d-11e5-a84c-1f39510f0d6b", "protocol": "HTTP/1.1", "sender": "127.0.0.1", "method": "GET", "uri": "http://example.org/test", "host": "example.org", "path": "/test", "scheme": "http", "port": null, "headers": { "Accept": ["application/json"], "Content-Type": ["text/plain"] }, "body": "Hello world!" } ``` -------------------------------- ### Curl Command Output Example Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Formatters.md An example of the output generated by CurlHttpLogFormatter, showing a curl command. ```shell curl -X GET \ -H 'Accept: application/json' \ -H 'Host: api.example.com' \ 'https://api.example.com/api/users?page=1' ``` -------------------------------- ### HTTP Logbook Response Example Source: https://github.com/zalando/logbook/blob/main/README.md Example of an outgoing HTTP response formatted for local development and debugging. ```http Outgoing Response: 2d66e4bc-9a0d-11e5-a84c-1f39510f0d6b Duration: 25 ms HTTP/1.1 200 Content-Type: application/json {"value":"Hello world!"} ``` -------------------------------- ### Create Logbook Instance with Defaults Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Logbook.md Creates a Logbook instance with default configuration. Use this for a quick setup with sensible defaults. ```java Logbook logbook = Logbook.create(); ``` -------------------------------- ### Sink and Formatting Example Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/CoreConcepts.md Shows the flow from request/response objects through the HttpLogFormatter to the Sink, and finally to the HttpLogWriter for persistent storage. ```text Request/Response objects ↓ HttpLogFormatter (formats to string) ↓ Sink (receives string) ↓ HttpLogWriter (writes to file/network/etc) ``` -------------------------------- ### Basic Logbook Setup with Default Formatter and Writer Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Formatters.md Demonstrates how to create a Logbook instance using the default HttpLogFormatter and HttpLogWriter, combined into a composite sink. ```java import org.zalando.logbook.Logbook; import org.zalando.logbook.HttpLogFormatter; import org.zalando.logbook.HttpLogWriter; import org.zalando.logbook.Sink; import org.zalando.logbook.DefaultHttpLogFormatter; import org.zalando.logbook.DefaultHttpLogWriter; import org.zalando.logbook.core.DefaultSink; HttpLogFormatter formatter = new DefaultHttpLogFormatter(); HttpLogWriter writer = new DefaultHttpLogWriter(); // Create composite sink using formatter and writer Sink sink = new DefaultSink(formatter, writer); Logbook logbook = Logbook.builder() .sink(sink) .build(); ``` -------------------------------- ### Logbook Orchestration Example Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/CoreConcepts.md Demonstrates the chaining of methods in the Logbook entry point to orchestrate the request-response lifecycle, from initial processing to final writing. ```text logbook.process(request) → RequestWritingStage .write() → ResponseProcessingStage .process(response) → ResponseWritingStage .write() → void (complete) ``` -------------------------------- ### Custom HttpLogFormatter for Request Logging Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Correlation.md Provides an example of a custom `HttpLogFormatter` to format log output for incoming requests, including correlation ID, start time, method, and path. ```java HttpLogFormatter formatter = new HttpLogFormatter() { @Override public String format(Precorrelation precorrelation, HttpRequest request) throws IOException { StringBuilder sb = new StringBuilder(); sb.append("Request: ").append(precorrelation.getId()).append("\n"); sb.append("Started: ").append(precorrelation.getStart()).append("\n"); sb.append(request.getMethod()).append(" ").append(request.getPath()); return sb.toString(); } @Override public String format(Correlation correlation, HttpResponse response) throws IOException { StringBuilder sb = new StringBuilder(); sb.append("Response: ").append(correlation.getId()).append("\n"); sb.append("Duration: ").append(correlation.getDuration()).append("\n"); sb.append("Status: ").append(response.getStatus()); return sb.toString(); } }; ``` -------------------------------- ### Filter Composition Example Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/CoreConcepts.md Demonstrates how multiple filters can be composed sequentially. Filters are applied from left to right. ```plaintext Filter1 + Filter2 + Filter3 = ComposedFilter Composed filters are applied left-to-right: Input → Filter1 → Filter2 → Filter3 → Output ``` -------------------------------- ### Correlation getDuration() Method Example Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Correlation.md Shows how to obtain the total elapsed time between the request start and response end, represented as a `Duration` object. ```java Correlation corr = /* ... */; Duration elapsed = corr.getDuration(); long millis = elapsed.toMillis(); // e.g., 245 ``` -------------------------------- ### Logbook configuration with header filtering Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/HttpHeaders.md Example demonstrating how to configure Logbook with a custom HeaderFilter to sanitize sensitive headers before logging. ```java HeaderFilter securityFilter = headers -> headers .delete("Authorization", "X-API-Key", "Cookie") .apply( (name, values) -> name.equalsIgnoreCase("Set-Cookie"), (name, values) -> List.of("***")); Logbook logbook = Logbook.builder() .headerFilter(securityFilter) .build(); ``` -------------------------------- ### Splunk Request Log Example Source: https://github.com/zalando/logbook/blob/main/README.md An HTTP request formatted for Splunk as key-value pairs. ```text origin=remote type=request correlation=2d66e4bc-9a0d-11e5-a84c-1f39510f0d6b protocol=HTTP/1.1 sender=127.0.0.1 method=POST uri=http://example.org/test host=example.org scheme=http port=null path=/test headers={Accept=[application/json], Content-Type=[text/plain]} body=Hello world! ``` -------------------------------- ### Splunk Response Log Example Source: https://github.com/zalando/logbook/blob/main/README.md An HTTP response formatted for Splunk as key-value pairs. ```text origin=local type=response correlation=2d66e4bc-9a0d-11e5-a84c-1f39510f0d6b duration=25 protocol=HTTP/1.1 status=200 headers={Content-Type=[text/plain]} body=Hello world! ``` -------------------------------- ### Logbook Filter Composition Example Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Filters.md Demonstrates how to configure a Logbook instance with various pre-built and custom filters for body, headers, path, query, request, and response. ```java import org.zalando.logbook.Logbook; import org.zalando.logbook.BodyFilters; Logbook logbook = Logbook.builder() // Body filters .bodyFilter(BodyFilters.oauthRequest()) .bodyFilter(BodyFilters.truncate(1000)) // Header filters .headerFilter(headers -> headers.delete("Authorization")) // Path filters .pathFilter(path -> path.replaceAll("/\\d+/", "/{id}/")) // Query filters .queryFilter(query -> query.replaceAll("key=[^&]*", "key=***")) // Request filters .requestFilter(request -> request.withoutBody()) // Response filters .responseFilter(response -> response.withoutBody()) .build(); ``` -------------------------------- ### FastJsonHttpLogFormatter JSON Output Example Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Formatters.md An example of the structured JSON output produced by FastJsonHttpLogFormatter, suitable for log aggregation systems. ```json { "origin": "REMOTE", "type": "request", "correlation": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "protocol": "HTTP/1.1", "remote": "192.168.1.100", "method": "GET", "uri": "https://api.example.com/api/users?page=1", "headers": { "Accept": ["application/json"], "Host": ["api.example.com"] } } ``` -------------------------------- ### Logbook Usage Example Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/HttpRequest.md Demonstrates how to configure Logbook with a custom strategy to conditionally buffer the request body based on the HTTP method. ```java Strategy strategy = (request) -> { // Access request details String method = request.getMethod(); String path = request.getPath(); String query = request.getQuery(); String host = request.getHost(); // Conditionally buffer body if ("POST".equals(method) || "PUT".equals(method)) { return request.withBody(); } else { return request.withoutBody(); } }; Logbook logbook = Logbook.builder() .build(); ``` -------------------------------- ### Logbook Core Dependency Installation Source: https://github.com/zalando/logbook/blob/main/README.md Add this dependency to your project to include the core functionality of Logbook. ```xml org.zalando logbook-core ${logbook.version} ``` -------------------------------- ### Common Log Format Example Source: https://github.com/zalando/logbook/blob/main/README.md A log entry formatted using the Common Log Format (CLF). ```text 185.85.220.253 - - [02/Aug/2019:08:16:41 0000] "GET /search?q=zalando HTTP/1.1" 200 - ``` -------------------------------- ### Java Example: Sanitizing Headers by Deleting and Modifying Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Filters.md An example HeaderFilter that deletes specific headers like 'Authorization' and 'X-API-Key', and modifies 'Cookie' headers to mask values. This is useful for security and privacy. ```java HeaderFilter sanitizeHeaders = headers -> headers .delete("Authorization", "X-API-Key") .apply( (name, values) -> name.equalsIgnoreCase("Cookie"), (name, values) -> List.of("***")); ``` -------------------------------- ### Precorrelation correlate() Method Example Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Correlation.md Illustrates upgrading a `Precorrelation` object to a full `Correlation` object once the HTTP response has been received. ```java Precorrelation precorr = /* ... */; // Later, when response is available Correlation full = precorr.correlate(); ``` -------------------------------- ### Correlation getEnd() Method Example Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Correlation.md Demonstrates how to retrieve the timestamp when the HTTP response was received. ```java Correlation corr = /* ... */; Instant responseEnd = corr.getEnd(); ``` -------------------------------- ### Example Usage of RestTemplate with Logbook Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/SpringIntegration.md Demonstrates how a service can use an auto-configured RestTemplate to make HTTP requests, which are then automatically logged by the Logbook interceptor. ```java @Service public class UserService { @Autowired private RestTemplate restTemplate; public User fetchUser(String userId) { // HTTP requests are automatically logged ResponseEntity response = restTemplate.getForEntity( "https://api.example.com/users/{id}", User.class, userId); return response.getBody(); } } ``` -------------------------------- ### Filter Composition Example Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Filters.md Demonstrates how to compose various filters, including body, header, path, query, request, and response filters, when building a Logbook instance. ```APIDOC ## Filter Composition in Logbook ```java Logbook logbook = Logbook.builder() // Body filters .bodyFilter(BodyFilters.oauthRequest()) .bodyFilter(BodyFilters.truncate(1000)) // Header filters .headerFilter(headers -> headers.delete("Authorization")) // Path filters .pathFilter(path -> path.replaceAll("/\\d+/", "/{id}/")) // Query filters .queryFilter(query -> query.replaceAll("key=[^&]*", "key=***")) // Request filters .requestFilter(request -> request.withoutBody()) // Response filters .responseFilter(response -> response.withoutBody()) .build(); ``` ``` -------------------------------- ### Extended Log Format Example Source: https://github.com/zalando/logbook/blob/main/README.md A log entry formatted using the Extended Log Format (ELF) with default fields. ```text 2019-08-02 08:16:41 185.85.220.253 localhost POST /search ?q=zalando 200 21 20 0.125 HTTP/1.1 "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0" "name=value" "https://example.com/page?q=123" ``` -------------------------------- ### Origin Enum Usage Example Source: https://github.com/zalando/logbook/blob/main/_autodocs/types.md Demonstrates how to check the origin of an HTTP message using the Origin enum. ```java Origin origin = message.getOrigin(); if (origin == Origin.LOCAL) { // This is a request we sent or response we received } else { // This is a request from a client or response to a client } ``` -------------------------------- ### JDK HTTP Server Integration Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/OtherIntegrations.md Integrates Logbook with Java's built-in `com.sun.net.httpserver.HttpServer`. This example shows how to create a server and add the LogbookHttpHandler. ```java HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0); server.createContext("/api", new LogbookHttpHandler( logbook, actualHandler)); server.start(); ``` -------------------------------- ### Example Log Output for Outgoing Requests Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/SpringIntegration.md Illustrates the typical log format for outgoing HTTP client requests and their corresponding incoming responses as captured by Logbook. ```text Outgoing Request: f47ac10b-58cc-4372-a567-0e02b2c3d479 Remote: api.example.com GET /api/users/123 HTTP/1.1 Host: api.example.com Accept: application/json User-Agent: Spring-Framework/6.1 --- Incoming Response: f47ac10b-58cc-4372-a567-0e02b2c3d479 Duration: 245 ms HTTP/1.1 200 OK Content-Type: application/json Content-Length: 456 Cache-Control: no-cache ``` -------------------------------- ### Configuring Request and Response Filters Source: https://github.com/zalando/logbook/blob/main/README.md Set up Logbook to filter sensitive parts of HTTP requests and responses. This example replaces binary/stream bodies and specific query/header values. ```java import static org.zalando.logbook.core.HeaderFilters.authorization; import static org.zalando.logbook.core.HeaderFilters.eachHeader; import static org.zalando.logbook.core.QueryFilters.accessToken; import static org.zalando.logbook.core.QueryFilters.replaceQuery; Logbook logbook = Logbook.builder() .requestFilter(RequestFilters.replaceBody(message -> contentType("audio/*").test(message) ? "mmh mmh mmh mmh" : null)) .responseFilter(ResponseFilters.replaceBody(message -> contentType("*/*-stream").test(message) ? "It just keeps going and going..." : null)) .queryFilter(accessToken()) .queryFilter(replaceQuery("password", "")) .headerFilter(authorization()) .headerFilter(eachHeader("X-Secret"::equalsIgnoreCase, "")) .build(); ``` -------------------------------- ### Registering Default LogbookFilter with Spring Boot Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/ServletIntegration.md Example of how to register the default LogbookFilter using Spring Boot's FilterRegistrationBean. ```java @WebListener public class LogbookConfiguration { @Bean public FilterRegistrationBean logbookFilter() { return new FilterRegistrationBean<>(new LogbookFilter()); } } ``` -------------------------------- ### Attribute Extractor Example Source: https://github.com/zalando/logbook/blob/main/README.md Implement AttributeExtractor to extract custom attributes from requests. Logbook must be configured with this extractor. ```java final class OriginExtractor implements AttributeExtractor { @Override public HttpAttributes extract(final HttpRequest request) { return HttpAttributes.of("origin", request.getOrigin()); } } ``` -------------------------------- ### Charset Detection Examples Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/CoreConcepts.md Demonstrates how Logbook automatically detects character encoding from the Content-Type header. It shows default encodings for common types and specific encodings when provided. ```plaintext application/json; charset=utf-8 → UTF-8 application/json → UTF-8 (JSON default) text/html; charset=iso-8859-1 → ISO-8859-1 application/octet-stream → UTF-8 (default) ``` -------------------------------- ### Java FileSink Implementation Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Sink.md An example implementation of the Sink interface for writing logs to a file. It formats and writes request or response logs using a PrintWriter. ```java public class FileSink implements Sink { private final HttpLogFormatter formatter; private final PrintWriter writer; @Override public void write(Precorrelation precorrelation, HttpRequest request) throws IOException { writer.println(formatter.format(precorrelation, request)); writer.flush(); } @Override public void write(Correlation correlation, HttpRequest request, HttpResponse response) throws IOException { writer.println(formatter.format(correlation, response)); writer.flush(); } } ``` -------------------------------- ### Precorrelation Interface Definition Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Correlation.md Defines the preliminary correlation information available before a response is received. It includes methods to get the unique ID and the start time of the request. ```java public interface Precorrelation { String getId(); Instant getStart(); Correlation correlate(); } ``` -------------------------------- ### File-Based Sink Configuration Source: https://github.com/zalando/logbook/blob/main/_autodocs/configuration.md Configure Logbook to write HTTP request and response logs to a file. This example uses a custom HttpLogWriter to append logs to 'requests.log'. ```java HttpLogFormatter formatter = new DefaultHttpLogFormatter(); HttpLogWriter fileWriter = new HttpLogWriter() { private final PrintWriter writer = new PrintWriter( new FileWriter("requests.log", true)); @Override public void write(Precorrelation precorrelation, String request) throws IOException { writer.println(request); writer.flush(); } @Override public void write(Correlation correlation, String response) throws IOException { writer.println(response); writer.flush(); } }; Logbook logbook = Logbook.builder() .sink(new DefaultSink(formatter, fileWriter)) .build(); ``` -------------------------------- ### Setting a Request Logging Condition Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/LogbookBuilder.md Use a predicate to specify which HTTP requests should be logged. This example excludes requests to the /health endpoint. ```java Logbook logbook = Logbook.builder() .condition(request -> !request.getPath().startsWith("/health")) .build(); ``` -------------------------------- ### Java Example: Merging BodyFilters for OAuth and Truncation Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Filters.md Demonstrates merging two BodyFilters: one for OAuth requests and another for truncating content. This creates a composite filter. ```java BodyFilter combined = BodyFilter.merge( BodyFilters.oauthRequest(), BodyFilters.truncate(1000) ); ``` -------------------------------- ### Create an empty HttpHeaders instance Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/HttpHeaders.md Factory method to create a new, empty HttpHeaders object. Useful for starting with a clean slate. ```java static HttpHeaders empty(); ``` ```java HttpHeaders headers = HttpHeaders.empty() .update("Content-Type", "application/json"); ``` -------------------------------- ### BodyFilter Usage Example Source: https://github.com/zalando/logbook/blob/main/_autodocs/types.md An example of a BodyFilter that replaces sensitive password information with asterisks. ```java BodyFilter filter = (contentType, body) -> body.replaceAll("password=[^&]*", "password=***"); ``` -------------------------------- ### Custom HttpLogFormatter Implementation Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Formatters.md Example of a custom HttpLogFormatter that formats logs based on request and response details. It checks for an Authorization header. ```java import org.zalando.logbook.Correlation; import org.zalando.logbook.HttpRequest; import org.zalando.logbook.HttpLogFormatter; import org.zalando.logbook.Precorrelation; import java.io.IOException; public class CustomFormatter implements HttpLogFormatter { @Override public String format(Precorrelation precorrelation, HttpRequest request) throws IOException { return String.format( "[%s] %s %s %s", precorrelation.getId(), request.getMethod(), request.getPath(), request.getHeaders().getFirst("Authorization") != null ? "AUTHENTICATED" : "ANONYMOUS" ); } @Override public String format(Correlation correlation, HttpResponse response) throws IOException { return String.format( "[%s] %d %dms", correlation.getId(), response.getStatus(), correlation.getDuration().toMillis() ); } } ``` -------------------------------- ### Basic Sink Usage with Logbook Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Sink.md Demonstrates how to create and configure a default sink and integrate it into a Logbook instance. Ensure you have HttpLogFormatter and HttpLogWriter implementations available. ```java HttpLogFormatter formatter = new DefaultHttpLogFormatter(); HttpLogWriter writer = new DefaultHttpLogWriter(); Sink sink = new DefaultSink(formatter, writer); Logbook logbook = Logbook.builder() .sink(sink) .build(); ``` -------------------------------- ### Get HTTP Method Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/HttpRequest.md Retrieves the HTTP method of the request, such as GET, POST, PUT, etc. ```java String getMethod(); ``` ```java String method = request.getMethod(); // e.g., "GET", "POST" ``` -------------------------------- ### Strategy Composition with Builder Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Strategy.md Demonstrates how to create a custom strategy using a lambda expression and integrate it into Logbook using its builder pattern. ```java Strategy customStrategy = request -> { // Perform checks and return modified request return request.withBody(); }; Logbook logbook = Logbook.builder() .strategy(customStrategy) .build(); ``` -------------------------------- ### Complete Logbook Configuration Example Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/LogbookBuilder.md This snippet demonstrates a comprehensive configuration of the LogbookBuilder, including excluding specific requests, generating correlation IDs, filtering sensitive headers and query parameters, filtering body content, defining custom logging strategies, extracting attributes, and configuring the sink. ```java Logbook logbook = Logbook.builder() // Exclude health checks and actuator endpoints .condition(Conditions.exclude( Conditions.requestTo("/health/**"), Conditions.requestTo("/actuator/**") )) // Generate correlation IDs from headers or UUID .correlationId(request -> { String header = request.getHeaders().getFirst("X-Correlation-ID"); return header != null ? header : UUID.randomUUID().toString(); }) // Filter sensitive headers .headerFilter(headers -> headers .delete("Authorization", "X-API-Key", "Cookie") .delete((name, values) -> name.equalsIgnoreCase("Set-Cookie"))) // Filter query parameters .queryFilter(query -> query .replaceAll("password=[^&]*", "password=***") .replaceAll("token=[^&]*", "token=***")) // Filter body content .bodyFilter(BodyFilters.oauthRequest()) .bodyFilter(BodyFilters.truncate(1000)) .bodyFilter((contentType, body) -> "application/json".equals(contentType) ? // Custom JSON processing body : body) // Custom strategy for conditional logging .strategy(new Strategy() { @Override public HttpResponse process(HttpRequest request, HttpResponse response) throws IOException { return response.getStatus() >= 400 ? response.withBody() : response.withoutBody(); } }) // Add custom attributes .attributeExtractor(request -> HttpAttributes.of("service", "my-service")) // Configure sink .sink(new DefaultSink( new DefaultHttpLogFormatter(), new DefaultHttpLogWriter())) .build(); ``` -------------------------------- ### Netty HTTP Server Integration Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/OtherIntegrations.md Integrates Logbook with Netty HTTP servers using LogbookHttpServerHandler. This example shows how to add the handler to the Netty pipeline. ```java ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) { ch.pipeline().addLast( new HttpServerCodec(), new LogbookHttpServerHandler(logbook) ); } }) .bind(8080); ``` -------------------------------- ### Example ResponseFilter: Remove Body Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Filters.md An example of a ResponseFilter that removes the response body. This can be used to prevent sensitive data from being logged. ```java ResponseFilter removeBody = response -> response.withoutBody(); ``` -------------------------------- ### Creating and Using LogbookFilter with Custom Logbook and Strategy Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/ServletIntegration.md Shows how to define a custom logging strategy and use it with a custom Logbook instance to create a LogbookFilter. ```java Strategy strategy = request -> request.getPath().startsWith("/api") ? request.withBody() : request.withoutBody(); LogbookFilter filter = new LogbookFilter(logbook, strategy); ``` -------------------------------- ### Example RequestFilter: Remove Body Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Filters.md An example of a RequestFilter that removes the request body. This is useful for reducing log size or removing sensitive information. ```java RequestFilter removeBody = request -> request.withoutBody(); ``` -------------------------------- ### Custom CorrelationId Generation Example Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Correlation.md Provides an example implementation of the CorrelationId interface that generates a correlation ID based on a custom header and a UUID. ```java CorrelationId idGenerator = request -> { String userId = request.getHeaders().getFirst("X-User-ID"); return userId + "-" + UUID.randomUUID(); }; ``` -------------------------------- ### Java Example: Masking IDs in Request Paths Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Filters.md An example PathFilter that replaces numerical IDs in a path with a placeholder like '{id}'. This is useful for anonymizing URLs. ```java PathFilter maskIds = path -> path.replaceAll("/\\d+/", "/{id}/"); ``` -------------------------------- ### Logbook.create() Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Logbook.md Creates a Logbook instance with default configuration. This is a factory method for obtaining a ready-to-use Logbook object. ```APIDOC ## Logbook.create() ### Description Creates a `Logbook` instance with default configuration. This is a factory method for obtaining a ready-to-use Logbook object. ### Method `create` ### Parameters None ### Returns `Logbook` - A new Logbook instance with sensible defaults ### Example ```java Logbook logbook = Logbook.create(); ``` ``` -------------------------------- ### Java Example: Masking API Keys in Query Strings Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Filters.md An example QueryFilter that masks API key values in a query string. This is useful for preventing sensitive information from being logged or exposed. ```java QueryFilter maskApiKey = query -> query.replaceAll("api_key=[^&]*", "api_key=***"); ``` -------------------------------- ### Create Logbook with Custom Configuration Source: https://github.com/zalando/logbook/blob/main/_autodocs/README.md Configure Logbook with custom header filters, body filters, and conditions. ```java Logbook logbook = Logbook.builder() .headerFilter(headers -> headers.delete("Authorization")) .bodyFilter(BodyFilters.oauthRequest()) .condition(Conditions.exclude(Conditions.requestTo("/health"))) .build(); ``` -------------------------------- ### Java Example: Masking Passwords in Form Data Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Filters.md An example of a BodyFilter that masks password values in URL-encoded form data. This filter is useful for sanitizing sensitive information in request bodies. ```java BodyFilter maskPasswords = (contentType, body) -> { if ("application/x-www-form-urlencoded".equals(contentType)) { return body.replaceAll("password=[^&]*", "password=***"); } return body; }; ``` -------------------------------- ### Creating and Using LogbookFilter with Custom Logbook Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/ServletIntegration.md Demonstrates creating a custom Logbook instance with header and body filters, then using it to instantiate LogbookFilter. ```java Logbook logbook = Logbook.builder() .headerFilter(headers -> headers.delete("Authorization")) .bodyFilter(BodyFilters.truncate(1000)) .build(); LogbookFilter filter = new LogbookFilter(logbook); ``` -------------------------------- ### Integration Testing with Logbook Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/CoreConcepts.md Demonstrates how to set up and use Logbook in an integration test to verify header filtering. Ensure Logbook is built with the necessary filters before processing requests. ```java import org.junit.jupiter.api.Test; import org.zalando.logbook.HttpRequest; import org.zalando.logbook.Logbook; class IntegrationTest { @Test void testIntegration() { Logbook logbook = Logbook.builder() .headerFilter(headers -> headers.delete("Authorization")) .build(); HttpRequest request = /* test request */; logbook.process(request).write(); // Verify authorization header filtered } } ``` -------------------------------- ### Async Servlet Support Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/ServletIntegration.md Demonstrates how to use Logbook with asynchronous Servlets. Logbook automatically handles async completion, ensuring logs are captured even with asynchronous processing. ```java import javax.servlet.AsyncContext; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet(asyncSupported = true) public class AsyncServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { AsyncContext context = request.startAsync(); // Logbook automatically handles async completion context.start(() -> { try { // Your async processing response.getWriter().print("Response"); } catch (IOException e) { // Handle error } }); } } ``` -------------------------------- ### Get Request Attributes Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/HttpRequest.md Retrieves custom attributes associated with the request, defaulting to an empty map. ```java default HttpAttributes getAttributes(); ``` ```java HttpAttributes attrs = request.getAttributes(); Object userId = attrs.get("userId"); ``` -------------------------------- ### Configure WebClient for WebFlux Logging Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/SpringIntegration.md Illustrates the basic setup for configuring Logbook with Spring WebFlux's WebClient. This involves building a WebClient and potentially applying Logbook configurations. ```java @Configuration public class WebFluxLogbookConfiguration { @Bean public WebClient webClient(Logbook logbook) { return WebClient.builder() // Configure logbook for WebFlux .build(); } } ``` -------------------------------- ### Get Path Component Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/HttpRequest.md Retrieves the path component of the request URI, such as "/api/users/123". ```java String getPath(); ``` ```java String path = request.getPath(); // e.g., "/users/123" ``` -------------------------------- ### Get Host Component Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/HttpRequest.md Retrieves the host component of the request URI, which can be a hostname or IP address. ```java String getHost(); ``` ```java String host = request.getHost(); // e.g., "api.example.com" ``` -------------------------------- ### Get Remote Client Address Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/HttpRequest.md Retrieves the IP address or hostname of the client making the request. ```java String getRemote(); ``` ```java String remoteAddress = request.getRemote(); // e.g., "192.168.1.100" or "client.example.com" ``` -------------------------------- ### Get Message Origin Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/HttpMessage.md Determines if the message was sent locally by the application or received from a remote source. ```java Origin origin = message.getOrigin(); if (origin == Origin.LOCAL) { // This is a request we sent } ``` -------------------------------- ### Unit Testing Formatters in Java Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/CoreConcepts.md Provides a JUnit test example for unit testing Logbook's HTTP formatters. It shows how to instantiate a formatter, provide mock data for Precorrelation and HttpRequest, and assert the formatted output. ```java @Test void testFormatter() { HttpLogFormatter formatter = new DefaultHttpLogFormatter(); Precorrelation precorr = /* test data */; HttpRequest request = /* mock */; String result = formatter.format(precorr, request); assertThat(result).contains("GET"); assertThat(result).contains("/api/users"); } ``` -------------------------------- ### Spring Boot Starter Maven Dependency Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/OtherIntegrations.md Include the logbook-spring-boot-starter dependency for simplified Spring Boot integration. ```xml org.zalando logbook-spring-boot-starter ``` -------------------------------- ### JSON Response with Plain Text Body Source: https://github.com/zalando/logbook/blob/main/README.md Example of a JSON response log where the body is plain text. ```json { "origin": "local", "type": "response", "correlation": "2d66e4bc-9a0d-11e5-a84c-1f39510f0d6b", "duration": 25, "protocol": "HTTP/1.1", "status": 200, "headers": { "Content-Type": ["text/plain"] }, "body": "Hello world!" } ``` -------------------------------- ### Get Charset Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/HttpMessage.md Extracts the character encoding from the Content-Type header. Defaults to UTF-8 for JSON, otherwise UTF-8. ```java Charset charset = message.getCharset(); // e.g., StandardCharsets.UTF_8 ``` -------------------------------- ### Execute Logbook JMH Benchmark Source: https://github.com/zalando/logbook/blob/main/logbook-jmh/README.md Run the Logbook JMH benchmark from the command line and output results in JSON format. Ensure you have Maven installed and the benchmark JAR is built. ```bash mvn clean package && java -jar logbook-jmh/target/benchmark.jar LogbookBenchmark -rf json ``` -------------------------------- ### DefaultCorrelationId Generator Example Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Correlation.md Illustrates the default implementation for generating unique correlation IDs, typically based on UUIDs. ```java CorrelationId generator = new DefaultCorrelationId(); String id = generator.generate(request); // Returns UUID-based ID ``` -------------------------------- ### LogstashLogbackSink with Custom Level Source: https://github.com/zalando/logbook/blob/main/README.md Java code demonstrating how to initialize LogstashLogbackSink with a specific logging level, such as INFO. ```java LogstashLogbackSink sink = new LogstashLogbackSink(formatter, Level.INFO); ``` -------------------------------- ### DefaultHttpLogFormatter Output Example Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Formatters.md Demonstrates the typical output format produced by the DefaultHttpLogFormatter for both outgoing requests and incoming responses. This format is line-separated and includes key details like correlation ID, headers, and duration. ```text Outgoing Request: 3fa85f64-5717-4562-b3fc-2c963f66afa6 Remote: 192.168.1.100 GET /api/users?page=1 HTTP/1.1 Host: api.example.com Accept: application/json --- Incoming Response: 3fa85f64-5717-4562-b3fc-2c963f66afa6 Duration: 245 ms HTTP/1.1 200 OK Content-Type: application/json Content-Length: 456 {...} ``` -------------------------------- ### Get Query String Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/HttpRequest.md Retrieves the query string of the request URI, or an empty string if no query parameters are present. ```java String getQuery(); ``` ```java String query = request.getQuery(); // e.g., "user_id=42&format=json" ``` -------------------------------- ### Get HTTP Headers Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/HttpMessage.md Retrieves the immutable multimap of HTTP headers. Allows access to individual header values. ```java HttpHeaders headers = message.getHeaders(); String contentType = headers.getFirst("Content-Type"); List acceptValues = headers.get("Accept"); ``` -------------------------------- ### Get HTTP Protocol Version Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/HttpMessage.md Retrieves the HTTP protocol version of the message. Defaults to "HTTP/1.1". ```java String version = message.getProtocolVersion(); // e.g., "HTTP/1.1", "HTTP/2" ``` -------------------------------- ### Create LogbookClientHttpRequestInterceptor Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/SpringIntegration.md Creates an interceptor with a Logbook instance. Use this to initialize the interceptor with a basic Logbook configuration. ```java Logbook logbook = Logbook.create(); LogbookClientHttpRequestInterceptor interceptor = new LogbookClientHttpRequestInterceptor(logbook); ``` -------------------------------- ### JSON Response with JSON Body Inlined Source: https://github.com/zalando/logbook/blob/main/README.md Example of a JSON response log where the body is a JSON object, which is inlined into the log. ```json { "origin": "local", "type": "response", "correlation": "2d66e4bc-9a0d-11e5-a84c-1f39510f0d6b", "duration": 25, "protocol": "HTTP/1.1", "status": 200, "headers": { "Content-Type": ["application/json"] }, "body": { "greeting": "Hello, world!" } } ``` -------------------------------- ### Scalyr Query for Local Requests to Tokeninfo Source: https://github.com/zalando/logbook/blob/main/docs/scalyr.md Example Scalyr query to find local requests directed to the 'tokeninfo' endpoint. ```text $httpOrigin = 'local' $httpUri matches '.*/tokeninfo' ``` -------------------------------- ### getScheme() Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/HttpRequest.md Returns the URI scheme. ```APIDOC ## getScheme() ### Description Returns the URI scheme. ### Method ```java String getScheme(); ``` ### Returns `String` — Scheme component (e.g., "http" or "https") ### Example ```java String scheme = request.getScheme(); // e.g., "https" ``` ``` -------------------------------- ### Create Customized Logbook Instance Source: https://github.com/zalando/logbook/blob/main/README.md Use LogbookBuilder to create a customized Logbook instance with specific conditions, filters, and sinks. ```java Logbook logbook = Logbook.builder() .condition(new CustomCondition()) .queryFilter(new CustomQueryFilter()) .pathFilter(new CustomPathFilter()) .headerFilter(new CustomHeaderFilter()) .bodyFilter(new CustomBodyFilter()) .requestFilter(new CustomRequestFilter()) .responseFilter(new CustomResponseFilter()) .sink(new DefaultSink( new CustomHttpLogFormatter(), new CustomHttpLogWriter() )) .build(); ``` -------------------------------- ### Safe Sink Implementation in Java Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/CoreConcepts.md Provides an example of implementing a 'fail-safe' logging sink. This pattern ensures that logging failures do not disrupt the application's normal operation, logging the error but continuing execution. ```java // Example: Write safely Sink safeSink = new Sink() { @Override public void write(Precorrelation precorr, HttpRequest req) { try { delegate.write(precorr, req); } catch (IOException e) { logger.warn("Logging failed, continuing", e); } } }; ``` -------------------------------- ### Get Content Type Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/HttpMessage.md Extracts the MIME type from the Content-Type header, excluding the charset. Returns null if the header is absent. ```java String contentType = message.getContentType(); // For "application/json; charset=utf-8", returns "application/json" ``` -------------------------------- ### Create Logbook Instance with Custom Builder Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/Logbook.md Creates a builder for customizing Logbook configuration. Use this to specify custom sinks, conditions, or body filters. ```java Logbook logbook = Logbook.builder() .sink(/* custom sink */) .condition(/* condition */) .bodyFilter(/* filter */) .build(); ``` -------------------------------- ### Precorrelation Interface Source: https://github.com/zalando/logbook/blob/main/_autodocs/types.md Represents correlation information available before a response is received. It provides a unique ID and the start time of the correlation. ```java @API(status = STABLE) public interface Precorrelation { String getId(); Instant getStart(); Correlation correlate(); } ``` -------------------------------- ### Applying a Path Filter for Normalization Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/LogbookBuilder.md Use a path filter to normalize request paths, for example, by replacing specific IDs with a placeholder. ```java Logbook logbook = Logbook.builder() .pathFilter(path -> path.replaceAll("/\d+/", "/{id}/")) .build(); ``` -------------------------------- ### Body Buffering Trade-off Comparison Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/CoreConcepts.md Compares the trade-offs between buffering a request body with `withBody()` versus not buffering with `withoutBody()`, highlighting memory footprint, processing speed, and body availability. ```text withBody() withoutBody() ├─ Request body available ├─ No buffering overhead ├─ Larger memory footprint ├─ Faster processing ├─ Slower initial processing ├─ Body not logged └─ Body can be logged └─ Suitable for GET/HEAD ``` -------------------------------- ### Handling Strategy Processing Failures Source: https://github.com/zalando/logbook/blob/main/_autodocs/errors.md Demonstrates how to catch exceptions, such as IOExceptions, that may occur during custom strategy processing in Logbook. This ensures that strategy failures do not halt the application's integration layer. ```java try { logbook.process(request, strategy); } catch (IOException e) { logger.error("Strategy processing failed", e); } ``` -------------------------------- ### JAX-RS Application Registration Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/OtherIntegrations.md Registers Logbook filters for JAX-RS 3.x applications. This example shows how to register both server and client-side filters. ```java @ApplicationPath("/api") public class RestApplication extends Application { @Override public Set getSingletons() { Logbook logbook = Logbook.create(); return Set.of( new LogbookContainerRequestFilter(logbook), new LogbookContainerResponseFilter(logbook), new LogbookClientRequestFilter(logbook), new LogbookClientResponseFilter(logbook) ); } } ``` -------------------------------- ### Integrate Logbook with HttpClient 5 ExecHandler Source: https://github.com/zalando/logbook/blob/main/README.md Use LogbookHttpExecHandler with HttpClient 5's addExecInterceptorFirst for logging. This ensures compression and decompression are handled correctly around logging. ```java CloseableHttpClient client = HttpClientBuilder.create() .addExecInterceptorFirst("Logbook", new LogbookHttpExecHandler(logbook)) .build(); ``` -------------------------------- ### Scalyr Query for Local 4xx Responses Source: https://github.com/zalando/logbook/blob/main/docs/scalyr.md Example Scalyr query to identify local responses that resulted in a 4xx status code. ```text $httpOrigin = 'local' $httpStatus >= 400 $httpStatus < 500 ``` -------------------------------- ### Content Type Awareness Examples Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/CoreConcepts.md Lists common content types and how Logbook handles them, including specific formatting or filtering capabilities for JSON, form data, and XML, as well as general text and binary types. ```plaintext application/json → JSON formatting available application/x-www-form-urlencoded → Form field filtering application/xml → XML compacting available text/* → String processing image/*, video/*, etc → Binary content (truncate recommended) ``` -------------------------------- ### Implementing Metrics for Logbook Requests Source: https://github.com/zalando/logbook/blob/main/_autodocs/errors.md Integrate Logbook with a metrics registry to track successful and failed requests. This sink wraps a delegate and increments counters based on the outcome. ```java Sink metricsEnabledSink = new Sink() { private final MeterRegistry metrics; @Override public void write(Precorrelation precorr, HttpRequest request) throws IOException { try { delegate.write(precorr, request); metrics.counter("logbook.request.success").increment(); } catch (IOException e) { metrics.counter("logbook.request.failure").increment(); throw e; } } }; ``` -------------------------------- ### Request Processing Lifecycle Stage 1 Source: https://github.com/zalando/logbook/blob/main/_autodocs/api-reference/CoreConcepts.md Illustrates the initial stage of request processing where the strategy decides whether to buffer the request body. Buffering allows the framework to process the request while retaining the body for logging or filtering. ```text HTTP Request arrives ↓ Strategy.process(HttpRequest) ↓ Decide: withBody() or withoutBody() ↓ Body buffered in memory ```