Skip to content

Commit f8be7d2

Browse files
Added support for service.version (#168)
1 parent 05e5383 commit f8be7d2

File tree

22 files changed

+172
-13
lines changed

22 files changed

+172
-13
lines changed

docs/tab-widgets/ecs-encoder.asciidoc

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ All you have to do is to use the `co.elastic.logging.logback.EcsEncoder` instead
4141
----
4242
<encoder class="co.elastic.logging.logback.EcsEncoder">
4343
<serviceName>my-application</serviceName>
44+
<serviceVersion>my-application-version</serviceVersion>
4445
<serviceNodeName>my-application-cluster-node</serviceNodeName>
4546
</encoder>
4647
----
@@ -53,7 +54,12 @@ All you have to do is to use the `co.elastic.logging.logback.EcsEncoder` instead
5354
|`serviceName`
5455
|String
5556
|
56-
|Sets the `service.name` field so you can filter your logs by a particular service
57+
|Sets the `service.name` field so you can filter your logs by a particular service name
58+
59+
|`serviceVersion`
60+
|String
61+
|
62+
|Sets the `service.version` field so you can filter your logs by a particular service version
5763

5864
|`serviceNodeName`
5965
|String
@@ -110,10 +116,10 @@ For example:
110116
<Configuration status="DEBUG">
111117
<Appenders>
112118
<Console name="LogToConsole" target="SYSTEM_OUT">
113-
<EcsLayout serviceName="my-app" serviceNodeName="my-app-cluster-node"/>
119+
<EcsLayout serviceName="my-app" serviceVersion="my-app-version" serviceNodeName="my-app-cluster-node"/>
114120
</Console>
115121
<File name="LogToFile" fileName="logs/app.log">
116-
<EcsLayout serviceName="my-app" serviceNodeName="my-app-cluster-node"/>
122+
<EcsLayout serviceName="my-app" serviceVersion="my-app-version" serviceNodeName="my-app-cluster-node"/>
117123
</File>
118124
</Appenders>
119125
<Loggers>
@@ -133,7 +139,12 @@ For example:
133139
|`serviceName`
134140
|String
135141
|
136-
|Sets the `service.name` field so you can filter your logs by a particular service
142+
|Sets the `service.name` field so you can filter your logs by a particular service name
143+
144+
|`serviceVersion`
145+
|String
146+
|
147+
|Sets the `service.version` field so you can filter your logs by a particular service version
137148

138149
|`serviceNodeName`
139150
|String
@@ -220,7 +231,12 @@ For example:
220231
|`serviceName`
221232
|String
222233
|
223-
|Sets the `service.name` field so you can filter your logs by a particular service
234+
|Sets the `service.name` field so you can filter your logs by a particular service name
235+
236+
|`serviceVersion`
237+
|String
238+
|
239+
|Sets the `service.version` field so you can filter your logs by a particular service version
224240

225241
|`serviceNodeName`
226242
|String
@@ -269,6 +285,7 @@ For example, in `$CATALINA_HOME/conf/logging.properties`:
269285
java.util.logging.ConsoleHandler.level = FINE
270286
java.util.logging.ConsoleHandler.formatter = co.elastic.logging.jul.EcsFormatter
271287
co.elastic.logging.jul.EcsFormatter.serviceName=my-app
288+
co.elastic.logging.jul.EcsFormatter.serviceVersion=my-app-version
272289
co.elastic.logging.jul.EcsFormatter.serviceNodeName=my-app-cluster-node
273290
----
274291

@@ -280,7 +297,12 @@ co.elastic.logging.jul.EcsFormatter.serviceNodeName=my-app-cluster-node
280297
|`serviceName`
281298
|String
282299
|
283-
|Sets the `service.name` field so you can filter your logs by a particular service
300+
|Sets the `service.name` field so you can filter your logs by a particular service name
301+
302+
|`serviceVersion`
303+
|String
304+
|
305+
|Sets the `service.version` field so you can filter your logs by a particular service version
284306

285307
|`serviceNodeName`
286308
|String
@@ -328,7 +350,7 @@ Add the formatter to a handler in the logging subsystem:
328350
[source,bash]
329351
----
330352
$WILDFLY_HOME/bin/jboss-cli.sh -c '/subsystem=logging/custom-formatter=ECS:add(module=co.elastic.logging.jboss-logmanager-ecs-formatter,
331-
class=co.elastic.logging.jboss.logmanager.EcsFormatter, properties={serviceName=my-app,serviceNodeName=my-app-cluster-node}),\
353+
class=co.elastic.logging.jboss.logmanager.EcsFormatter, properties={serviceName=my-app,serviceVersion=my-app-version,serviceNodeName=my-app-cluster-node}),\
332354
/subsystem=logging/console-handler=CONSOLE:write-attribute(name=named-formatter,value=ECS)'
333355
----
334356

@@ -340,7 +362,12 @@ class=co.elastic.logging.jboss.logmanager.EcsFormatter, properties={serviceName=
340362
|`serviceName`
341363
|String
342364
|
343-
|Sets the `service.name` field so you can filter your logs by a particular service
365+
|Sets the `service.name` field so you can filter your logs by a particular service name
366+
367+
|`serviceVersion`
368+
|String
369+
|
370+
|Sets the `service.version` field so you can filter your logs by a particular service version
344371

345372
|`serviceNodeName`
346373
|String

ecs-logging-core/src/main/java/co/elastic/logging/EcsJsonSerializer.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,14 @@ public static void serializeServiceName(StringBuilder builder, String serviceNam
9595
}
9696
}
9797

98+
public static void serializeServiceVersion(StringBuilder builder, String serviceVersion) {
99+
if (serviceVersion != null) {
100+
builder.append("\"service.version\":\"");
101+
JsonUtils.quoteAsString(serviceVersion, builder);
102+
builder.append("\",");
103+
}
104+
}
105+
98106
public static void serializeServiceNodeName(StringBuilder builder, String serviceNodeName) {
99107
if (serviceNodeName != null) {
100108
builder.append("\"service.node.name\":\"");

ecs-logging-core/src/test/java/co/elastic/logging/AbstractEcsLoggingTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ void testMetadata() throws Exception {
5959
System.out.println(logLine.toPrettyString());
6060
assertThat(logLine.get("process.thread.name").textValue()).isEqualTo(Thread.currentThread().getName());
6161
assertThat(logLine.get("service.name").textValue()).isEqualTo("test");
62+
assertThat(logLine.get("service.version").textValue()).isEqualTo("test-version");
6263
assertThat(logLine.get("service.node.name").textValue()).isEqualTo("test-node");
6364
assertThat(Instant.parse(logLine.get("@timestamp").textValue())).isCloseTo(Instant.now(), within(1, ChronoUnit.MINUTES));
6465
assertThat(logLine.get("log.level").textValue()).isIn("DEBUG", "FINE");

ecs-logging-core/src/test/java/co/elastic/logging/EcsJsonSerializerTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ void serializeExceptionAsString() throws IOException {
6565
void testEscaping() throws IOException {
6666
String loggerName = "logger\"";
6767
String serviceName = "test\"";
68+
String serviceVersion = "test-version\"";
6869
String serviceNodeName = "test-node\"";
6970
String eventDataset = "event-dataset\"";
7071
String threadName = "event-dataset\"";
@@ -75,6 +76,7 @@ void testEscaping() throws IOException {
7576
jsonBuilder.append('{');
7677
EcsJsonSerializer.serializeLoggerName(jsonBuilder, loggerName);
7778
EcsJsonSerializer.serializeServiceName(jsonBuilder, serviceName);
79+
EcsJsonSerializer.serializeServiceVersion(jsonBuilder, serviceVersion);
7880
EcsJsonSerializer.serializeServiceNodeName(jsonBuilder, serviceNodeName);
7981
EcsJsonSerializer.serializeEventDataset(jsonBuilder, eventDataset);
8082
EcsJsonSerializer.serializeThreadName(jsonBuilder, threadName);
@@ -85,6 +87,7 @@ void testEscaping() throws IOException {
8587

8688
assertThat(jsonNode.get("log.logger").textValue()).isEqualTo(loggerName);
8789
assertThat(jsonNode.get("service.name").textValue()).isEqualTo(serviceName);
90+
assertThat(jsonNode.get("service.version").textValue()).isEqualTo(serviceVersion);
8891
assertThat(jsonNode.get("service.node.name").textValue()).isEqualTo(serviceNodeName);
8992
assertThat(jsonNode.get("event.dataset").textValue()).isEqualTo(eventDataset);
9093
assertThat(jsonNode.get("process.thread.name").textValue()).isEqualTo(eventDataset);

jboss-logmanager-ecs-formatter/src/main/java/co/elastic/logging/jboss/logmanager/EcsFormatter.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,19 @@
2424
*/
2525
package co.elastic.logging.jboss.logmanager;
2626

27-
import co.elastic.logging.EcsJsonSerializer;
2827
import co.elastic.logging.AdditionalField;
28+
import co.elastic.logging.EcsJsonSerializer;
2929
import org.jboss.logmanager.ExtFormatter;
3030
import org.jboss.logmanager.ExtLogRecord;
3131
import org.jboss.logmanager.LogManager;
3232

33-
import java.util.ArrayList;
3433
import java.util.Collections;
3534
import java.util.List;
3635

3736
public class EcsFormatter extends ExtFormatter {
3837

3938
private String serviceName;
39+
private String serviceVersion;
4040
private String serviceNodeName;
4141
private String eventDataset;
4242
private List<AdditionalField> additionalFields = Collections.emptyList();
@@ -45,6 +45,7 @@ public class EcsFormatter extends ExtFormatter {
4545

4646
public EcsFormatter() {
4747
serviceName = getProperty("co.elastic.logging.jboss.logmanager.EcsFormatter.serviceName", null);
48+
serviceVersion = getProperty("co.elastic.logging.jboss.logmanager.EcsFormatter.serviceversion", null);
4849
serviceNodeName = getProperty("co.elastic.logging.jboss.logmanager.EcsFormatter.serviceNodeName", null);
4950
eventDataset = getProperty("co.elastic.logging.jboss.logmanager.EcsFormatter.eventDataset", null);
5051
eventDataset = EcsJsonSerializer.computeEventDataset(eventDataset, serviceName);
@@ -60,6 +61,7 @@ public String format(ExtLogRecord record) {
6061
EcsJsonSerializer.serializeFormattedMessage(builder, record.getFormattedMessage());
6162
EcsJsonSerializer.serializeEcsVersion(builder);
6263
EcsJsonSerializer.serializeServiceName(builder, serviceName);
64+
EcsJsonSerializer.serializeServiceVersion(builder, serviceVersion);
6365
EcsJsonSerializer.serializeServiceNodeName(builder, serviceNodeName);
6466
EcsJsonSerializer.serializeEventDataset(builder, eventDataset);
6567
EcsJsonSerializer.serializeThreadName(builder, record.getThreadName());
@@ -94,6 +96,10 @@ public void setServiceName(final String serviceName) {
9496
eventDataset = EcsJsonSerializer.computeEventDataset(eventDataset, serviceName);
9597
}
9698

99+
public void setServiceVersion(final String serviceVersion) {
100+
this.serviceVersion = serviceVersion;
101+
}
102+
97103
public void setServiceNodeName(final String serviceNodeName) {
98104
this.serviceNodeName = serviceNodeName;
99105
}

jboss-logmanager-ecs-formatter/src/test/java/co/elastic/logging/jboss/logmanager/JBossLogManagerTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ public JsonNode getLastLogLine() throws IOException {
8989
void setUp() {
9090
formatter.setIncludeOrigin(true);
9191
formatter.setServiceName("test");
92+
formatter.setServiceVersion("test-version");
9293
formatter.setServiceNodeName("test-node");
9394
formatter.setEventDataset("testdataset");
9495
formatter.setAdditionalFields("key1=value1,key2=value2");

jul-ecs-formatter/src/main/java/co/elastic/logging/jul/EcsFormatter.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public class EcsFormatter extends Formatter {
4040

4141
private boolean stackTraceAsArray;
4242
private String serviceName;
43+
private String serviceVersion;
4344
private String serviceNodeName;
4445
private boolean includeOrigin;
4546
private String eventDataset;
@@ -50,6 +51,7 @@ public class EcsFormatter extends Formatter {
5051
*/
5152
public EcsFormatter() {
5253
serviceName = getProperty("co.elastic.logging.jul.EcsFormatter.serviceName", null);
54+
serviceVersion= getProperty("co.elastic.logging.jul.EcsFormatter.serviceVersion", null);
5355
serviceNodeName = getProperty("co.elastic.logging.jul.EcsFormatter.serviceNodeName", null);
5456
includeOrigin = Boolean.getBoolean(getProperty("co.elastic.logging.jul.EcsFormatter.includeOrigin", "false"));
5557
stackTraceAsArray = Boolean
@@ -69,6 +71,7 @@ public String format(final LogRecord record) {
6971
EcsJsonSerializer.serializeAdditionalFields(builder, additionalFields);
7072
EcsJsonSerializer.serializeMDC(builder, mdcSupplier.getMDC());
7173
EcsJsonSerializer.serializeServiceName(builder, serviceName);
74+
EcsJsonSerializer.serializeServiceVersion(builder, serviceVersion);
7275
EcsJsonSerializer.serializeServiceNodeName(builder, serviceNodeName);
7376
EcsJsonSerializer.serializeEventDataset(builder, eventDataset);
7477
if (Thread.currentThread().getId() == record.getThreadID()) {
@@ -96,6 +99,10 @@ public void setServiceName(final String serviceName) {
9699
this.serviceName = serviceName;
97100
}
98101

102+
public void setServiceVersion(final String serviceVersion) {
103+
this.serviceVersion = serviceVersion;
104+
}
105+
99106
public void setServiceNodeName(final String serviceNodeName) {
100107
this.serviceNodeName = serviceNodeName;
101108
}

jul-ecs-formatter/src/test/java/co/elastic/logging/jul/JulLoggingTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ private void setUpFormatter() {
120120
formatter = new EcsFormatter();
121121
formatter.setIncludeOrigin(true);
122122
formatter.setServiceName("test");
123+
formatter.setServiceVersion("test-version");
123124
formatter.setServiceNodeName("test-node");
124125
formatter.setEventDataset("testdataset");
125126

log4j-ecs-layout/src/main/java/co/elastic/logging/log4j/EcsLayout.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public class EcsLayout extends Layout {
4040

4141
private boolean stackTraceAsArray = false;
4242
private String serviceName;
43+
private String serviceVersion;
4344
private String serviceNodeName;
4445
private boolean includeOrigin;
4546
private String eventDataset;
@@ -53,6 +54,7 @@ public String format(LoggingEvent event) {
5354
EcsJsonSerializer.serializeFormattedMessage(builder, event.getRenderedMessage());
5455
EcsJsonSerializer.serializeEcsVersion(builder);
5556
EcsJsonSerializer.serializeServiceName(builder, serviceName);
57+
EcsJsonSerializer.serializeServiceVersion(builder, serviceVersion);
5658
EcsJsonSerializer.serializeServiceNodeName(builder, serviceNodeName);
5759
EcsJsonSerializer.serializeEventDataset(builder, eventDataset);
5860
EcsJsonSerializer.serializeThreadName(builder, event.getThreadName());
@@ -101,6 +103,10 @@ public void setServiceName(String serviceName) {
101103
this.serviceName = serviceName;
102104
}
103105

106+
public void setServiceVersion(String serviceVersion) {
107+
this.serviceVersion = serviceVersion;
108+
}
109+
104110
public void setServiceNodeName(String serviceNodeName) {
105111
this.serviceNodeName = serviceNodeName;
106112
}

log4j-ecs-layout/src/test/java/co/elastic/logging/log4j/Log4jEcsLayoutTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ void setUp() {
5151
logger.addAppender(appender);
5252
ecsLayout = new EcsLayout();
5353
ecsLayout.setServiceName("test");
54+
ecsLayout.setServiceVersion("test-version");
5455
ecsLayout.setServiceNodeName("test-node");
5556
ecsLayout.setIncludeOrigin(true);
5657
ecsLayout.setEventDataset("testdataset");

log4j-ecs-layout/src/test/resources/log4j.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<appender name="List" class="co.elastic.logging.log4j.ListAppender">
55
<layout class="co.elastic.logging.log4j.EcsLayout">
66
<param name="serviceName" value="test"/>
7+
<param name="serviceVersion" value="test-version"/>
78
<param name="serviceNodeName" value="test-node"/>
89
<param name="eventDataset" value="testdataset"/>
910
<param name="includeOrigin" value="true"/>

log4j2-ecs-layout/src/main/java/co/elastic/logging/log4j2/EcsLayout.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,17 +71,19 @@ public class EcsLayout extends AbstractStringLayout {
7171
private final PatternFormatter[][] fieldValuePatternFormatter;
7272
private final boolean stackTraceAsArray;
7373
private final String serviceName;
74+
private final String serviceVersion;
7475
private final String serviceNodeName;
7576
private final String eventDataset;
7677
private final boolean includeMarkers;
7778
private final boolean includeOrigin;
7879
private final PatternFormatter[] exceptionPatternFormatter;
7980
private final ConcurrentMap<Class<? extends MultiformatMessage>, Boolean> supportsJson = new ConcurrentHashMap<Class<? extends MultiformatMessage>, Boolean>();
8081

81-
private EcsLayout(Configuration config, String serviceName, String serviceNodeName, String eventDataset, boolean includeMarkers,
82+
private EcsLayout(Configuration config, String serviceName, String serviceVersion, String serviceNodeName, String eventDataset, boolean includeMarkers,
8283
KeyValuePair[] additionalFields, boolean includeOrigin, String exceptionPattern, boolean stackTraceAsArray) {
8384
super(config, UTF_8, null, null);
8485
this.serviceName = serviceName;
86+
this.serviceVersion = serviceVersion;
8587
this.serviceNodeName = serviceNodeName;
8688
this.eventDataset = eventDataset;
8789
this.includeMarkers = includeMarkers;
@@ -140,6 +142,7 @@ private StringBuilder toText(LogEvent event, StringBuilder builder, boolean gcFr
140142
serializeMessage(builder, gcFree, event.getMessage(), event.getThrown());
141143
EcsJsonSerializer.serializeEcsVersion(builder);
142144
EcsJsonSerializer.serializeServiceName(builder, serviceName);
145+
EcsJsonSerializer.serializeServiceVersion(builder, serviceVersion);
143146
EcsJsonSerializer.serializeServiceNodeName(builder, serviceNodeName);
144147
EcsJsonSerializer.serializeEventDataset(builder, eventDataset);
145148
EcsJsonSerializer.serializeThreadName(builder, event.getThreadName());
@@ -354,6 +357,8 @@ public static class Builder implements org.apache.logging.log4j.core.util.Builde
354357
private Configuration configuration;
355358
@PluginBuilderAttribute("serviceName")
356359
private String serviceName;
360+
@PluginBuilderAttribute("serviceVersion")
361+
private String serviceVersion;
357362
@PluginBuilderAttribute("serviceNodeName")
358363
private String serviceNodeName;
359364
@PluginBuilderAttribute("eventDataset")
@@ -389,6 +394,10 @@ public String getServiceName() {
389394
return serviceName;
390395
}
391396

397+
public String getServiceVersion() {
398+
return serviceVersion;
399+
}
400+
392401
public String getServiceNodeName() {
393402
return serviceNodeName;
394403
}
@@ -428,6 +437,11 @@ public EcsLayout.Builder setServiceName(final String serviceName) {
428437
return this;
429438
}
430439

440+
public EcsLayout.Builder setServiceVersion(final String serviceVersion) {
441+
this.serviceVersion = serviceVersion;
442+
return this;
443+
}
444+
431445
public EcsLayout.Builder setServiceNodeName(final String serviceNodeName) {
432446
this.serviceNodeName = serviceNodeName;
433447
return this;
@@ -460,7 +474,7 @@ public EcsLayout.Builder setExceptionPattern(String exceptionPattern) {
460474

461475
@Override
462476
public EcsLayout build() {
463-
return new EcsLayout(getConfiguration(), serviceName, serviceNodeName, EcsJsonSerializer.computeEventDataset(eventDataset, serviceName),
477+
return new EcsLayout(getConfiguration(), serviceName, serviceVersion, serviceNodeName, EcsJsonSerializer.computeEventDataset(eventDataset, serviceName),
464478
includeMarkers, additionalFields, includeOrigin, exceptionPattern, stackTraceAsArray);
465479
}
466480
}

log4j2-ecs-layout/src/test/java/co/elastic/logging/log4j2/CustomExceptionPatternConverter.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,27 @@
1+
/*-
2+
* #%L
3+
* Java ECS logging
4+
* %%
5+
* Copyright (C) 2019 - 2022 Elastic and contributors
6+
* %%
7+
* Licensed to Elasticsearch B.V. under one or more contributor
8+
* license agreements. See the NOTICE file distributed with
9+
* this work for additional information regarding copyright
10+
* ownership. Elasticsearch B.V. licenses this file to you under
11+
* the Apache License, Version 2.0 (the "License"); you may
12+
* not use this file except in compliance with the License.
13+
* You may obtain a copy of the License at
14+
*
15+
* http://www.apache.org/licenses/LICENSE-2.0
16+
*
17+
* Unless required by applicable law or agreed to in writing,
18+
* software distributed under the License is distributed on an
19+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20+
* KIND, either express or implied. See the License for the
21+
* specific language governing permissions and limitations
22+
* under the License.
23+
* #L%
24+
*/
125
package co.elastic.logging.log4j2;
226

327
import org.apache.logging.log4j.core.LogEvent;

0 commit comments

Comments
 (0)