From 0b1fb5d65588f759b209f696a736795f73c5c0e6 Mon Sep 17 00:00:00 2001 From: "Zellner, Markus (GfK)" Date: Fri, 29 Apr 2022 08:29:45 +0200 Subject: [PATCH 1/4] Add service.Environment as dedicated field --- docs/tab-widgets/ecs-encoder.asciidoc | 33 +++++++++++++++++-- .../co/elastic/logging/EcsJsonSerializer.java | 8 +++++ .../logging/AbstractEcsLoggingTest.java | 1 + .../logging/EcsJsonSerializerTest.java | 3 ++ .../jboss/logmanager/EcsFormatter.java | 9 ++++- .../jboss/logmanager/EcsFormatterTest.java | 4 +-- .../jboss/logmanager/JBossLogManagerTest.java | 1 + .../co/elastic/logging/jul/EcsFormatter.java | 8 +++++ .../elastic/logging/jul/JulLoggingTest.java | 1 + .../src/test/resources/logging.properties | 1 + .../co/elastic/logging/log4j/EcsLayout.java | 7 ++++ .../logging/log4j/Log4jEcsLayoutTest.java | 1 + log4j-ecs-layout/src/test/resources/log4j.xml | 1 + .../co/elastic/logging/log4j2/EcsLayout.java | 18 ++++++++-- .../EcsLayoutWithStackTraceAsArrayTest.java | 4 +-- .../logging/log4j2/Log4j2EcsLayoutTest.java | 1 + .../src/test/resources/log4j2-test.xml | 2 +- .../elastic/logging/logback/EcsEncoder.java | 7 ++++ .../logging/logback/EcsEncoderTest.java | 1 + .../EcsEncoderWithStacktraceAsArrayTest.java | 1 + ...ck-config-with-nop-throwable-converter.xml | 1 + .../src/test/resources/logback-config.xml | 1 + 22 files changed, 103 insertions(+), 11 deletions(-) diff --git a/docs/tab-widgets/ecs-encoder.asciidoc b/docs/tab-widgets/ecs-encoder.asciidoc index 10132aad..d9c5aab4 100644 --- a/docs/tab-widgets/ecs-encoder.asciidoc +++ b/docs/tab-widgets/ecs-encoder.asciidoc @@ -42,6 +42,7 @@ All you have to do is to use the `co.elastic.logging.logback.EcsEncoder` instead my-application my-application-version + my-application-environment my-application-cluster-node ---- @@ -61,6 +62,11 @@ All you have to do is to use the `co.elastic.logging.logback.EcsEncoder` instead | |Sets the `service.version` field so you can filter your logs by a particular service version +|`serviceEnvironment` +|String +| +|Sets the `service.environment` field so you can filter your logs by a particular service environment + |`serviceNodeName` |String | @@ -116,10 +122,10 @@ For example: - + - + @@ -146,6 +152,11 @@ For example: | |Sets the `service.version` field so you can filter your logs by a particular service version +|`serviceEnvironment` +|String +| +|Sets the `service.environment` field so you can filter your logs by a particular service environment + |`serviceNodeName` |String | @@ -238,6 +249,11 @@ For example: | |Sets the `service.version` field so you can filter your logs by a particular service version +|`serviceEnvironment` +|String +| +|Sets the `service.environment` field so you can filter your logs by a particular service environment + |`serviceNodeName` |String | @@ -286,6 +302,7 @@ java.util.logging.ConsoleHandler.level = FINE java.util.logging.ConsoleHandler.formatter = co.elastic.logging.jul.EcsFormatter co.elastic.logging.jul.EcsFormatter.serviceName=my-app co.elastic.logging.jul.EcsFormatter.serviceVersion=my-app-version +co.elastic.logging.jul.EcsFormatter.serviceEnvironment=my-app-environment co.elastic.logging.jul.EcsFormatter.serviceNodeName=my-app-cluster-node ---- @@ -304,6 +321,11 @@ co.elastic.logging.jul.EcsFormatter.serviceNodeName=my-app-cluster-node | |Sets the `service.version` field so you can filter your logs by a particular service version +|`serviceEnvironment` +|String +| +|Sets the `service.environment` field so you can filter your logs by a particular service environment + |`serviceNodeName` |String | @@ -350,7 +372,7 @@ Add the formatter to a handler in the logging subsystem: [source,bash] ---- $WILDFLY_HOME/bin/jboss-cli.sh -c '/subsystem=logging/custom-formatter=ECS:add(module=co.elastic.logging.jboss-logmanager-ecs-formatter, -class=co.elastic.logging.jboss.logmanager.EcsFormatter, properties={serviceName=my-app,serviceVersion=my-app-version,serviceNodeName=my-app-cluster-node}),\ +class=co.elastic.logging.jboss.logmanager.EcsFormatter, properties={serviceName=my-app,serviceVersion=my-app-version,serviceEnvironment=my-app-environment,serviceNodeName=my-app-cluster-node}),\ /subsystem=logging/console-handler=CONSOLE:write-attribute(name=named-formatter,value=ECS)' ---- @@ -369,6 +391,11 @@ class=co.elastic.logging.jboss.logmanager.EcsFormatter, properties={serviceName= | |Sets the `service.version` field so you can filter your logs by a particular service version +|`serviceEnvironment` +|String +| +|Sets the `service.environment` field so you can filter your logs by a particular service environment + |`serviceNodeName` |String | 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 cd16e53f..97eaa93a 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 @@ -103,6 +103,14 @@ public static void serializeServiceVersion(StringBuilder builder, String service } } + public static void serializeServiceEnvironment(StringBuilder builder, String serviceEnvironment) { + if (serviceEnvironment != null) { + builder.append("\"service.environment\":\""); + JsonUtils.quoteAsString(serviceEnvironment, builder); + builder.append("\","); + } + } + public static void serializeServiceNodeName(StringBuilder builder, String serviceNodeName) { if (serviceNodeName != null) { builder.append("\"service.node.name\":\""); diff --git a/ecs-logging-core/src/test/java/co/elastic/logging/AbstractEcsLoggingTest.java b/ecs-logging-core/src/test/java/co/elastic/logging/AbstractEcsLoggingTest.java index 4df38f01..bc83c4bf 100644 --- a/ecs-logging-core/src/test/java/co/elastic/logging/AbstractEcsLoggingTest.java +++ b/ecs-logging-core/src/test/java/co/elastic/logging/AbstractEcsLoggingTest.java @@ -60,6 +60,7 @@ void testMetadata() throws Exception { assertThat(logLine.get("process.thread.name").textValue()).isEqualTo(Thread.currentThread().getName()); assertThat(logLine.get("service.name").textValue()).isEqualTo("test"); assertThat(logLine.get("service.version").textValue()).isEqualTo("test-version"); + assertThat(logLine.get("service.environment").textValue()).isEqualTo("test-environment"); assertThat(logLine.get("service.node.name").textValue()).isEqualTo("test-node"); assertThat(Instant.parse(logLine.get("@timestamp").textValue())).isCloseTo(Instant.now(), within(1, ChronoUnit.MINUTES)); assertThat(logLine.get("log.level").textValue()).isIn("DEBUG", "FINE"); 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 e58a4f0c..3eca5e9e 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 @@ -66,6 +66,7 @@ void testEscaping() throws IOException { String loggerName = "logger\""; String serviceName = "test\""; String serviceVersion = "test-version\""; + String serviceEnvironment = "test-environment\""; String serviceNodeName = "test-node\""; String eventDataset = "event-dataset\""; String threadName = "event-dataset\""; @@ -77,6 +78,7 @@ void testEscaping() throws IOException { EcsJsonSerializer.serializeLoggerName(jsonBuilder, loggerName); EcsJsonSerializer.serializeServiceName(jsonBuilder, serviceName); EcsJsonSerializer.serializeServiceVersion(jsonBuilder, serviceVersion); + EcsJsonSerializer.serializeServiceEnvironment(jsonBuilder, serviceEnvironment); EcsJsonSerializer.serializeServiceNodeName(jsonBuilder, serviceNodeName); EcsJsonSerializer.serializeEventDataset(jsonBuilder, eventDataset); EcsJsonSerializer.serializeThreadName(jsonBuilder, threadName); @@ -88,6 +90,7 @@ void testEscaping() throws IOException { assertThat(jsonNode.get("log.logger").textValue()).isEqualTo(loggerName); assertThat(jsonNode.get("service.name").textValue()).isEqualTo(serviceName); assertThat(jsonNode.get("service.version").textValue()).isEqualTo(serviceVersion); + assertThat(jsonNode.get("service.environment").textValue()).isEqualTo(serviceEnvironment); assertThat(jsonNode.get("service.node.name").textValue()).isEqualTo(serviceNodeName); assertThat(jsonNode.get("event.dataset").textValue()).isEqualTo(eventDataset); assertThat(jsonNode.get("process.thread.name").textValue()).isEqualTo(eventDataset); diff --git a/jboss-logmanager-ecs-formatter/src/main/java/co/elastic/logging/jboss/logmanager/EcsFormatter.java b/jboss-logmanager-ecs-formatter/src/main/java/co/elastic/logging/jboss/logmanager/EcsFormatter.java index 99883cb8..0a3e8f30 100644 --- a/jboss-logmanager-ecs-formatter/src/main/java/co/elastic/logging/jboss/logmanager/EcsFormatter.java +++ b/jboss-logmanager-ecs-formatter/src/main/java/co/elastic/logging/jboss/logmanager/EcsFormatter.java @@ -37,6 +37,7 @@ public class EcsFormatter extends ExtFormatter { private String serviceName; private String serviceVersion; + private String serviceEnvironment; private String serviceNodeName; private String eventDataset; private List additionalFields = Collections.emptyList(); @@ -45,7 +46,8 @@ public class EcsFormatter extends ExtFormatter { public EcsFormatter() { serviceName = getProperty("co.elastic.logging.jboss.logmanager.EcsFormatter.serviceName", null); - serviceVersion = getProperty("co.elastic.logging.jboss.logmanager.EcsFormatter.serviceversion", null); + serviceVersion = getProperty("co.elastic.logging.jboss.logmanager.EcsFormatter.serviceVersion", null); + serviceEnvironment = getProperty("co.elastic.logging.jboss.logmanager.EcsFormatter.serviceEnvironment", null); serviceNodeName = getProperty("co.elastic.logging.jboss.logmanager.EcsFormatter.serviceNodeName", null); eventDataset = getProperty("co.elastic.logging.jboss.logmanager.EcsFormatter.eventDataset", null); eventDataset = EcsJsonSerializer.computeEventDataset(eventDataset, serviceName); @@ -62,6 +64,7 @@ public String format(ExtLogRecord record) { EcsJsonSerializer.serializeEcsVersion(builder); EcsJsonSerializer.serializeServiceName(builder, serviceName); EcsJsonSerializer.serializeServiceVersion(builder, serviceVersion); + EcsJsonSerializer.serializeServiceEnvironment(builder, serviceEnvironment); EcsJsonSerializer.serializeServiceNodeName(builder, serviceNodeName); EcsJsonSerializer.serializeEventDataset(builder, eventDataset); EcsJsonSerializer.serializeThreadName(builder, record.getThreadName()); @@ -100,6 +103,10 @@ public void setServiceVersion(final String serviceVersion) { this.serviceVersion = serviceVersion; } + public void setServiceEnvironment(final String serviceEnvironment) { + this.serviceEnvironment = serviceEnvironment; + } + public void setServiceNodeName(final String serviceNodeName) { this.serviceNodeName = serviceNodeName; } diff --git a/jboss-logmanager-ecs-formatter/src/test/java/co/elastic/logging/jboss/logmanager/EcsFormatterTest.java b/jboss-logmanager-ecs-formatter/src/test/java/co/elastic/logging/jboss/logmanager/EcsFormatterTest.java index 57360220..029d2716 100644 --- a/jboss-logmanager-ecs-formatter/src/test/java/co/elastic/logging/jboss/logmanager/EcsFormatterTest.java +++ b/jboss-logmanager-ecs-formatter/src/test/java/co/elastic/logging/jboss/logmanager/EcsFormatterTest.java @@ -85,8 +85,8 @@ public void printStackTrace(PrintWriter pw) { assertThat(result.get("error.type").textValue()).isEqualTo("co.elastic.logging.jboss.logmanager.EcsFormatterTest$1"); assertThat(result.get("error.message").textValue()).isEqualTo("Example Exception Message"); assertThat(result.get("error.stack_trace").textValue()) - .isEqualTo("co.elastic.logging.jboss.logmanager.EcsFormatterTest$1: Example Exception Message\n" + - "\tat co.elastic.logging.jboss.logmanager.EcsFormatterTest.testExceptionLogging(EcsFormatterTest.java:125)\n"); + .isEqualTo("co.elastic.logging.jboss.logmanager.EcsFormatterTest$1: Example Exception Message" + System.lineSeparator() + + "\tat co.elastic.logging.jboss.logmanager.EcsFormatterTest.testExceptionLogging(EcsFormatterTest.java:125)" + System.lineSeparator()); } } diff --git a/jboss-logmanager-ecs-formatter/src/test/java/co/elastic/logging/jboss/logmanager/JBossLogManagerTest.java b/jboss-logmanager-ecs-formatter/src/test/java/co/elastic/logging/jboss/logmanager/JBossLogManagerTest.java index a4584016..c74b0867 100644 --- a/jboss-logmanager-ecs-formatter/src/test/java/co/elastic/logging/jboss/logmanager/JBossLogManagerTest.java +++ b/jboss-logmanager-ecs-formatter/src/test/java/co/elastic/logging/jboss/logmanager/JBossLogManagerTest.java @@ -90,6 +90,7 @@ void setUp() { formatter.setIncludeOrigin(true); formatter.setServiceName("test"); formatter.setServiceVersion("test-version"); + formatter.setServiceEnvironment("test-environment"); formatter.setServiceNodeName("test-node"); formatter.setEventDataset("testdataset"); formatter.setAdditionalFields("key1=value1,key2=value2"); diff --git a/jul-ecs-formatter/src/main/java/co/elastic/logging/jul/EcsFormatter.java b/jul-ecs-formatter/src/main/java/co/elastic/logging/jul/EcsFormatter.java index 66b851d7..9320dbc4 100644 --- a/jul-ecs-formatter/src/main/java/co/elastic/logging/jul/EcsFormatter.java +++ b/jul-ecs-formatter/src/main/java/co/elastic/logging/jul/EcsFormatter.java @@ -41,6 +41,8 @@ public class EcsFormatter extends Formatter { private boolean stackTraceAsArray; private String serviceName; private String serviceVersion; + + private String serviceEnvironment; private String serviceNodeName; private boolean includeOrigin; private String eventDataset; @@ -52,6 +54,7 @@ public class EcsFormatter extends Formatter { public EcsFormatter() { serviceName = getProperty("co.elastic.logging.jul.EcsFormatter.serviceName", null); serviceVersion= getProperty("co.elastic.logging.jul.EcsFormatter.serviceVersion", null); + serviceEnvironment= getProperty("co.elastic.logging.jul.EcsFormatter.serviceEnvironment", null); serviceNodeName = getProperty("co.elastic.logging.jul.EcsFormatter.serviceNodeName", null); includeOrigin = Boolean.parseBoolean(getProperty("co.elastic.logging.jul.EcsFormatter.includeOrigin", "false")); stackTraceAsArray = Boolean.parseBoolean(getProperty("co.elastic.logging.jul.EcsFormatter.stackTraceAsArray", "false")); @@ -71,6 +74,7 @@ public String format(final LogRecord record) { EcsJsonSerializer.serializeMDC(builder, mdcSupplier.getMDC()); EcsJsonSerializer.serializeServiceName(builder, serviceName); EcsJsonSerializer.serializeServiceVersion(builder, serviceVersion); + EcsJsonSerializer.serializeServiceEnvironment(builder, serviceEnvironment); EcsJsonSerializer.serializeServiceNodeName(builder, serviceNodeName); EcsJsonSerializer.serializeEventDataset(builder, eventDataset); if (Thread.currentThread().getId() == record.getThreadID()) { @@ -102,6 +106,10 @@ public void setServiceVersion(final String serviceVersion) { this.serviceVersion = serviceVersion; } + public void setServiceEnvironment(final String serviceEnvironment) { + this.serviceEnvironment = serviceEnvironment; + } + public void setServiceNodeName(final String serviceNodeName) { this.serviceNodeName = serviceNodeName; } diff --git a/jul-ecs-formatter/src/test/java/co/elastic/logging/jul/JulLoggingTest.java b/jul-ecs-formatter/src/test/java/co/elastic/logging/jul/JulLoggingTest.java index e90cedcb..36590b57 100644 --- a/jul-ecs-formatter/src/test/java/co/elastic/logging/jul/JulLoggingTest.java +++ b/jul-ecs-formatter/src/test/java/co/elastic/logging/jul/JulLoggingTest.java @@ -133,6 +133,7 @@ protected EcsFormatter createEcsFormatter() { ret.setIncludeOrigin(true); ret.setServiceName("test"); ret.setServiceVersion("test-version"); + ret.setServiceEnvironment("test-environment"); ret.setServiceNodeName("test-node"); ret.setEventDataset("testdataset"); return ret; diff --git a/jul-ecs-formatter/src/test/resources/logging.properties b/jul-ecs-formatter/src/test/resources/logging.properties index 7ec68431..33319567 100644 --- a/jul-ecs-formatter/src/test/resources/logging.properties +++ b/jul-ecs-formatter/src/test/resources/logging.properties @@ -1,6 +1,7 @@ # ECS formatter co.elastic.logging.jul.EcsFormatter.serviceName=test co.elastic.logging.jul.EcsFormatter.serviceVersion=test-version +co.elastic.logging.jul.EcsFormatter.serviceEnvironment=test-environment co.elastic.logging.jul.EcsFormatter.serviceNodeName=test-node co.elastic.logging.jul.EcsFormatter.eventDataset=testdataset co.elastic.logging.jul.EcsFormatter.includeOrigin=true diff --git a/log4j-ecs-layout/src/main/java/co/elastic/logging/log4j/EcsLayout.java b/log4j-ecs-layout/src/main/java/co/elastic/logging/log4j/EcsLayout.java index d8503048..25ccede4 100644 --- a/log4j-ecs-layout/src/main/java/co/elastic/logging/log4j/EcsLayout.java +++ b/log4j-ecs-layout/src/main/java/co/elastic/logging/log4j/EcsLayout.java @@ -41,6 +41,8 @@ public class EcsLayout extends Layout { private boolean stackTraceAsArray = false; private String serviceName; private String serviceVersion; + + private String serviceEnvironment; private String serviceNodeName; private boolean includeOrigin; private String eventDataset; @@ -55,6 +57,7 @@ public String format(LoggingEvent event) { EcsJsonSerializer.serializeEcsVersion(builder); EcsJsonSerializer.serializeServiceName(builder, serviceName); EcsJsonSerializer.serializeServiceVersion(builder, serviceVersion); + EcsJsonSerializer.serializeServiceEnvironment(builder, serviceEnvironment); EcsJsonSerializer.serializeServiceNodeName(builder, serviceNodeName); EcsJsonSerializer.serializeEventDataset(builder, eventDataset); EcsJsonSerializer.serializeThreadName(builder, event.getThreadName()); @@ -107,6 +110,10 @@ public void setServiceVersion(String serviceVersion) { this.serviceVersion = serviceVersion; } + public void setServiceEnvironment(String serviceEnvironment) { + this.serviceEnvironment = serviceEnvironment; + } + public void setServiceNodeName(String serviceNodeName) { this.serviceNodeName = serviceNodeName; } diff --git a/log4j-ecs-layout/src/test/java/co/elastic/logging/log4j/Log4jEcsLayoutTest.java b/log4j-ecs-layout/src/test/java/co/elastic/logging/log4j/Log4jEcsLayoutTest.java index 1ac395f0..cecc288c 100644 --- a/log4j-ecs-layout/src/test/java/co/elastic/logging/log4j/Log4jEcsLayoutTest.java +++ b/log4j-ecs-layout/src/test/java/co/elastic/logging/log4j/Log4jEcsLayoutTest.java @@ -52,6 +52,7 @@ void setUp() { ecsLayout = new EcsLayout(); ecsLayout.setServiceName("test"); ecsLayout.setServiceVersion("test-version"); + ecsLayout.setServiceEnvironment("test-environment"); ecsLayout.setServiceNodeName("test-node"); ecsLayout.setIncludeOrigin(true); ecsLayout.setEventDataset("testdataset"); diff --git a/log4j-ecs-layout/src/test/resources/log4j.xml b/log4j-ecs-layout/src/test/resources/log4j.xml index 53287289..887d495e 100644 --- a/log4j-ecs-layout/src/test/resources/log4j.xml +++ b/log4j-ecs-layout/src/test/resources/log4j.xml @@ -5,6 +5,7 @@ + diff --git a/log4j2-ecs-layout/src/main/java/co/elastic/logging/log4j2/EcsLayout.java b/log4j2-ecs-layout/src/main/java/co/elastic/logging/log4j2/EcsLayout.java index f07e0d82..9c6b084f 100644 --- a/log4j2-ecs-layout/src/main/java/co/elastic/logging/log4j2/EcsLayout.java +++ b/log4j2-ecs-layout/src/main/java/co/elastic/logging/log4j2/EcsLayout.java @@ -72,6 +72,8 @@ public class EcsLayout extends AbstractStringLayout { private final boolean stackTraceAsArray; private final String serviceName; private final String serviceVersion; + + private final String serviceEnvironment; private final String serviceNodeName; private final String eventDataset; private final boolean includeMarkers; @@ -79,11 +81,12 @@ public class EcsLayout extends AbstractStringLayout { private final PatternFormatter[] exceptionPatternFormatter; private final ConcurrentMap, Boolean> supportsJson = new ConcurrentHashMap, Boolean>(); - private EcsLayout(Configuration config, String serviceName, String serviceVersion, String serviceNodeName, String eventDataset, boolean includeMarkers, + private EcsLayout(Configuration config, String serviceName, String serviceVersion, String serviceEnvironment, String serviceNodeName, String eventDataset, boolean includeMarkers, KeyValuePair[] additionalFields, boolean includeOrigin, String exceptionPattern, boolean stackTraceAsArray) { super(config, UTF_8, null, null); this.serviceName = serviceName; this.serviceVersion = serviceVersion; + this.serviceEnvironment = serviceEnvironment; this.serviceNodeName = serviceNodeName; this.eventDataset = eventDataset; this.includeMarkers = includeMarkers; @@ -143,6 +146,7 @@ private StringBuilder toText(LogEvent event, StringBuilder builder, boolean gcFr EcsJsonSerializer.serializeEcsVersion(builder); EcsJsonSerializer.serializeServiceName(builder, serviceName); EcsJsonSerializer.serializeServiceVersion(builder, serviceVersion); + EcsJsonSerializer.serializeServiceEnvironment(builder, serviceEnvironment); EcsJsonSerializer.serializeServiceNodeName(builder, serviceNodeName); EcsJsonSerializer.serializeEventDataset(builder, eventDataset); EcsJsonSerializer.serializeThreadName(builder, event.getThreadName()); @@ -358,6 +362,8 @@ public static class Builder implements org.apache.logging.log4j.core.util.Builde private String serviceName; @PluginBuilderAttribute("serviceVersion") private String serviceVersion; + @PluginBuilderAttribute("serviceEnvironment") + private String serviceEnvironment; @PluginBuilderAttribute("serviceNodeName") private String serviceNodeName; @PluginBuilderAttribute("eventDataset") @@ -397,6 +403,8 @@ public String getServiceVersion() { return serviceVersion; } + public String getServiceEnvironment() { return serviceEnvironment; } + public String getServiceNodeName() { return serviceNodeName; } @@ -441,6 +449,11 @@ public EcsLayout.Builder setServiceVersion(final String serviceVersion) { return this; } + public EcsLayout.Builder setServiceEnvironment(final String serviceEnvironment) { + this.serviceEnvironment = serviceEnvironment; + return this; + } + public EcsLayout.Builder setServiceNodeName(final String serviceNodeName) { this.serviceNodeName = serviceNodeName; return this; @@ -473,7 +486,8 @@ public EcsLayout.Builder setExceptionPattern(String exceptionPattern) { @Override public EcsLayout build() { - return new EcsLayout(getConfiguration(), serviceName, serviceVersion, serviceNodeName, EcsJsonSerializer.computeEventDataset(eventDataset, serviceName), + return new EcsLayout(getConfiguration(), serviceName, serviceVersion, serviceEnvironment, serviceNodeName, + EcsJsonSerializer.computeEventDataset(eventDataset, serviceName), includeMarkers, additionalFields, includeOrigin, exceptionPattern, stackTraceAsArray); } } diff --git a/log4j2-ecs-layout/src/test/java/co/elastic/logging/log4j2/EcsLayoutWithStackTraceAsArrayTest.java b/log4j2-ecs-layout/src/test/java/co/elastic/logging/log4j2/EcsLayoutWithStackTraceAsArrayTest.java index 8eb7f4e2..909712ff 100644 --- a/log4j2-ecs-layout/src/test/java/co/elastic/logging/log4j2/EcsLayoutWithStackTraceAsArrayTest.java +++ b/log4j2-ecs-layout/src/test/java/co/elastic/logging/log4j2/EcsLayoutWithStackTraceAsArrayTest.java @@ -50,7 +50,7 @@ void testLogException() throws Exception { assertThat(log.get("error.stack_trace").isArray()).isTrue(); ArrayNode arrayNode = (ArrayNode) log.get("error.stack_trace"); assertThat(arrayNode.size()).isEqualTo(4); - assertThat(arrayNode.get(0).textValue()).isEqualTo("java.lang.NumberFormatException: For input string: \"NOT_AN_INT\""); + assertThat(arrayNode.get(0).textValue()).isEqualTo("java.lang.NumberFormatException: For input string: \"NOT_AN_INT\"\r"); assertThat(arrayNode.get(1).textValue()).startsWith("\t... suppressed"); assertThat(arrayNode.get(2).textValue()).startsWith("\tat co.elastic.logging.log4j2.EcsLayoutWithStackTraceAsArrayTest.numberFormatException"); assertThat(arrayNode.get(3).textValue()).startsWith("\tat co.elastic.logging.log4j2.EcsLayoutWithStackTraceAsArrayTest.testLogException"); @@ -75,7 +75,7 @@ void testLogExceptionNullMessage() throws Exception { assertThat(log.get("error.stack_trace").isArray()).isTrue(); ArrayNode arrayNode = (ArrayNode) log.get("error.stack_trace"); assertThat(arrayNode.size()).isEqualTo(4); - assertThat(arrayNode.get(0).textValue()).isEqualTo("java.lang.RuntimeException"); + assertThat(arrayNode.get(0).textValue()).isEqualTo("java.lang.RuntimeException\r"); assertThat(arrayNode.get(1).textValue()).startsWith("\tat co.elastic.logging.log4j2.EcsLayoutWithStackTraceAsArrayTest.testLogExceptionNullMessage"); } } diff --git a/log4j2-ecs-layout/src/test/java/co/elastic/logging/log4j2/Log4j2EcsLayoutTest.java b/log4j2-ecs-layout/src/test/java/co/elastic/logging/log4j2/Log4j2EcsLayoutTest.java index aba4f3ce..0896ce5f 100644 --- a/log4j2-ecs-layout/src/test/java/co/elastic/logging/log4j2/Log4j2EcsLayoutTest.java +++ b/log4j2-ecs-layout/src/test/java/co/elastic/logging/log4j2/Log4j2EcsLayoutTest.java @@ -78,6 +78,7 @@ protected EcsLayout.Builder configureLayout(LoggerContext context) { .setConfiguration(context.getConfiguration()) .setServiceName("test") .setServiceVersion("test-version") + .setServiceEnvironment("test-environment") .setServiceNodeName("test-node") .setIncludeMarkers(true) .setIncludeOrigin(true) diff --git a/log4j2-ecs-layout/src/test/resources/log4j2-test.xml b/log4j2-ecs-layout/src/test/resources/log4j2-test.xml index e3397889..58b74c7c 100644 --- a/log4j2-ecs-layout/src/test/resources/log4j2-test.xml +++ b/log4j2-ecs-layout/src/test/resources/log4j2-test.xml @@ -5,7 +5,7 @@ - diff --git a/logback-ecs-encoder/src/main/java/co/elastic/logging/logback/EcsEncoder.java b/logback-ecs-encoder/src/main/java/co/elastic/logging/logback/EcsEncoder.java index fb98bd77..24b8b90f 100644 --- a/logback-ecs-encoder/src/main/java/co/elastic/logging/logback/EcsEncoder.java +++ b/logback-ecs-encoder/src/main/java/co/elastic/logging/logback/EcsEncoder.java @@ -47,6 +47,8 @@ public class EcsEncoder extends EncoderBase { private boolean stackTraceAsArray = false; private String serviceName; private String serviceVersion; + + private String serviceEnvironment; private String serviceNodeName; private String eventDataset; private boolean includeMarkers = false; @@ -109,6 +111,7 @@ public byte[] encode(ILoggingEvent event) { serializeMarkers(event, builder); EcsJsonSerializer.serializeServiceName(builder, serviceName); EcsJsonSerializer.serializeServiceVersion(builder, serviceVersion); + EcsJsonSerializer.serializeServiceEnvironment(builder, serviceEnvironment); EcsJsonSerializer.serializeServiceNodeName(builder, serviceNodeName); EcsJsonSerializer.serializeEventDataset(builder, eventDataset); EcsJsonSerializer.serializeThreadName(builder, event.getThreadName()); @@ -177,6 +180,10 @@ public void setServiceVersion(String serviceVersion) { this.serviceVersion = serviceVersion; } + public void setServiceEnvironment(String serviceEnvironment) { + this.serviceEnvironment = serviceEnvironment; + } + public void setServiceNodeName(String serviceNodeName) { this.serviceNodeName = serviceNodeName; } diff --git a/logback-ecs-encoder/src/test/java/co/elastic/logging/logback/EcsEncoderTest.java b/logback-ecs-encoder/src/test/java/co/elastic/logging/logback/EcsEncoderTest.java index d5d8f244..13f10e51 100644 --- a/logback-ecs-encoder/src/test/java/co/elastic/logging/logback/EcsEncoderTest.java +++ b/logback-ecs-encoder/src/test/java/co/elastic/logging/logback/EcsEncoderTest.java @@ -45,6 +45,7 @@ void setUp() { EcsEncoder ecsEncoder = new EcsEncoder(); ecsEncoder.setServiceName("test"); ecsEncoder.setServiceVersion("test-version"); + ecsEncoder.setServiceEnvironment("test-environment"); ecsEncoder.setServiceNodeName("test-node"); ecsEncoder.setIncludeMarkers(true); ecsEncoder.setIncludeOrigin(true); diff --git a/logback-ecs-encoder/src/test/java/co/elastic/logging/logback/EcsEncoderWithStacktraceAsArrayTest.java b/logback-ecs-encoder/src/test/java/co/elastic/logging/logback/EcsEncoderWithStacktraceAsArrayTest.java index cf20e784..e26e503c 100644 --- a/logback-ecs-encoder/src/test/java/co/elastic/logging/logback/EcsEncoderWithStacktraceAsArrayTest.java +++ b/logback-ecs-encoder/src/test/java/co/elastic/logging/logback/EcsEncoderWithStacktraceAsArrayTest.java @@ -48,6 +48,7 @@ void setUp() throws IOException { EcsEncoder ecsEncoder = new EcsEncoder(); ecsEncoder.setServiceName("test"); ecsEncoder.setServiceVersion("test-version"); + ecsEncoder.setServiceEnvironment("test-environment"); ecsEncoder.setIncludeMarkers(true); ecsEncoder.setIncludeOrigin(true); ecsEncoder.addAdditionalField(new AdditionalField("key1", "value1")); diff --git a/logback-ecs-encoder/src/test/resources/logback-config-with-nop-throwable-converter.xml b/logback-ecs-encoder/src/test/resources/logback-config-with-nop-throwable-converter.xml index 5005348d..38f7a0fc 100644 --- a/logback-ecs-encoder/src/test/resources/logback-config-with-nop-throwable-converter.xml +++ b/logback-ecs-encoder/src/test/resources/logback-config-with-nop-throwable-converter.xml @@ -5,6 +5,7 @@ test test-version + test-environment test-node true true diff --git a/logback-ecs-encoder/src/test/resources/logback-config.xml b/logback-ecs-encoder/src/test/resources/logback-config.xml index a0e8cb70..b1872980 100644 --- a/logback-ecs-encoder/src/test/resources/logback-config.xml +++ b/logback-ecs-encoder/src/test/resources/logback-config.xml @@ -4,6 +4,7 @@ test test-version + test-environment test-node true true From 41da1c483e3866224563eb4e534e89ba7c18c85f Mon Sep 17 00:00:00 2001 From: "Zellner, Markus (GfK)" Date: Mon, 2 May 2022 08:22:40 +0200 Subject: [PATCH 2/4] Apply review changes --- .../src/main/java/co/elastic/logging/jul/EcsFormatter.java | 1 - .../src/main/java/co/elastic/logging/log4j/EcsLayout.java | 1 - .../src/main/java/co/elastic/logging/log4j2/EcsLayout.java | 1 - .../logging/log4j2/EcsLayoutWithStackTraceAsArrayTest.java | 4 ++-- .../src/main/java/co/elastic/logging/logback/EcsEncoder.java | 1 - 5 files changed, 2 insertions(+), 6 deletions(-) diff --git a/jul-ecs-formatter/src/main/java/co/elastic/logging/jul/EcsFormatter.java b/jul-ecs-formatter/src/main/java/co/elastic/logging/jul/EcsFormatter.java index 9320dbc4..191642b3 100644 --- a/jul-ecs-formatter/src/main/java/co/elastic/logging/jul/EcsFormatter.java +++ b/jul-ecs-formatter/src/main/java/co/elastic/logging/jul/EcsFormatter.java @@ -41,7 +41,6 @@ public class EcsFormatter extends Formatter { private boolean stackTraceAsArray; private String serviceName; private String serviceVersion; - private String serviceEnvironment; private String serviceNodeName; private boolean includeOrigin; diff --git a/log4j-ecs-layout/src/main/java/co/elastic/logging/log4j/EcsLayout.java b/log4j-ecs-layout/src/main/java/co/elastic/logging/log4j/EcsLayout.java index 25ccede4..d75bd1e0 100644 --- a/log4j-ecs-layout/src/main/java/co/elastic/logging/log4j/EcsLayout.java +++ b/log4j-ecs-layout/src/main/java/co/elastic/logging/log4j/EcsLayout.java @@ -41,7 +41,6 @@ public class EcsLayout extends Layout { private boolean stackTraceAsArray = false; private String serviceName; private String serviceVersion; - private String serviceEnvironment; private String serviceNodeName; private boolean includeOrigin; diff --git a/log4j2-ecs-layout/src/main/java/co/elastic/logging/log4j2/EcsLayout.java b/log4j2-ecs-layout/src/main/java/co/elastic/logging/log4j2/EcsLayout.java index 9c6b084f..1a997423 100644 --- a/log4j2-ecs-layout/src/main/java/co/elastic/logging/log4j2/EcsLayout.java +++ b/log4j2-ecs-layout/src/main/java/co/elastic/logging/log4j2/EcsLayout.java @@ -72,7 +72,6 @@ public class EcsLayout extends AbstractStringLayout { private final boolean stackTraceAsArray; private final String serviceName; private final String serviceVersion; - private final String serviceEnvironment; private final String serviceNodeName; private final String eventDataset; diff --git a/log4j2-ecs-layout/src/test/java/co/elastic/logging/log4j2/EcsLayoutWithStackTraceAsArrayTest.java b/log4j2-ecs-layout/src/test/java/co/elastic/logging/log4j2/EcsLayoutWithStackTraceAsArrayTest.java index 909712ff..ffc803f7 100644 --- a/log4j2-ecs-layout/src/test/java/co/elastic/logging/log4j2/EcsLayoutWithStackTraceAsArrayTest.java +++ b/log4j2-ecs-layout/src/test/java/co/elastic/logging/log4j2/EcsLayoutWithStackTraceAsArrayTest.java @@ -50,7 +50,7 @@ void testLogException() throws Exception { assertThat(log.get("error.stack_trace").isArray()).isTrue(); ArrayNode arrayNode = (ArrayNode) log.get("error.stack_trace"); assertThat(arrayNode.size()).isEqualTo(4); - assertThat(arrayNode.get(0).textValue()).isEqualTo("java.lang.NumberFormatException: For input string: \"NOT_AN_INT\"\r"); + assertThat(arrayNode.get(0).textValue().trim()).isEqualTo("java.lang.NumberFormatException: For input string: \"NOT_AN_INT\""); assertThat(arrayNode.get(1).textValue()).startsWith("\t... suppressed"); assertThat(arrayNode.get(2).textValue()).startsWith("\tat co.elastic.logging.log4j2.EcsLayoutWithStackTraceAsArrayTest.numberFormatException"); assertThat(arrayNode.get(3).textValue()).startsWith("\tat co.elastic.logging.log4j2.EcsLayoutWithStackTraceAsArrayTest.testLogException"); @@ -75,7 +75,7 @@ void testLogExceptionNullMessage() throws Exception { assertThat(log.get("error.stack_trace").isArray()).isTrue(); ArrayNode arrayNode = (ArrayNode) log.get("error.stack_trace"); assertThat(arrayNode.size()).isEqualTo(4); - assertThat(arrayNode.get(0).textValue()).isEqualTo("java.lang.RuntimeException\r"); + assertThat(arrayNode.get(0).textValue().trim()).isEqualTo("java.lang.RuntimeException"); assertThat(arrayNode.get(1).textValue()).startsWith("\tat co.elastic.logging.log4j2.EcsLayoutWithStackTraceAsArrayTest.testLogExceptionNullMessage"); } } diff --git a/logback-ecs-encoder/src/main/java/co/elastic/logging/logback/EcsEncoder.java b/logback-ecs-encoder/src/main/java/co/elastic/logging/logback/EcsEncoder.java index 24b8b90f..fce8e0f9 100644 --- a/logback-ecs-encoder/src/main/java/co/elastic/logging/logback/EcsEncoder.java +++ b/logback-ecs-encoder/src/main/java/co/elastic/logging/logback/EcsEncoder.java @@ -47,7 +47,6 @@ public class EcsEncoder extends EncoderBase { private boolean stackTraceAsArray = false; private String serviceName; private String serviceVersion; - private String serviceEnvironment; private String serviceNodeName; private String eventDataset; From bf486bfca10bf4c27b839e5ab55bd27565e5e634 Mon Sep 17 00:00:00 2001 From: "Zellner, Markus (GfK)" Date: Mon, 2 May 2022 09:21:43 +0200 Subject: [PATCH 3/4] Fix root cause of testing issue: \r\n was splitted only by \n which is problematic on windows. Generalized to use \R which matches all combinations of line breaks. --- .../src/main/java/co/elastic/logging/EcsJsonSerializer.java | 2 +- .../logging/log4j2/EcsLayoutWithStackTraceAsArrayTest.java | 4 ++-- 2 files changed, 3 insertions(+), 3 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 97eaa93a..2bf20b18 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 @@ -36,7 +36,7 @@ public class EcsJsonSerializer { private static final TimestampSerializer TIMESTAMP_SERIALIZER = new TimestampSerializer(); private static final ThreadLocal messageStringBuilder = new ThreadLocal(); private static final String NEW_LINE = System.getProperty("line.separator"); - private static final Pattern NEW_LINE_PATTERN = Pattern.compile("\\n"); + private static final Pattern NEW_LINE_PATTERN = Pattern.compile("\\R"); public static CharSequence toNullSafeString(final CharSequence s) { return s == null ? "" : s; diff --git a/log4j2-ecs-layout/src/test/java/co/elastic/logging/log4j2/EcsLayoutWithStackTraceAsArrayTest.java b/log4j2-ecs-layout/src/test/java/co/elastic/logging/log4j2/EcsLayoutWithStackTraceAsArrayTest.java index ffc803f7..8eb7f4e2 100644 --- a/log4j2-ecs-layout/src/test/java/co/elastic/logging/log4j2/EcsLayoutWithStackTraceAsArrayTest.java +++ b/log4j2-ecs-layout/src/test/java/co/elastic/logging/log4j2/EcsLayoutWithStackTraceAsArrayTest.java @@ -50,7 +50,7 @@ void testLogException() throws Exception { assertThat(log.get("error.stack_trace").isArray()).isTrue(); ArrayNode arrayNode = (ArrayNode) log.get("error.stack_trace"); assertThat(arrayNode.size()).isEqualTo(4); - assertThat(arrayNode.get(0).textValue().trim()).isEqualTo("java.lang.NumberFormatException: For input string: \"NOT_AN_INT\""); + assertThat(arrayNode.get(0).textValue()).isEqualTo("java.lang.NumberFormatException: For input string: \"NOT_AN_INT\""); assertThat(arrayNode.get(1).textValue()).startsWith("\t... suppressed"); assertThat(arrayNode.get(2).textValue()).startsWith("\tat co.elastic.logging.log4j2.EcsLayoutWithStackTraceAsArrayTest.numberFormatException"); assertThat(arrayNode.get(3).textValue()).startsWith("\tat co.elastic.logging.log4j2.EcsLayoutWithStackTraceAsArrayTest.testLogException"); @@ -75,7 +75,7 @@ void testLogExceptionNullMessage() throws Exception { assertThat(log.get("error.stack_trace").isArray()).isTrue(); ArrayNode arrayNode = (ArrayNode) log.get("error.stack_trace"); assertThat(arrayNode.size()).isEqualTo(4); - assertThat(arrayNode.get(0).textValue().trim()).isEqualTo("java.lang.RuntimeException"); + assertThat(arrayNode.get(0).textValue()).isEqualTo("java.lang.RuntimeException"); assertThat(arrayNode.get(1).textValue()).startsWith("\tat co.elastic.logging.log4j2.EcsLayoutWithStackTraceAsArrayTest.testLogExceptionNullMessage"); } } From b5fd6997c198a93aa4e727b994e2ce6b17967c1f Mon Sep 17 00:00:00 2001 From: "Zellner, Markus (GfK)" Date: Mon, 2 May 2022 10:07:18 +0200 Subject: [PATCH 4/4] Make pattern compatible with < Java 8 --- .../src/main/java/co/elastic/logging/EcsJsonSerializer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 2bf20b18..dfb7411d 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 @@ -36,7 +36,7 @@ public class EcsJsonSerializer { private static final TimestampSerializer TIMESTAMP_SERIALIZER = new TimestampSerializer(); private static final ThreadLocal messageStringBuilder = new ThreadLocal(); private static final String NEW_LINE = System.getProperty("line.separator"); - private static final Pattern NEW_LINE_PATTERN = Pattern.compile("\\R"); + private static final Pattern NEW_LINE_PATTERN = Pattern.compile("\\r\\n|\\n|\\r"); public static CharSequence toNullSafeString(final CharSequence s) { return s == null ? "" : s;