From 705c3bb54f19c33d8b914bf5dda3756191968351 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Skj=C3=B8lberg?= Date: Wed, 29 Apr 2026 15:49:44 +0200 Subject: [PATCH 1/9] Add truncate message for request-response-logging --- .../example/web/rest/DocumentEndpoint.java | 4 +- .../example/web/rest/DocumentEndpoint.java | 42 +++++++++++++++++-- .../WebLoggingFormatWithBigResponsesTest.java | 25 +++++++++++ ...estResponseSingleFieldAppendingMarker.java | 17 ++++++++ 4 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 examples/gcp-web-without-test-artifacts-example/src/test/java/org/entur/example/web/WebLoggingFormatWithBigResponsesTest.java create mode 100644 request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/RequestResponseSingleFieldAppendingMarker.java diff --git a/examples/gcp-web-example/src/main/java/org/entur/example/web/rest/DocumentEndpoint.java b/examples/gcp-web-example/src/main/java/org/entur/example/web/rest/DocumentEndpoint.java index 34d6ba89..50a8fa30 100644 --- a/examples/gcp-web-example/src/main/java/org/entur/example/web/rest/DocumentEndpoint.java +++ b/examples/gcp-web-example/src/main/java/org/entur/example/web/rest/DocumentEndpoint.java @@ -87,7 +87,9 @@ ResponseEntity bigResponse() throws IOException { generator.writeStartObject(); generator.writeStringProperty("start", "here"); - generator.writeStringProperty("longValue", generateLongString(192*1024)); + for(int i = 0; i < 10; i++) { + generator.writeStringProperty("longValue" + i, generateLongString(25*1024)); + } generator.writeStringProperty("end", "here"); generator.writeEndObject(); diff --git a/examples/gcp-web-without-test-artifacts-example/src/main/java/org/entur/example/web/rest/DocumentEndpoint.java b/examples/gcp-web-without-test-artifacts-example/src/main/java/org/entur/example/web/rest/DocumentEndpoint.java index 7726710c..b02625c7 100644 --- a/examples/gcp-web-without-test-artifacts-example/src/main/java/org/entur/example/web/rest/DocumentEndpoint.java +++ b/examples/gcp-web-without-test-artifacts-example/src/main/java/org/entur/example/web/rest/DocumentEndpoint.java @@ -4,10 +4,10 @@ import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; + +import java.io.CharArrayWriter; +import java.io.IOException; @RestController @RequestMapping("/api/document") @@ -46,5 +46,39 @@ public ResponseEntity errorMethod(@RequestBody MyEntity entity) throws Interrupt } + @GetMapping(value = "/some/bigResponse", produces = "application/json") + ResponseEntity bigResponse() throws IOException { + tools.jackson.core.json.JsonFactory factory = new tools.jackson.core.json.JsonFactory(); + + CharArrayWriter writer = new CharArrayWriter(); + + tools.jackson.core.JsonGenerator generator = factory.createGenerator(writer); + + generator.writeStartObject(); + generator.writeStringProperty("start", "here"); + for(int i = 0; i < 10; i++) { + generator.writeStringProperty("longValue" + i, generateLongString(25*1024)); + } + generator.writeStringProperty("longValue", generateLongString(192*1024)); + generator.writeStringProperty("end", "here"); + generator.writeEndObject(); + + generator.flush(); + + return new ResponseEntity<>(writer.toString(), HttpStatus.OK); + } + + private String generateLongString(int length) { + StringBuilder builder = new StringBuilder(length); + + int mod = 'z' - 'a'; + + for(int i = 0; i < length; i++) { + char c = (char) ('a' + i % mod); + builder.append(c); + } + return builder.toString(); + } + } \ No newline at end of file diff --git a/examples/gcp-web-without-test-artifacts-example/src/test/java/org/entur/example/web/WebLoggingFormatWithBigResponsesTest.java b/examples/gcp-web-without-test-artifacts-example/src/test/java/org/entur/example/web/WebLoggingFormatWithBigResponsesTest.java new file mode 100644 index 00000000..d2803cc3 --- /dev/null +++ b/examples/gcp-web-without-test-artifacts-example/src/test/java/org/entur/example/web/WebLoggingFormatWithBigResponsesTest.java @@ -0,0 +1,25 @@ +package org.entur.example.web; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +public class WebLoggingFormatWithBigResponsesTest { + + @Autowired + private TestRestTemplate restTemplate; + + @Test + public void useHumanReadablePlainEncoderTest() { + ResponseEntity response = restTemplate.getForEntity("/api/document/some/bigResponse", String.class); + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + } + +} \ No newline at end of file diff --git a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/RequestResponseSingleFieldAppendingMarker.java b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/RequestResponseSingleFieldAppendingMarker.java new file mode 100644 index 00000000..a0e19bb1 --- /dev/null +++ b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/RequestResponseSingleFieldAppendingMarker.java @@ -0,0 +1,17 @@ +package no.entur.logging.cloud.logbook; + +import net.logstash.logback.marker.SingleFieldAppendingMarker; + +public abstract class RequestResponseSingleFieldAppendingMarker extends SingleFieldAppendingMarker { + + protected final boolean truncated; + + public RequestResponseSingleFieldAppendingMarker(String markerName, String fieldName, boolean truncated) { + super(markerName, fieldName); + this.truncated = truncated; + } + + public boolean isTruncated() { + return truncated; + } +} From 7c2514007b76a914d4b9369d7c8cae7c75423613 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Skj=C3=B8lberg?= Date: Wed, 29 Apr 2026 16:31:04 +0200 Subject: [PATCH 2/9] Fix truncated length message --- .../WebLoggingFormatWithBigResponsesTest.java | 2 + .../WebLoggingFormatWithBigResponsesTest.java | 4 +- ...tyPrintingLogLevelLogstashLogbackSink.java | 16 +++---- ...tingRequestSingleFieldAppendingMarker.java | 4 +- ...ingResponseSingleFieldAppendingMarker.java | 4 +- .../logbook/test/PrettyPrintingSink.java | 8 ++-- ...ngOndemandLogLevelLogstashLogbackSink.java | 46 +++++++++++-------- .../AbstractLogLevelLogstashLogbackSink.java | 44 ++++++++++-------- .../cloud/logbook/AbstractLogLevelSink.java | 24 +++++----- .../AbstractSingleFieldAppendingMarker.java | 6 +-- .../logbook/LogLevelLogstashLogbackSink.java | 10 ++-- .../cloud/logbook/MessageComposer.java | 24 +++++++++- ...estResponseSingleFieldAppendingMarker.java | 14 +++++- .../RequestSingleFieldAppendingMarker.java | 4 +- .../ResponseSingleFieldAppendingMarker.java | 4 +- ...actOndemandSingleFieldAppendingMarker.java | 7 +-- .../OndemandLogLevelLogstashLogbackSink.java | 35 ++++++++------ ...estOndemandSingleFieldAppendingMarker.java | 4 +- ...nseOndemandSingleFieldAppendingMarker.java | 5 +- ...stractLogLevelLogstashLogbackSinkTest.java | 22 ++++----- 20 files changed, 171 insertions(+), 116 deletions(-) diff --git a/examples/gcp-web-example/src/test/java/org/entur/example/web/WebLoggingFormatWithBigResponsesTest.java b/examples/gcp-web-example/src/test/java/org/entur/example/web/WebLoggingFormatWithBigResponsesTest.java index 5a5482d8..956b869c 100644 --- a/examples/gcp-web-example/src/test/java/org/entur/example/web/WebLoggingFormatWithBigResponsesTest.java +++ b/examples/gcp-web-example/src/test/java/org/entur/example/web/WebLoggingFormatWithBigResponsesTest.java @@ -44,6 +44,8 @@ public void useMachineReadableJsonEncoder() throws InterruptedException { try (CompositeConsoleOutputControlClosable c = CompositeConsoleOutputControl.useMachineReadableJsonEncoder()) { ResponseEntity response = restTemplate.getForEntity("/api/document/some/bigResponse", String.class); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + + Thread.sleep(1000); } } diff --git a/examples/gcp-web-without-test-artifacts-example/src/test/java/org/entur/example/web/WebLoggingFormatWithBigResponsesTest.java b/examples/gcp-web-without-test-artifacts-example/src/test/java/org/entur/example/web/WebLoggingFormatWithBigResponsesTest.java index d2803cc3..8893fbe1 100644 --- a/examples/gcp-web-without-test-artifacts-example/src/test/java/org/entur/example/web/WebLoggingFormatWithBigResponsesTest.java +++ b/examples/gcp-web-without-test-artifacts-example/src/test/java/org/entur/example/web/WebLoggingFormatWithBigResponsesTest.java @@ -2,15 +2,17 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureTestRestTemplate; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.resttestclient.TestRestTemplate; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +@AutoConfigureTestRestTemplate public class WebLoggingFormatWithBigResponsesTest { @Autowired diff --git a/request-response/logbook-test/src/main/java/no/entur/logging/cloud/logbook/logbook/test/PrettyPrintingLogLevelLogstashLogbackSink.java b/request-response/logbook-test/src/main/java/no/entur/logging/cloud/logbook/logbook/test/PrettyPrintingLogLevelLogstashLogbackSink.java index e933c924..92b79480 100644 --- a/request-response/logbook-test/src/main/java/no/entur/logging/cloud/logbook/logbook/test/PrettyPrintingLogLevelLogstashLogbackSink.java +++ b/request-response/logbook-test/src/main/java/no/entur/logging/cloud/logbook/logbook/test/PrettyPrintingLogLevelLogstashLogbackSink.java @@ -1,10 +1,6 @@ package no.entur.logging.cloud.logbook.logbook.test; -import no.entur.logging.cloud.logbook.AbstractLogLevelLogstashLogbackSink; -import no.entur.logging.cloud.logbook.AbstractSinkBuilder; -import no.entur.logging.cloud.logbook.DefaultRemoteHttpMessageContextSupplier; -import no.entur.logging.cloud.logbook.MessageComposer; -import no.entur.logging.cloud.logbook.RemoteHttpMessageContextSupplier; +import no.entur.logging.cloud.logbook.*; import org.slf4j.Marker; import org.zalando.logbook.HttpRequest; import org.zalando.logbook.HttpResponse; @@ -60,14 +56,14 @@ public PrettyPrintingLogLevelLogstashLogbackSink(BiConsumer logC } @Override - protected Marker newRequestSingleFieldAppendingMarker(HttpRequest request, String body, boolean wellformed) { - return new PrettyPrintingRequestSingleFieldAppendingMarker(request, body, wellformed); + protected RequestResponseSingleFieldAppendingMarker newRequestSingleFieldAppendingMarker(HttpRequest request, String body, boolean wellformed, int truncated) { + return new PrettyPrintingRequestSingleFieldAppendingMarker(request, body, wellformed, truncated); } @Override - protected Marker newResponseSingleFieldAppendingMarker(HttpResponse response, Duration duration, String body, - boolean wellformed) { - return new PrettyPrintingResponseSingleFieldAppendingMarker(response, duration, body, wellformed); + protected RequestResponseSingleFieldAppendingMarker newResponseSingleFieldAppendingMarker(HttpResponse response, Duration duration, String body, + boolean wellformed, int truncated) { + return new PrettyPrintingResponseSingleFieldAppendingMarker(response, duration, body, wellformed, truncated); } } diff --git a/request-response/logbook-test/src/main/java/no/entur/logging/cloud/logbook/logbook/test/PrettyPrintingRequestSingleFieldAppendingMarker.java b/request-response/logbook-test/src/main/java/no/entur/logging/cloud/logbook/logbook/test/PrettyPrintingRequestSingleFieldAppendingMarker.java index bbcb8788..96a0fa84 100644 --- a/request-response/logbook-test/src/main/java/no/entur/logging/cloud/logbook/logbook/test/PrettyPrintingRequestSingleFieldAppendingMarker.java +++ b/request-response/logbook-test/src/main/java/no/entur/logging/cloud/logbook/logbook/test/PrettyPrintingRequestSingleFieldAppendingMarker.java @@ -9,8 +9,8 @@ public class PrettyPrintingRequestSingleFieldAppendingMarker extends RequestSingleFieldAppendingMarker { - public PrettyPrintingRequestSingleFieldAppendingMarker(HttpRequest request, String body, boolean wellformed) { - super(request, body, wellformed); + public PrettyPrintingRequestSingleFieldAppendingMarker(HttpRequest request, String body, boolean wellformed, int truncated) { + super(request, body, wellformed, truncated); } @Override diff --git a/request-response/logbook-test/src/main/java/no/entur/logging/cloud/logbook/logbook/test/PrettyPrintingResponseSingleFieldAppendingMarker.java b/request-response/logbook-test/src/main/java/no/entur/logging/cloud/logbook/logbook/test/PrettyPrintingResponseSingleFieldAppendingMarker.java index a7e13f24..2aaa65b9 100644 --- a/request-response/logbook-test/src/main/java/no/entur/logging/cloud/logbook/logbook/test/PrettyPrintingResponseSingleFieldAppendingMarker.java +++ b/request-response/logbook-test/src/main/java/no/entur/logging/cloud/logbook/logbook/test/PrettyPrintingResponseSingleFieldAppendingMarker.java @@ -14,8 +14,8 @@ public class PrettyPrintingResponseSingleFieldAppendingMarker extends ResponseSingleFieldAppendingMarker { - public PrettyPrintingResponseSingleFieldAppendingMarker(HttpResponse response, Duration duration, String body, boolean wellformed) { - super(response, duration, body, wellformed); + public PrettyPrintingResponseSingleFieldAppendingMarker(HttpResponse response, Duration duration, String body, boolean wellformed, int truncated) { + super(response, duration, body, wellformed, truncated); } @Override diff --git a/request-response/logbook-test/src/main/java/no/entur/logging/cloud/logbook/logbook/test/PrettyPrintingSink.java b/request-response/logbook-test/src/main/java/no/entur/logging/cloud/logbook/logbook/test/PrettyPrintingSink.java index 033fce02..fb566b22 100644 --- a/request-response/logbook-test/src/main/java/no/entur/logging/cloud/logbook/logbook/test/PrettyPrintingSink.java +++ b/request-response/logbook-test/src/main/java/no/entur/logging/cloud/logbook/logbook/test/PrettyPrintingSink.java @@ -84,8 +84,8 @@ public PrettyPrintingSink(BooleanSupplier logLevelEnabled, BiConsumer 0) { if (request.getOrigin() == Origin.LOCAL) { // trust our own data to be wellformed - if (body.length > maxBodySize) { + if (body.length < maxBodySize) { writer = new PrettyPrintingLocalHttpMessageBodyWriter(body); } else { + truncated = body.length - maxBodySize; + writer = new PrettyPrintingLocalMaxSizeHttpMessageBodyWriter(jsonMapper, body, maxBodySize); } } else { HttpMessageStateSupplier httpMessageStateSupplier = requestHttpMessageStateSupplierSource.get(); - if (body.length > maxBodySize) { - writer = new PrettyPrintingRemoteHttpMessageBodyWriter(jsonMapper, body, - httpMessageStateSupplier); + if (body.length < maxBodySize) { + writer = new PrettyPrintingRemoteHttpMessageBodyWriter(jsonMapper, body, httpMessageStateSupplier); } else { + truncated = body.length - maxBodySize; + writer = new PrettyPrintingRemoteMaxSizeHttpMessageBodyWriter(jsonMapper, body, maxSize, httpMessageStateSupplier); } @@ -112,8 +113,10 @@ public Marker createRequestMarker(HttpRequest request) { String bodyAsString = request.getBodyAsString(); if (bodyAsString != null && bodyAsString.length() > 0) { if (bodyAsString.length() > maxBodySize) { - String truncated = bodyAsString.substring(0, maxBodySize); - writer = new StringHttpMessageBodyWriter(truncated); + truncated = bodyAsString.length() - maxBodySize; + + String truncatedString = bodyAsString.substring(0, maxBodySize); + writer = new StringHttpMessageBodyWriter(truncatedString); } else { writer = new StringHttpMessageBodyWriter(bodyAsString); } @@ -123,32 +126,37 @@ public Marker createRequestMarker(HttpRequest request) { } } - return new RequestOndemandSingleFieldAppendingMarker(request, writer); + return new RequestOndemandSingleFieldAppendingMarker(request, writer, truncated); } - public Marker createResponseMarker(Correlation correlation, HttpResponse response) { + public RequestResponseSingleFieldAppendingMarker createResponseMarker(Correlation correlation, HttpResponse response) { HttpMessageBodyWriter writer = EmptyHttpMessageBodyWriter.INSTANCE; + int truncated = -1; if (ContentType.isJsonMediaType(response.getContentType())) { try { byte[] body = response.getBody(); if (body != null && body.length > 0) { if (response.getOrigin() == Origin.LOCAL) { // trust our own data to be wellformed - if (body.length > maxBodySize) { + if (body.length < maxBodySize) { writer = new PrettyPrintingLocalHttpMessageBodyWriter(body); } else { + truncated = body.length - maxBodySize; + writer = new PrettyPrintingLocalMaxSizeHttpMessageBodyWriter(jsonMapper, body, maxBodySize); } } else { HttpMessageStateSupplier httpMessageStateSupplier = responseHttpMessageStateSupplierSource .get(); - if (body.length > maxBodySize) { + if (body.length < maxBodySize) { writer = new PrettyPrintingRemoteHttpMessageBodyWriter(jsonMapper, body, httpMessageStateSupplier); } else { + truncated = body.length - maxBodySize; + writer = new PrettyPrintingRemoteMaxSizeHttpMessageBodyWriter(jsonMapper, body, maxSize, httpMessageStateSupplier); } @@ -163,8 +171,10 @@ public Marker createResponseMarker(Correlation correlation, HttpResponse respons String bodyAsString = response.getBodyAsString(); if (bodyAsString != null && bodyAsString.length() > 0) { if (bodyAsString.length() > maxBodySize) { - String truncated = bodyAsString.substring(0, maxBodySize); - writer = new StringHttpMessageBodyWriter(truncated); + truncated = bodyAsString.length() - maxBodySize; + + String truncatedString = bodyAsString.substring(0, maxBodySize); + writer = new StringHttpMessageBodyWriter(truncatedString); } else { writer = new StringHttpMessageBodyWriter(bodyAsString); } @@ -174,7 +184,7 @@ public Marker createResponseMarker(Correlation correlation, HttpResponse respons } } - return new ResponseOndemandSingleFieldAppendingMarker(response, correlation.getDuration(), writer); + return new ResponseOndemandSingleFieldAppendingMarker(response, correlation.getDuration(), writer, truncated); } } diff --git a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/AbstractLogLevelLogstashLogbackSink.java b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/AbstractLogLevelLogstashLogbackSink.java index 50b253ae..93b9c010 100644 --- a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/AbstractLogLevelLogstashLogbackSink.java +++ b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/AbstractLogLevelLogstashLogbackSink.java @@ -35,25 +35,25 @@ public AbstractLogLevelLogstashLogbackSink(BiConsumer logConsume this.remoteHttpMessageContextSupplier = remoteHttpMessageContextSupplier; } - public Marker createRequestMarker(HttpRequest request) { + public RequestResponseSingleFieldAppendingMarker createRequestMarker(HttpRequest request) { String contentType = request.getContentType(); boolean isJson = ContentType.isJsonMediaType(contentType); boolean isXml = isXmlMediaType(contentType); if (!isJson && !isXml) { - return newRequestSingleFieldAppendingMarker(request, null, false); + return newRequestSingleFieldAppendingMarker(request, null, false, -1); } String bodyAsString; try { bodyAsString = request.getBodyAsString(); } catch (Exception e) { - return newRequestSingleFieldAppendingMarker(request, null, false); + return newRequestSingleFieldAppendingMarker(request, null, false, -1); } if (bodyAsString == null || bodyAsString.length() == 0) { - return newRequestSingleFieldAppendingMarker(request, null, false); + return newRequestSingleFieldAppendingMarker(request, null, false, -1); } // add sanity check for JSON content, even if mimetype does match @@ -61,17 +61,19 @@ public Marker createRequestMarker(HttpRequest request) { if (bodyAsString.length() > maxSize) { // TODO add filter String truncatedBody = bodyAsString.substring(0, maxSize); - return newRequestSingleFieldAppendingMarker(request, truncatedBody, false); + return newRequestSingleFieldAppendingMarker(request, truncatedBody, false, -1); } - return newRequestSingleFieldAppendingMarker(request, bodyAsString, false); + return newRequestSingleFieldAppendingMarker(request, bodyAsString, false, -1); } String body; boolean wellformed; + int truncated = -1; if (request.getOrigin() == Origin.LOCAL) { // trust data from ourselves to be wellformed and not pretty-printed if (bodyAsString.length() > maxSize) { + truncated = bodyAsString.length() - maxSize; try { body = maxSizeJsonFilter.transform(bodyAsString); wellformed = true; @@ -87,6 +89,7 @@ public Marker createRequestMarker(HttpRequest request) { } else { // do not trust data from others to be wellformed if (bodyAsString.length() > maxSize) { + truncated = bodyAsString.length() - maxSize; try { body = maxSizeJsonFilter.transform(bodyAsString); wellformed = true; @@ -105,51 +108,55 @@ public Marker createRequestMarker(HttpRequest request) { } } } - return newRequestSingleFieldAppendingMarker(request, body, wellformed); + return newRequestSingleFieldAppendingMarker(request, body, wellformed, truncated); } - protected abstract Marker newRequestSingleFieldAppendingMarker(HttpRequest request, String body, - boolean wellformed); + protected abstract RequestResponseSingleFieldAppendingMarker newRequestSingleFieldAppendingMarker(HttpRequest request, String body, + boolean wellformed, int truncated); - public Marker createResponseMarker(Correlation correlation, HttpResponse response) { + public RequestResponseSingleFieldAppendingMarker createResponseMarker(Correlation correlation, HttpResponse response) { String contentType = response.getContentType(); boolean isJson = ContentType.isJsonMediaType(contentType); boolean isXml = isXmlMediaType(contentType); if (!isJson && !isXml) { - return newResponseSingleFieldAppendingMarker(response, correlation.getDuration(), null, false); + return newResponseSingleFieldAppendingMarker(response, correlation.getDuration(), null, false, -1); } String bodyAsString; try { bodyAsString = response.getBodyAsString(); } catch (Exception e) { - return newResponseSingleFieldAppendingMarker(response, correlation.getDuration(), null, false); + return newResponseSingleFieldAppendingMarker(response, correlation.getDuration(), null, false, -1); } if (bodyAsString == null || bodyAsString.length() == 0) { - return newResponseSingleFieldAppendingMarker(response, correlation.getDuration(), null, false); + return newResponseSingleFieldAppendingMarker(response, correlation.getDuration(), null, false, -1); } // add sanity check for JSON content, even if mimetype does match if (!isJson || !smellsLikeJson(bodyAsString)) { if(bodyAsString.length() > maxSize) { // TODO add filter + int truncated = bodyAsString.length() - maxSize; + String truncatedBody = bodyAsString.substring(0, maxSize); return newResponseSingleFieldAppendingMarker(response, correlation.getDuration(), - truncatedBody, false); + truncatedBody, false, truncated); } return new ResponseSingleFieldAppendingMarker(response, correlation.getDuration(), bodyAsString, - false); + false, -1); } String body; boolean wellformed; + int truncated = -1; if (response.getOrigin() == Origin.LOCAL) { // trust data from ourselves to be wellformed if (bodyAsString.length() > maxSize) { + truncated = bodyAsString.length() - maxSize; try { body = maxSizeJsonFilter.transform(bodyAsString); wellformed = true; @@ -165,6 +172,7 @@ public Marker createResponseMarker(Correlation correlation, HttpResponse respons } else { // do not trust data from others to be wellformed if (bodyAsString.length() > maxSize) { + truncated = bodyAsString.length() - maxSize; try { body = maxSizeJsonFilter.transform(bodyAsString); wellformed = true; @@ -183,11 +191,11 @@ public Marker createResponseMarker(Correlation correlation, HttpResponse respons } } } - return newResponseSingleFieldAppendingMarker(response, correlation.getDuration(), body, wellformed); + return newResponseSingleFieldAppendingMarker(response, correlation.getDuration(), body, wellformed, truncated); } - protected abstract Marker newResponseSingleFieldAppendingMarker(HttpResponse response, Duration duration, String body, - boolean wellformed); + protected abstract RequestResponseSingleFieldAppendingMarker newResponseSingleFieldAppendingMarker(HttpResponse response, Duration duration, String body, + boolean wellformed, int truncated); /** * diff --git a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/AbstractLogLevelSink.java b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/AbstractLogLevelSink.java index 9c5d2ffc..59d534d0 100644 --- a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/AbstractLogLevelSink.java +++ b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/AbstractLogLevelSink.java @@ -54,43 +54,43 @@ public boolean isActive() { return logLevelEnabled.getAsBoolean(); } - protected void requestMessage(HttpRequest request, StringBuilder messageBuilder) throws IOException { + protected void requestMessage(HttpRequest request, StringBuilder messageBuilder, int truncated) throws IOException { if (request.getOrigin() == Origin.LOCAL) { - client.requestMessage(request, messageBuilder); + client.requestMessage(request, messageBuilder, truncated); } else { - server.requestMessage(request, messageBuilder); + server.requestMessage(request, messageBuilder, truncated); } } protected void responseMessage(Correlation correlation, HttpRequest request, HttpResponse response, - StringBuilder messageBuilder) throws IOException { + StringBuilder messageBuilder, int truncated) throws IOException { if (request.getOrigin() == Origin.LOCAL) { - client.responseMessage(correlation, request, response, messageBuilder); + client.responseMessage(correlation, request, response, messageBuilder, truncated); } else { - server.responseMessage(correlation, request, response, messageBuilder); + server.responseMessage(correlation, request, response, messageBuilder, truncated); } } @Override public void write(final Precorrelation precorrelation, final HttpRequest request) throws IOException { - Marker marker = createRequestMarker(request); + RequestResponseSingleFieldAppendingMarker marker = createRequestMarker(request); StringBuilder stringBuilder = new StringBuilder(256); - requestMessage(request, stringBuilder); + requestMessage(request, stringBuilder, marker != null ? marker.getTruncated() : -1); logConsumer.accept(marker, stringBuilder.toString()); } public void write(Correlation correlation, final HttpRequest request, HttpResponse response) throws IOException { - Marker marker = createResponseMarker(correlation, response); + RequestResponseSingleFieldAppendingMarker marker = createResponseMarker(correlation, response); StringBuilder stringBuilder = new StringBuilder(256); - responseMessage(correlation, request, response, stringBuilder); + responseMessage(correlation, request, response, stringBuilder, marker != null ? marker.getTruncated() : -1); logConsumer.accept(marker, stringBuilder.toString()); } - protected Marker createResponseMarker(Correlation correlation, HttpResponse response) { + protected RequestResponseSingleFieldAppendingMarker createResponseMarker(Correlation correlation, HttpResponse response) { return null; } - protected Marker createRequestMarker(HttpRequest request) { + protected RequestResponseSingleFieldAppendingMarker createRequestMarker(HttpRequest request) { return null; } diff --git a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/AbstractSingleFieldAppendingMarker.java b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/AbstractSingleFieldAppendingMarker.java index 9e3a1338..c8a59c1a 100644 --- a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/AbstractSingleFieldAppendingMarker.java +++ b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/AbstractSingleFieldAppendingMarker.java @@ -9,15 +9,15 @@ import java.util.List; import java.util.Map; -public abstract class AbstractSingleFieldAppendingMarker extends SingleFieldAppendingMarker { +public abstract class AbstractSingleFieldAppendingMarker extends RequestResponseSingleFieldAppendingMarker { protected String contentType; protected Map> headers; protected String body; protected boolean wellformed; - public AbstractSingleFieldAppendingMarker(String markerName, T message, String body, boolean wellformed) { - super(markerName, "http"); + public AbstractSingleFieldAppendingMarker(String markerName, T message, String body, boolean wellformed, int truncated) { + super(markerName, "http", truncated); this.body = body; this.wellformed = wellformed; diff --git a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/LogLevelLogstashLogbackSink.java b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/LogLevelLogstashLogbackSink.java index aa351806..ca9a4e15 100644 --- a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/LogLevelLogstashLogbackSink.java +++ b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/LogLevelLogstashLogbackSink.java @@ -61,14 +61,14 @@ public LogLevelLogstashLogbackSink build() { } @Override - protected Marker newRequestSingleFieldAppendingMarker(HttpRequest request, String body, boolean wellformed) { - return new RequestSingleFieldAppendingMarker(request, body, wellformed); + protected RequestResponseSingleFieldAppendingMarker newRequestSingleFieldAppendingMarker(HttpRequest request, String body, boolean wellformed, int truncated) { + return new RequestSingleFieldAppendingMarker(request, body, wellformed, truncated); } @Override - protected Marker newResponseSingleFieldAppendingMarker(HttpResponse response, Duration duration, String body, - boolean wellformed) { - return new ResponseSingleFieldAppendingMarker(response, duration, body, wellformed); + protected RequestResponseSingleFieldAppendingMarker newResponseSingleFieldAppendingMarker(HttpResponse response, Duration duration, String body, + boolean wellformed, int truncated) { + return new ResponseSingleFieldAppendingMarker(response, duration, body, wellformed, truncated); } } diff --git a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/MessageComposer.java b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/MessageComposer.java index a1ac3e5e..1dba1a31 100644 --- a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/MessageComposer.java +++ b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/MessageComposer.java @@ -72,17 +72,32 @@ protected void constructMessage(HttpRequest request, StringBuilder messageBuilde } } - public void requestMessage(HttpRequest request, StringBuilder messageBuilder) throws IOException { + public void requestMessage(HttpRequest request, StringBuilder messageBuilder, int truncated) throws IOException { String method = request.getMethod(); if(method != null) { messageBuilder.append(method); messageBuilder.append(' '); } constructMessage(request, messageBuilder); + + if(truncated != -1) { + writeTruncated(messageBuilder, truncated); + } + } + + private static void writeTruncated(StringBuilder messageBuilder, int truncated) { + messageBuilder.append(" [truncated ~"); + if(truncated <= 1024) { + messageBuilder.append(truncated); + messageBuilder.append(" bytes)"); + } else { + messageBuilder.append(truncated / 1024); + messageBuilder.append("KB]"); + } } public void responseMessage(Correlation correlation, HttpRequest request, HttpResponse response, - StringBuilder messageBuilder) throws IOException { + StringBuilder messageBuilder, int truncated) throws IOException { messageBuilder.append(response.getStatus()); String reasonPhrase = response.getReasonPhrase(); @@ -99,5 +114,10 @@ public void responseMessage(Correlation correlation, HttpRequest request, HttpRe messageBuilder.append(duration.toMillis()); messageBuilder.append(" ms)"); } + + if(truncated != -1) { + writeTruncated(messageBuilder, truncated); + } + } } diff --git a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/RequestResponseSingleFieldAppendingMarker.java b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/RequestResponseSingleFieldAppendingMarker.java index a0e19bb1..0c61fa80 100644 --- a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/RequestResponseSingleFieldAppendingMarker.java +++ b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/RequestResponseSingleFieldAppendingMarker.java @@ -4,14 +4,24 @@ public abstract class RequestResponseSingleFieldAppendingMarker extends SingleFieldAppendingMarker { - protected final boolean truncated; + protected final int truncated; - public RequestResponseSingleFieldAppendingMarker(String markerName, String fieldName, boolean truncated) { + public RequestResponseSingleFieldAppendingMarker(String markerName, String fieldName, int truncated) { super(markerName, fieldName); this.truncated = truncated; } public boolean isTruncated() { + return truncated != -1; + } + + /** + * Number of bytes which were truncated + * + * @return count + */ + + public int getTruncated() { return truncated; } } diff --git a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/RequestSingleFieldAppendingMarker.java b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/RequestSingleFieldAppendingMarker.java index 5b3c5548..d1bebd11 100644 --- a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/RequestSingleFieldAppendingMarker.java +++ b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/RequestSingleFieldAppendingMarker.java @@ -22,8 +22,8 @@ public class RequestSingleFieldAppendingMarker extends AbstractSingleFieldAppend protected String scheme; protected Optional port; - public RequestSingleFieldAppendingMarker(HttpRequest request, String body, boolean wellformed) { - super(MARKER_NAME, request, body, wellformed); + public RequestSingleFieldAppendingMarker(HttpRequest request, String body, boolean wellformed, int truncated) { + super(MARKER_NAME, request, body, wellformed, truncated); } @Override diff --git a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/ResponseSingleFieldAppendingMarker.java b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/ResponseSingleFieldAppendingMarker.java index 4f9ff5b6..14d106e3 100644 --- a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/ResponseSingleFieldAppendingMarker.java +++ b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/ResponseSingleFieldAppendingMarker.java @@ -17,8 +17,8 @@ public class ResponseSingleFieldAppendingMarker extends AbstractSingleFieldAppen private String protocol; private int status; - public ResponseSingleFieldAppendingMarker(HttpResponse response, Duration duration, String body, boolean wellformed) { - super(MARKER_NAME, response, body, wellformed); + public ResponseSingleFieldAppendingMarker(HttpResponse response, Duration duration, String body, boolean wellformed, int truncated) { + super(MARKER_NAME, response, body, wellformed, truncated); this.duration = duration; } diff --git a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/ondemand/AbstractOndemandSingleFieldAppendingMarker.java b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/ondemand/AbstractOndemandSingleFieldAppendingMarker.java index 9fc77373..7e19fe2a 100644 --- a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/ondemand/AbstractOndemandSingleFieldAppendingMarker.java +++ b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/ondemand/AbstractOndemandSingleFieldAppendingMarker.java @@ -1,5 +1,6 @@ package no.entur.logging.cloud.logbook.ondemand; +import no.entur.logging.cloud.logbook.RequestResponseSingleFieldAppendingMarker; import tools.jackson.core.JsonGenerator; import net.logstash.logback.marker.SingleFieldAppendingMarker; import no.entur.logging.cloud.appender.scope.LoggingScopePostProcessing; @@ -10,7 +11,7 @@ import java.util.List; import java.util.Map; -public abstract class AbstractOndemandSingleFieldAppendingMarker extends SingleFieldAppendingMarker implements LoggingScopePostProcessing { +public abstract class AbstractOndemandSingleFieldAppendingMarker extends RequestResponseSingleFieldAppendingMarker implements LoggingScopePostProcessing { protected String contentType; protected Map> headers; @@ -18,8 +19,8 @@ public abstract class AbstractOndemandSingleFieldAppendingMarker logConsume client); } - public Marker createRequestMarker(HttpRequest request) { + public RequestResponseSingleFieldAppendingMarker createRequestMarker(HttpRequest request) { HttpMessageBodyWriter writer = EmptyHttpMessageBodyWriter.INSTANCE; + int truncated = -1; if (ContentType.isJsonMediaType(request.getContentType())) { try { byte[] body = request.getBody(); @@ -78,6 +74,7 @@ public Marker createRequestMarker(HttpRequest request) { if (body.length < maxBodySize) { writer = new LocalHttpMessageBodyWriter(body); } else { + truncated = body.length - maxBodySize; writer = new MaxSizeLocalHttpMessageBodyWriter(jsonMapper, body, maxBodySize); } } else { @@ -88,6 +85,7 @@ public Marker createRequestMarker(HttpRequest request) { if (body.length < maxBodySize) { writer = new RemoteHttpMessageBodyWriter(jsonMapper, body, httpMessageStateSupplier); } else { + truncated = body.length - maxBodySize; writer = new MaxSizeRemoteHttpMessageBodyWriter(jsonMapper, body, maxSize, httpMessageStateSupplier); } @@ -96,6 +94,7 @@ public Marker createRequestMarker(HttpRequest request) { if (body.length < maxBodySize) { writer = new LocalHttpMessageBodyWriter(body); } else { + truncated = body.length - maxBodySize; writer = new MaxSizeLocalHttpMessageBodyWriter(jsonMapper, body, maxBodySize); } } @@ -109,8 +108,10 @@ public Marker createRequestMarker(HttpRequest request) { String bodyAsString = request.getBodyAsString(); if (bodyAsString != null && bodyAsString.length() > 0) { if (bodyAsString.length() > maxBodySize) { - String truncated = bodyAsString.substring(0, maxBodySize); - writer = new StringHttpMessageBodyWriter(truncated); + truncated = bodyAsString.length() - maxBodySize; + + String truncatedString = bodyAsString.substring(0, maxBodySize); + writer = new StringHttpMessageBodyWriter(truncatedString); } else { writer = new StringHttpMessageBodyWriter(bodyAsString); } @@ -120,13 +121,14 @@ public Marker createRequestMarker(HttpRequest request) { } } - return new RequestOndemandSingleFieldAppendingMarker(request, writer); + return new RequestOndemandSingleFieldAppendingMarker(request, writer, truncated); } - public Marker createResponseMarker(Correlation correlation, HttpResponse response) { + public RequestResponseSingleFieldAppendingMarker createResponseMarker(Correlation correlation, HttpResponse response) { HttpMessageBodyWriter writer = EmptyHttpMessageBodyWriter.INSTANCE; + int truncated = -1; if (ContentType.isJsonMediaType(response.getContentType())) { try { byte[] body = response.getBody(); @@ -136,6 +138,7 @@ public Marker createResponseMarker(Correlation correlation, HttpResponse respons if (body.length < maxBodySize) { writer = new LocalHttpMessageBodyWriter(body); } else { + truncated = body.length - maxBodySize; writer = new MaxSizeLocalHttpMessageBodyWriter(jsonMapper, body, maxBodySize); } } else { @@ -146,6 +149,7 @@ public Marker createResponseMarker(Correlation correlation, HttpResponse respons if (body.length < maxBodySize) { writer = new RemoteHttpMessageBodyWriter(jsonMapper, body, httpMessageStateSupplier); } else { + truncated = body.length - maxBodySize; writer = new MaxSizeRemoteHttpMessageBodyWriter(jsonMapper, body, maxSize, httpMessageStateSupplier); } @@ -154,6 +158,7 @@ public Marker createResponseMarker(Correlation correlation, HttpResponse respons if (body.length < maxBodySize) { writer = new LocalHttpMessageBodyWriter(body); } else { + truncated = body.length - maxBodySize; writer = new MaxSizeLocalHttpMessageBodyWriter(jsonMapper, body, maxBodySize); } } @@ -167,8 +172,10 @@ public Marker createResponseMarker(Correlation correlation, HttpResponse respons String bodyAsString = response.getBodyAsString(); if (bodyAsString != null && bodyAsString.length() > 0) { if (bodyAsString.length() > maxBodySize) { - String truncated = bodyAsString.substring(0, maxBodySize); - writer = new StringHttpMessageBodyWriter(truncated); + truncated = bodyAsString.length() - maxBodySize; + + String truncatedString = bodyAsString.substring(0, maxBodySize); + writer = new StringHttpMessageBodyWriter(truncatedString); } else { writer = new StringHttpMessageBodyWriter(bodyAsString); } @@ -178,7 +185,7 @@ public Marker createResponseMarker(Correlation correlation, HttpResponse respons } } - return new ResponseOndemandSingleFieldAppendingMarker(response, correlation.getDuration(), writer); + return new ResponseOndemandSingleFieldAppendingMarker(response, correlation.getDuration(), writer, truncated); } } diff --git a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/ondemand/RequestOndemandSingleFieldAppendingMarker.java b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/ondemand/RequestOndemandSingleFieldAppendingMarker.java index 5112cfb1..6017c671 100644 --- a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/ondemand/RequestOndemandSingleFieldAppendingMarker.java +++ b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/ondemand/RequestOndemandSingleFieldAppendingMarker.java @@ -23,8 +23,8 @@ public class RequestOndemandSingleFieldAppendingMarker extends AbstractOndemandS protected String scheme; protected Optional port; - public RequestOndemandSingleFieldAppendingMarker(HttpRequest request, HttpMessageBodyWriter httpMessageBodyWriter) { - super(MARKER_NAME, request, httpMessageBodyWriter); + public RequestOndemandSingleFieldAppendingMarker(HttpRequest request, HttpMessageBodyWriter httpMessageBodyWriter, int truncated) { + super(MARKER_NAME, request, httpMessageBodyWriter, truncated); } @Override diff --git a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/ondemand/ResponseOndemandSingleFieldAppendingMarker.java b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/ondemand/ResponseOndemandSingleFieldAppendingMarker.java index 5e22ea5a..501db80a 100644 --- a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/ondemand/ResponseOndemandSingleFieldAppendingMarker.java +++ b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/ondemand/ResponseOndemandSingleFieldAppendingMarker.java @@ -5,7 +5,6 @@ import org.zalando.logbook.HttpResponse; import org.zalando.logbook.Origin; -import java.io.IOException; import java.time.Duration; import java.util.Locale; @@ -18,8 +17,8 @@ public class ResponseOndemandSingleFieldAppendingMarker extends AbstractOndemand private String protocol; private int status; - public ResponseOndemandSingleFieldAppendingMarker(HttpResponse response, Duration duration, HttpMessageBodyWriter httpMessageBodyWriter) { - super(MARKER_NAME, response, httpMessageBodyWriter); + public ResponseOndemandSingleFieldAppendingMarker(HttpResponse response, Duration duration, HttpMessageBodyWriter httpMessageBodyWriter, int truncated) { + super(MARKER_NAME, response, httpMessageBodyWriter, truncated); this.duration = duration; } diff --git a/request-response/logbook/src/test/java/no/entur/logging/cloud/logbook/AbstractLogLevelLogstashLogbackSinkTest.java b/request-response/logbook/src/test/java/no/entur/logging/cloud/logbook/AbstractLogLevelLogstashLogbackSinkTest.java index dbdd8b41..f7800442 100644 --- a/request-response/logbook/src/test/java/no/entur/logging/cloud/logbook/AbstractLogLevelLogstashLogbackSinkTest.java +++ b/request-response/logbook/src/test/java/no/entur/logging/cloud/logbook/AbstractLogLevelLogstashLogbackSinkTest.java @@ -26,13 +26,13 @@ public MockLogLevelLogstashLogbackSink(BiConsumer logConsumer, B } @Override - protected Marker newRequestSingleFieldAppendingMarker(HttpRequest request, String body, boolean wellformed) { - return mock(Marker.class); + protected RequestResponseSingleFieldAppendingMarker newRequestSingleFieldAppendingMarker(HttpRequest request, String body, boolean wellformed, int truncated) { + return mock(RequestResponseSingleFieldAppendingMarker.class); } @Override - protected Marker newResponseSingleFieldAppendingMarker(HttpResponse response, Duration duration, String body, boolean wellformed) { - return mock(Marker.class); + protected RequestResponseSingleFieldAppendingMarker newResponseSingleFieldAppendingMarker(HttpResponse response, Duration duration, String body, boolean wellformed, int truncated) { + return mock(RequestResponseSingleFieldAppendingMarker.class); } } @@ -58,7 +58,7 @@ public void testDoesNotPrintUnknownMimetypes() { when(request.getContentType()).thenReturn("application/unknown"); spy.createRequestMarker(request); - verify(spy).newRequestSingleFieldAppendingMarker(request, null, false); + verify(spy).newRequestSingleFieldAppendingMarker(request, null, false, -1); } @Test @@ -73,7 +73,7 @@ public void testPrintsRemoteJsonMimetype() throws IOException { when(request.getOrigin()).thenReturn(Origin.REMOTE); spy.createRequestMarker(request); - verify(spy).newRequestSingleFieldAppendingMarker(eq(request), anyString(), eq(true)); + verify(spy).newRequestSingleFieldAppendingMarker(eq(request), anyString(), eq(true), eq(-1)); } @Test @@ -88,7 +88,7 @@ public void testPrintsRemoteInvalidJsonMimetype() throws IOException { when(request.getOrigin()).thenReturn(Origin.REMOTE); spy.createRequestMarker(request); - verify(spy).newRequestSingleFieldAppendingMarker(eq(request), anyString(), eq(false)); + verify(spy).newRequestSingleFieldAppendingMarker(eq(request), anyString(), eq(false), eq(-1)); } @Test @@ -103,7 +103,7 @@ public void testPrintsLocalJsonMimetype() throws IOException { when(request.getOrigin()).thenReturn(Origin.LOCAL); spy.createRequestMarker(request); - verify(spy).newRequestSingleFieldAppendingMarker(eq(request), anyString(), eq(true)); + verify(spy).newRequestSingleFieldAppendingMarker(eq(request), anyString(), eq(true), eq(-1)); } @Test @@ -125,7 +125,7 @@ public void testPrintsTooLargeLocalJsonMimetype() throws IOException { when(request.getOrigin()).thenReturn(Origin.LOCAL); spy.createRequestMarker(request); - verify(spy).newRequestSingleFieldAppendingMarker(eq(request), anyString(), eq(true)); + verify(spy).newRequestSingleFieldAppendingMarker(eq(request), anyString(), eq(true), eq(1026)); } @Test @@ -147,7 +147,7 @@ public void testPrintsTooLargeRemoteJsonMimetype() throws IOException { when(request.getOrigin()).thenReturn(Origin.REMOTE); spy.createRequestMarker(request); - verify(spy).newRequestSingleFieldAppendingMarker(eq(request), eq("{\"Logger\":\"Max body size of 1024 reached, rest of the document has been filtered.\"}"), eq(true)); + verify(spy).newRequestSingleFieldAppendingMarker(eq(request), eq("{\"Logger\":\"Max body size of 1024 reached, rest of the document has been filtered.\"}"), eq(true), eq(1026)); } @Test @@ -169,7 +169,7 @@ public void testPrintsTooLargeRemoteInvalidJsonMimetype() throws IOException { when(request.getOrigin()).thenReturn(Origin.REMOTE); spy.createRequestMarker(request); - verify(spy).newRequestSingleFieldAppendingMarker(eq(request), eq(json.substring(0, 1024)), eq(false)); + verify(spy).newRequestSingleFieldAppendingMarker(eq(request), eq(json.substring(0, 1024)), eq(false), eq(1026)); } private MockLogLevelLogstashLogbackSink createSink() { From f344da481fa1c17c0b06372d0d260b3a29eab7da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Skj=C3=B8lberg?= Date: Wed, 29 Apr 2026 16:36:09 +0200 Subject: [PATCH 3/9] Adjust --- .../entur/example/web/WebLoggingFormatWithBigResponsesTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/gcp-web-example/src/test/java/org/entur/example/web/WebLoggingFormatWithBigResponsesTest.java b/examples/gcp-web-example/src/test/java/org/entur/example/web/WebLoggingFormatWithBigResponsesTest.java index 956b869c..5a5482d8 100644 --- a/examples/gcp-web-example/src/test/java/org/entur/example/web/WebLoggingFormatWithBigResponsesTest.java +++ b/examples/gcp-web-example/src/test/java/org/entur/example/web/WebLoggingFormatWithBigResponsesTest.java @@ -44,8 +44,6 @@ public void useMachineReadableJsonEncoder() throws InterruptedException { try (CompositeConsoleOutputControlClosable c = CompositeConsoleOutputControl.useMachineReadableJsonEncoder()) { ResponseEntity response = restTemplate.getForEntity("/api/document/some/bigResponse", String.class); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); - - Thread.sleep(1000); } } From b9ff8a526a7aa5919447316f1c6aaee5a6682ece Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Skj=C3=B8lberg?= Date: Wed, 29 Apr 2026 16:38:33 +0200 Subject: [PATCH 4/9] Adjust --- .../OndemandLogLevelLogstashLogbackSink.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/ondemand/OndemandLogLevelLogstashLogbackSink.java b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/ondemand/OndemandLogLevelLogstashLogbackSink.java index e7887d0e..9e65f882 100644 --- a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/ondemand/OndemandLogLevelLogstashLogbackSink.java +++ b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/ondemand/OndemandLogLevelLogstashLogbackSink.java @@ -74,7 +74,7 @@ public RequestResponseSingleFieldAppendingMarker createRequestMarker(HttpRequest if (body.length < maxBodySize) { writer = new LocalHttpMessageBodyWriter(body); } else { - truncated = body.length - maxBodySize; + truncated = body.length - maxBodySize; writer = new MaxSizeLocalHttpMessageBodyWriter(jsonMapper, body, maxBodySize); } } else { @@ -85,7 +85,7 @@ public RequestResponseSingleFieldAppendingMarker createRequestMarker(HttpRequest if (body.length < maxBodySize) { writer = new RemoteHttpMessageBodyWriter(jsonMapper, body, httpMessageStateSupplier); } else { - truncated = body.length - maxBodySize; + truncated = body.length - maxBodySize; writer = new MaxSizeRemoteHttpMessageBodyWriter(jsonMapper, body, maxSize, httpMessageStateSupplier); } @@ -94,7 +94,7 @@ public RequestResponseSingleFieldAppendingMarker createRequestMarker(HttpRequest if (body.length < maxBodySize) { writer = new LocalHttpMessageBodyWriter(body); } else { - truncated = body.length - maxBodySize; + truncated = body.length - maxBodySize; writer = new MaxSizeLocalHttpMessageBodyWriter(jsonMapper, body, maxBodySize); } } @@ -108,7 +108,7 @@ public RequestResponseSingleFieldAppendingMarker createRequestMarker(HttpRequest String bodyAsString = request.getBodyAsString(); if (bodyAsString != null && bodyAsString.length() > 0) { if (bodyAsString.length() > maxBodySize) { - truncated = bodyAsString.length() - maxBodySize; + truncated = bodyAsString.length() - maxBodySize; String truncatedString = bodyAsString.substring(0, maxBodySize); writer = new StringHttpMessageBodyWriter(truncatedString); @@ -138,7 +138,7 @@ public RequestResponseSingleFieldAppendingMarker createResponseMarker(Correlatio if (body.length < maxBodySize) { writer = new LocalHttpMessageBodyWriter(body); } else { - truncated = body.length - maxBodySize; + truncated = body.length - maxBodySize; writer = new MaxSizeLocalHttpMessageBodyWriter(jsonMapper, body, maxBodySize); } } else { @@ -149,7 +149,7 @@ public RequestResponseSingleFieldAppendingMarker createResponseMarker(Correlatio if (body.length < maxBodySize) { writer = new RemoteHttpMessageBodyWriter(jsonMapper, body, httpMessageStateSupplier); } else { - truncated = body.length - maxBodySize; + truncated = body.length - maxBodySize; writer = new MaxSizeRemoteHttpMessageBodyWriter(jsonMapper, body, maxSize, httpMessageStateSupplier); } @@ -158,7 +158,7 @@ public RequestResponseSingleFieldAppendingMarker createResponseMarker(Correlatio if (body.length < maxBodySize) { writer = new LocalHttpMessageBodyWriter(body); } else { - truncated = body.length - maxBodySize; + truncated = body.length - maxBodySize; writer = new MaxSizeLocalHttpMessageBodyWriter(jsonMapper, body, maxBodySize); } } @@ -172,7 +172,7 @@ public RequestResponseSingleFieldAppendingMarker createResponseMarker(Correlatio String bodyAsString = response.getBodyAsString(); if (bodyAsString != null && bodyAsString.length() > 0) { if (bodyAsString.length() > maxBodySize) { - truncated = bodyAsString.length() - maxBodySize; + truncated = bodyAsString.length() - maxBodySize; String truncatedString = bodyAsString.substring(0, maxBodySize); writer = new StringHttpMessageBodyWriter(truncatedString); From 74dc3e26cc81ebe8c2c378bc9738259da56afe1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Skj=C3=B8lberg?= Date: Wed, 29 Apr 2026 16:53:09 +0200 Subject: [PATCH 5/9] QA --- .../logbook/logbook/test/PrettyPrintingSink.java | 8 ++++---- ...yPrintingOndemandLogLevelLogstashLogbackSink.java | 8 ++++---- .../logbook/AbstractLogLevelLogstashLogbackSink.java | 3 ++- .../entur/logging/cloud/logbook/MessageComposer.java | 2 +- .../OndemandLogLevelLogstashLogbackSink.java | 12 ++++++------ 5 files changed, 17 insertions(+), 16 deletions(-) diff --git a/request-response/logbook-test/src/main/java/no/entur/logging/cloud/logbook/logbook/test/PrettyPrintingSink.java b/request-response/logbook-test/src/main/java/no/entur/logging/cloud/logbook/logbook/test/PrettyPrintingSink.java index fb566b22..52a67192 100644 --- a/request-response/logbook-test/src/main/java/no/entur/logging/cloud/logbook/logbook/test/PrettyPrintingSink.java +++ b/request-response/logbook-test/src/main/java/no/entur/logging/cloud/logbook/logbook/test/PrettyPrintingSink.java @@ -84,8 +84,8 @@ public PrettyPrintingSink(BooleanSupplier logLevelEnabled, BiConsumer 0) { if (request.getOrigin() == Origin.LOCAL) { // trust our own data to be wellformed - if (body.length < maxBodySize) { + if (body.length <= maxBodySize) { writer = new PrettyPrintingLocalHttpMessageBodyWriter(body); } else { truncated = body.length - maxBodySize; @@ -94,7 +94,7 @@ public RequestResponseSingleFieldAppendingMarker createRequestMarker(HttpRequest } } else { HttpMessageStateSupplier httpMessageStateSupplier = requestHttpMessageStateSupplierSource.get(); - if (body.length < maxBodySize) { + if (body.length <= maxBodySize) { writer = new PrettyPrintingRemoteHttpMessageBodyWriter(jsonMapper, body, httpMessageStateSupplier); } else { truncated = body.length - maxBodySize; @@ -140,7 +140,7 @@ public RequestResponseSingleFieldAppendingMarker createResponseMarker(Correlatio if (body != null && body.length > 0) { if (response.getOrigin() == Origin.LOCAL) { // trust our own data to be wellformed - if (body.length < maxBodySize) { + if (body.length <= maxBodySize) { writer = new PrettyPrintingLocalHttpMessageBodyWriter(body); } else { truncated = body.length - maxBodySize; @@ -151,7 +151,7 @@ public RequestResponseSingleFieldAppendingMarker createResponseMarker(Correlatio } else { HttpMessageStateSupplier httpMessageStateSupplier = responseHttpMessageStateSupplierSource .get(); - if (body.length < maxBodySize) { + if (body.length <= maxBodySize) { writer = new PrettyPrintingRemoteHttpMessageBodyWriter(jsonMapper, body, httpMessageStateSupplier); } else { diff --git a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/AbstractLogLevelLogstashLogbackSink.java b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/AbstractLogLevelLogstashLogbackSink.java index 93b9c010..c0f27f5a 100644 --- a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/AbstractLogLevelLogstashLogbackSink.java +++ b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/AbstractLogLevelLogstashLogbackSink.java @@ -60,8 +60,9 @@ public RequestResponseSingleFieldAppendingMarker createRequestMarker(HttpRequest if (!isJson || !smellsLikeJson(bodyAsString)) { if (bodyAsString.length() > maxSize) { // TODO add filter + int truncated = bodyAsString.length() - maxSize; String truncatedBody = bodyAsString.substring(0, maxSize); - return newRequestSingleFieldAppendingMarker(request, truncatedBody, false, -1); + return newRequestSingleFieldAppendingMarker(request, truncatedBody, false, truncated); } return newRequestSingleFieldAppendingMarker(request, bodyAsString, false, -1); } diff --git a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/MessageComposer.java b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/MessageComposer.java index 1dba1a31..4d3baa47 100644 --- a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/MessageComposer.java +++ b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/MessageComposer.java @@ -89,7 +89,7 @@ private static void writeTruncated(StringBuilder messageBuilder, int truncated) messageBuilder.append(" [truncated ~"); if(truncated <= 1024) { messageBuilder.append(truncated); - messageBuilder.append(" bytes)"); + messageBuilder.append(" bytes]"); } else { messageBuilder.append(truncated / 1024); messageBuilder.append("KB]"); diff --git a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/ondemand/OndemandLogLevelLogstashLogbackSink.java b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/ondemand/OndemandLogLevelLogstashLogbackSink.java index 9e65f882..6689e82f 100644 --- a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/ondemand/OndemandLogLevelLogstashLogbackSink.java +++ b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/ondemand/OndemandLogLevelLogstashLogbackSink.java @@ -71,7 +71,7 @@ public RequestResponseSingleFieldAppendingMarker createRequestMarker(HttpRequest if (body != null && body.length > 0) { if (request.getOrigin() == Origin.LOCAL) { // trust our own data to be wellformed and not pretty-printed - if (body.length < maxBodySize) { + if (body.length <= maxBodySize) { writer = new LocalHttpMessageBodyWriter(body); } else { truncated = body.length - maxBodySize; @@ -82,7 +82,7 @@ public RequestResponseSingleFieldAppendingMarker createRequestMarker(HttpRequest if (verify) { HttpMessageStateSupplier httpMessageStateSupplier = requestHttpMessageStateSupplierSource .get(); - if (body.length < maxBodySize) { + if (body.length <= maxBodySize) { writer = new RemoteHttpMessageBodyWriter(jsonMapper, body, httpMessageStateSupplier); } else { truncated = body.length - maxBodySize; @@ -91,7 +91,7 @@ public RequestResponseSingleFieldAppendingMarker createRequestMarker(HttpRequest } } else { // trust contents is well formed - if (body.length < maxBodySize) { + if (body.length <= maxBodySize) { writer = new LocalHttpMessageBodyWriter(body); } else { truncated = body.length - maxBodySize; @@ -135,7 +135,7 @@ public RequestResponseSingleFieldAppendingMarker createResponseMarker(Correlatio if (body != null && body.length > 0) { if (response.getOrigin() == Origin.LOCAL) { // trust our own data to be wellformed and not pretty-printed - if (body.length < maxBodySize) { + if (body.length <= maxBodySize) { writer = new LocalHttpMessageBodyWriter(body); } else { truncated = body.length - maxBodySize; @@ -146,7 +146,7 @@ public RequestResponseSingleFieldAppendingMarker createResponseMarker(Correlatio if (verify) { HttpMessageStateSupplier httpMessageStateSupplier = responseHttpMessageStateSupplierSource .get(); - if (body.length < maxBodySize) { + if (body.length <= maxBodySize) { writer = new RemoteHttpMessageBodyWriter(jsonMapper, body, httpMessageStateSupplier); } else { truncated = body.length - maxBodySize; @@ -155,7 +155,7 @@ public RequestResponseSingleFieldAppendingMarker createResponseMarker(Correlatio } } else { // trust contents is well formed - if (body.length < maxBodySize) { + if (body.length <= maxBodySize) { writer = new LocalHttpMessageBodyWriter(body); } else { truncated = body.length - maxBodySize; From 9b6c16ef09a4e8700285cab8c26b9f5abcfdd6eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Skj=C3=B8lberg?= Date: Thu, 30 Apr 2026 08:21:08 +0200 Subject: [PATCH 6/9] Update examples/gcp-web-without-test-artifacts-example/src/main/java/org/entur/example/web/rest/DocumentEndpoint.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../example/web/rest/DocumentEndpoint.java | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/examples/gcp-web-without-test-artifacts-example/src/main/java/org/entur/example/web/rest/DocumentEndpoint.java b/examples/gcp-web-without-test-artifacts-example/src/main/java/org/entur/example/web/rest/DocumentEndpoint.java index b02625c7..82888fac 100644 --- a/examples/gcp-web-without-test-artifacts-example/src/main/java/org/entur/example/web/rest/DocumentEndpoint.java +++ b/examples/gcp-web-without-test-artifacts-example/src/main/java/org/entur/example/web/rest/DocumentEndpoint.java @@ -52,19 +52,16 @@ ResponseEntity bigResponse() throws IOException { CharArrayWriter writer = new CharArrayWriter(); - tools.jackson.core.JsonGenerator generator = factory.createGenerator(writer); - - generator.writeStartObject(); - generator.writeStringProperty("start", "here"); - for(int i = 0; i < 10; i++) { - generator.writeStringProperty("longValue" + i, generateLongString(25*1024)); + try (tools.jackson.core.JsonGenerator generator = factory.createGenerator(writer)) { + generator.writeStartObject(); + generator.writeStringProperty("start", "here"); + for(int i = 0; i < 10; i++) { + generator.writeStringProperty("longValue" + i, generateLongString(25*1024)); + } + generator.writeStringProperty("longValue", generateLongString(192*1024)); + generator.writeStringProperty("end", "here"); + generator.writeEndObject(); } - generator.writeStringProperty("longValue", generateLongString(192*1024)); - generator.writeStringProperty("end", "here"); - generator.writeEndObject(); - - generator.flush(); - return new ResponseEntity<>(writer.toString(), HttpStatus.OK); } From 9f6b3b7435b321c04699fb5be91a7e81ec5d272b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Skj=C3=B8lberg?= Date: Thu, 30 Apr 2026 09:45:49 +0200 Subject: [PATCH 7/9] adjust javadoc --- .../logbook/RequestResponseSingleFieldAppendingMarker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/RequestResponseSingleFieldAppendingMarker.java b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/RequestResponseSingleFieldAppendingMarker.java index 0c61fa80..7b5e60fd 100644 --- a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/RequestResponseSingleFieldAppendingMarker.java +++ b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/RequestResponseSingleFieldAppendingMarker.java @@ -16,7 +16,7 @@ public boolean isTruncated() { } /** - * Number of bytes which were truncated + * Number of bytes or chars which were truncated * * @return count */ From c34d80afc8849301cfb03f031ca2bddee5455237 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Skj=C3=B8lberg?= Date: Thu, 30 Apr 2026 09:50:55 +0200 Subject: [PATCH 8/9] Adjust --- .../PrettyPrintingOndemandLogLevelLogstashLogbackSink.java | 2 +- .../logbook/ondemand/OndemandLogLevelLogstashLogbackSink.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/request-response/logbook-test/src/main/java/no/entur/logging/cloud/logbook/logbook/test/ondemand/PrettyPrintingOndemandLogLevelLogstashLogbackSink.java b/request-response/logbook-test/src/main/java/no/entur/logging/cloud/logbook/logbook/test/ondemand/PrettyPrintingOndemandLogLevelLogstashLogbackSink.java index 802d9f9d..1b61044a 100644 --- a/request-response/logbook-test/src/main/java/no/entur/logging/cloud/logbook/logbook/test/ondemand/PrettyPrintingOndemandLogLevelLogstashLogbackSink.java +++ b/request-response/logbook-test/src/main/java/no/entur/logging/cloud/logbook/logbook/test/ondemand/PrettyPrintingOndemandLogLevelLogstashLogbackSink.java @@ -99,7 +99,7 @@ public RequestResponseSingleFieldAppendingMarker createRequestMarker(HttpRequest } else { truncated = body.length - maxBodySize; - writer = new PrettyPrintingRemoteMaxSizeHttpMessageBodyWriter(jsonMapper, body, maxSize, + writer = new PrettyPrintingRemoteMaxSizeHttpMessageBodyWriter(jsonMapper, body, maxBodySize, httpMessageStateSupplier); } } diff --git a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/ondemand/OndemandLogLevelLogstashLogbackSink.java b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/ondemand/OndemandLogLevelLogstashLogbackSink.java index 6689e82f..c9100972 100644 --- a/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/ondemand/OndemandLogLevelLogstashLogbackSink.java +++ b/request-response/logbook/src/main/java/no/entur/logging/cloud/logbook/ondemand/OndemandLogLevelLogstashLogbackSink.java @@ -150,7 +150,7 @@ public RequestResponseSingleFieldAppendingMarker createResponseMarker(Correlatio writer = new RemoteHttpMessageBodyWriter(jsonMapper, body, httpMessageStateSupplier); } else { truncated = body.length - maxBodySize; - writer = new MaxSizeRemoteHttpMessageBodyWriter(jsonMapper, body, maxSize, + writer = new MaxSizeRemoteHttpMessageBodyWriter(jsonMapper, body, maxBodySize, httpMessageStateSupplier); } } else { From 66a9f22ec0c6a9011009773ebee5b08ea5fadef7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Skj=C3=B8lberg?= Date: Thu, 30 Apr 2026 09:57:35 +0200 Subject: [PATCH 9/9] Update examples/gcp-web-without-test-artifacts-example/src/test/java/org/entur/example/web/WebLoggingFormatWithBigResponsesTest.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../entur/example/web/WebLoggingFormatWithBigResponsesTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/gcp-web-without-test-artifacts-example/src/test/java/org/entur/example/web/WebLoggingFormatWithBigResponsesTest.java b/examples/gcp-web-without-test-artifacts-example/src/test/java/org/entur/example/web/WebLoggingFormatWithBigResponsesTest.java index 8893fbe1..c5511f8f 100644 --- a/examples/gcp-web-without-test-artifacts-example/src/test/java/org/entur/example/web/WebLoggingFormatWithBigResponsesTest.java +++ b/examples/gcp-web-without-test-artifacts-example/src/test/java/org/entur/example/web/WebLoggingFormatWithBigResponsesTest.java @@ -9,7 +9,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import static org.assertj.core.api.Assertions.assertThat; +import static com.google.common.truth.Truth.assertThat; @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) @AutoConfigureTestRestTemplate