From 24697530f31a6ca08a9c62c2f2ad938f30546c6b Mon Sep 17 00:00:00 2001 From: eyalkoren <41850454+eyalkoren@users.noreply.github.com> Date: Tue, 26 Apr 2022 17:30:16 +0300 Subject: [PATCH] Remove more serialization allocations --- .../co/elastic/logging/EcsJsonSerializer.java | 26 ++++++++----------- .../java/co/elastic/logging/JsonUtils.java | 10 ++++++- .../logging/EcsJsonSerializerTest.java | 18 +++++++++++++ 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/ecs-logging-core/src/main/java/co/elastic/logging/EcsJsonSerializer.java b/ecs-logging-core/src/main/java/co/elastic/logging/EcsJsonSerializer.java index 1a317d00..deb77a15 100644 --- a/ecs-logging-core/src/main/java/co/elastic/logging/EcsJsonSerializer.java +++ b/ecs-logging-core/src/main/java/co/elastic/logging/EcsJsonSerializer.java @@ -279,11 +279,9 @@ private static void formatStackTraceAsArray(StringBuilder builder, CharSequence continue; } - // append line - CharSequence match = stackTrace.subSequence(index, matcher.start()); - builder.append("\t\""); - JsonUtils.quoteAsString(match, builder); - builder.append("\","); + // append non-last line + appendStackTraceLine(builder, stackTrace, index, start); + builder.append(','); builder.append(NEW_LINE); index = end; } while (matcher.find()); @@ -291,22 +289,20 @@ private static void formatStackTraceAsArray(StringBuilder builder, CharSequence int length = stackTrace.length(); if (index < length) { // append remaining line - CharSequence remaining = stackTrace.subSequence(index, length); - builder.append("\t\""); - JsonUtils.quoteAsString(remaining, builder); - builder.append("\""); + appendStackTraceLine(builder, stackTrace, index, length); } - - removeIfEndsWith(builder, NEW_LINE); - removeIfEndsWith(builder, ","); } else { // no newlines found, add entire stack trace as single element - builder.append("\t\""); - JsonUtils.quoteAsString(stackTrace, builder); - builder.append("\""); + appendStackTraceLine(builder, stackTrace, 0, stackTrace.length()); } } + private static void appendStackTraceLine(StringBuilder builder, CharSequence stackTrace, int start, int end) { + builder.append("\t\""); + JsonUtils.quoteAsString(stackTrace, start, end, builder); + builder.append("\""); + } + public static void removeIfEndsWith(StringBuilder sb, String ending) { if (endsWith(sb, ending)) { sb.setLength(sb.length() - ending.length()); diff --git a/ecs-logging-core/src/main/java/co/elastic/logging/JsonUtils.java b/ecs-logging-core/src/main/java/co/elastic/logging/JsonUtils.java index d2d696c6..fc53a8ca 100644 --- a/ecs-logging-core/src/main/java/co/elastic/logging/JsonUtils.java +++ b/ecs-logging-core/src/main/java/co/elastic/logging/JsonUtils.java @@ -58,13 +58,21 @@ public final class JsonUtils { } public static void quoteAsString(CharSequence content, StringBuilder sb) { + if (content == null) { + sb.append("null"); + return; + } + quoteAsString(content, 0, content.length(), sb); + } + + public static void quoteAsString(CharSequence content, int start, int end, StringBuilder sb) { if (content == null) { sb.append("null"); return; } final int[] escCodes = sOutputEscapes128; final int escLen = escCodes.length; - for (int i = 0, len = content.length(); i < len; ++i) { + for (int i = start; i < end; ++i) { char c = content.charAt(i); if (c >= escLen || escCodes[c] == 0) { sb.append(c); diff --git a/ecs-logging-core/src/test/java/co/elastic/logging/EcsJsonSerializerTest.java b/ecs-logging-core/src/test/java/co/elastic/logging/EcsJsonSerializerTest.java index 73f088d2..ec851e8a 100644 --- a/ecs-logging-core/src/test/java/co/elastic/logging/EcsJsonSerializerTest.java +++ b/ecs-logging-core/src/test/java/co/elastic/logging/EcsJsonSerializerTest.java @@ -148,13 +148,31 @@ void serializeExceptionWithStackTraceAsArray() throws JsonProcessingException { jsonBuilder.append('}'); JsonNode jsonNode = objectMapper.readTree(jsonBuilder.toString()); + System.out.println(jsonNode.toPrettyString()); assertThat(jsonNode.get(ERROR_TYPE).textValue()).isEqualTo("className"); assertThat(jsonNode.get(ERROR_STACK_TRACE).isArray()).isTrue(); + assertThat(jsonNode.get(ERROR_STACK_TRACE).size()).isEqualTo(2); assertThat(jsonNode.get(ERROR_STACK_TRACE).get(0).textValue()).isEqualTo("stacktrace"); assertThat(jsonNode.get(ERROR_STACK_TRACE).get(1).textValue()).isEqualTo("caused by error"); assertThat(jsonNode.get(ERROR_MESSAGE).textValue()).isEqualTo("message"); } + @Test + void serializeExceptionWithSingleLineStackTraceAsArray() throws JsonProcessingException { + StringBuilder jsonBuilder = new StringBuilder(); + jsonBuilder.append('{'); + EcsJsonSerializer.serializeException(jsonBuilder, "className", "message", "caused by error", true); + jsonBuilder.append('}'); + System.out.println(jsonBuilder); + JsonNode jsonNode = objectMapper.readTree(jsonBuilder.toString()); + System.out.println(jsonNode.toPrettyString()); + assertThat(jsonNode.get(ERROR_TYPE).textValue()).isEqualTo("className"); + assertThat(jsonNode.get(ERROR_STACK_TRACE).isArray()).isTrue(); + assertThat(jsonNode.get(ERROR_STACK_TRACE).size()).isEqualTo(1); + assertThat(jsonNode.get(ERROR_STACK_TRACE).get(0).textValue()).isEqualTo("caused by error"); + assertThat(jsonNode.get(ERROR_MESSAGE).textValue()).isEqualTo("message"); + } + @Test void serializeExceptionWithNullMessage() throws JsonProcessingException { StringBuilder jsonBuilder = new StringBuilder();