Skip to content

Commit 1382236

Browse files
authored
Event dataset (#66)
1 parent 52423bc commit 1382236

File tree

12 files changed

+55
-6
lines changed

12 files changed

+55
-6
lines changed

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ public static void serializeServiceName(StringBuilder builder, String serviceNam
8181
}
8282
}
8383

84+
public static void serializeEventDataset(StringBuilder builder, String eventDataset) {
85+
if (eventDataset != null) {
86+
builder.append("\"event.dataset\":\"").append(eventDataset).append("\",");
87+
}
88+
}
89+
8490
public static void serializeLogLevel(StringBuilder builder, String level) {
8591
builder.append("\"log.level\":");
8692
// add padding so that all levels line up
@@ -260,6 +266,13 @@ public static StringBuilder getMessageStringBuilder() {
260266
return result;
261267
}
262268

269+
public static String computeEventDataset(String eventDataset, String serviceName) {
270+
if (eventDataset == null && serviceName != null && !serviceName.isEmpty()) {
271+
return serviceName + ".log";
272+
}
273+
return eventDataset;
274+
}
275+
263276
private static class StringBuilderWriter extends Writer {
264277

265278
private final StringBuilder buffer;

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
@@ -50,6 +50,7 @@ void testMetadata() throws Exception {
5050
assertThat(Instant.parse(getLastLogLine().get("@timestamp").textValue())).isCloseTo(Instant.now(), within(1, ChronoUnit.MINUTES));
5151
assertThat(getLastLogLine().get("log.level").textValue()).isEqualTo("DEBUG");
5252
assertThat(getLastLogLine().get("log.logger")).isNotNull();
53+
assertThat(getLastLogLine().get("event.dataset").textValue()).isEqualTo("testdataset.log");
5354
}
5455

5556
@Test

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public class EcsLayout extends Layout {
3939
private String serviceName;
4040
private Set<String> topLevelLabels = new HashSet<String>(EcsJsonSerializer.DEFAULT_TOP_LEVEL_LABELS);
4141
private boolean includeOrigin;
42+
private String eventDataset;
4243

4344
@Override
4445
public String format(LoggingEvent event) {
@@ -47,6 +48,7 @@ public String format(LoggingEvent event) {
4748
EcsJsonSerializer.serializeLogLevel(builder, event.getLevel().toString());
4849
EcsJsonSerializer.serializeFormattedMessage(builder, event.getRenderedMessage());
4950
EcsJsonSerializer.serializeServiceName(builder, serviceName);
51+
EcsJsonSerializer.serializeEventDataset(builder, eventDataset);
5052
EcsJsonSerializer.serializeThreadName(builder, event.getThreadName());
5153
EcsJsonSerializer.serializeLoggerName(builder, event.getLoggerName());
5254
EcsJsonSerializer.serializeLabels(builder, event.getProperties(), topLevelLabels);
@@ -85,7 +87,7 @@ public boolean ignoresThrowable() {
8587

8688
@Override
8789
public void activateOptions() {
88-
90+
eventDataset = EcsJsonSerializer.computeEventDataset(eventDataset, serviceName);
8991
}
9092

9193
public void setServiceName(String serviceName) {
@@ -99,8 +101,12 @@ public void setIncludeOrigin(boolean includeOrigin) {
99101
public void setStackTraceAsArray(boolean stackTraceAsArray) {
100102
this.stackTraceAsArray = stackTraceAsArray;
101103
}
102-
104+
103105
public void addTopLevelLabel(String topLevelLabel) {
104106
this.topLevelLabels.add(topLevelLabel);
105107
}
108+
109+
public void setEventDataset(String eventDataset) {
110+
this.eventDataset = eventDataset;
111+
}
106112
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ void setUp() {
5353
ecsLayout.setStackTraceAsArray(true);
5454
ecsLayout.setIncludeOrigin(true);
5555
ecsLayout.addTopLevelLabel("top_level");
56+
ecsLayout.setEventDataset("testdataset.log");
57+
ecsLayout.activateOptions();
5658
appender.setLayout(ecsLayout);
5759
}
5860

log4j2-ecs-layout/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ Instead of the usual `<PatternLayout/>`, use `<EcsLayout serviceName="my-app"/>`
4343
|Parameter name |Type |Default|Description|
4444
|-----------------|-------|-------|-----------|
4545
|serviceName |String | |Sets the `service.name` field so you can filter your logs by a particular service |
46+
|eventDataset |String |`${serviceName}.log`|Sets the `event.dataset` field used by the machine learning job of the Logs app to look for anomalies in the log rate. |
4647
|topLevelLabels |String |`trace.id, transaction.id, span.id, error.id, service.name`|Usually, MDC keys are nested under [`labels`](https://www.elastic.co/guide/en/ecs/current/ecs-base.html). You can specify a comma-separated list of properties which should be on the top level. |
4748
|includeMarkers |boolean|`false`|Log [Markers](https://logging.apache.org/log4j/2.0/manual/markers.html) as [`tags`](https://www.elastic.co/guide/en/ecs/current/ecs-base.html) |
4849
|stackTraceAsArray|boolean|`false`|Serializes the [`error.stack_trace`](https://www.elastic.co/guide/en/ecs/current/ecs-error.html) as a JSON array where each element is in a new line to improve readability. Note that this requires a slightly more complex [Filebeat configuration](../README.md#when-stacktraceasarray-is-enabled).|

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

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,16 @@ public void accept(final String key, final Object value, final StringBuilder str
8484
private final Set<String> topLevelLabels;
8585
private final boolean stackTraceAsArray;
8686
private final String serviceName;
87+
private final String eventDataset;
8788
private final boolean includeMarkers;
8889
private final boolean includeOrigin;
8990
private final ConcurrentMap<Class<? extends MultiformatMessage>, Boolean> supportsJson = new ConcurrentHashMap<Class<? extends MultiformatMessage>, Boolean>();
9091
private final ObjectMessageJacksonSerializer objectMessageJacksonSerializer = ObjectMessageJacksonSerializer.Resolver.INSTANCE.resolve();
9192

92-
private EcsLayout(Configuration config, String serviceName, boolean includeMarkers, KeyValuePair[] additionalFields, Collection<String> topLevelLabels, boolean includeOrigin, boolean stackTraceAsArray) {
93+
private EcsLayout(Configuration config, String serviceName, String eventDataset, boolean includeMarkers, KeyValuePair[] additionalFields, Collection<String> topLevelLabels, boolean includeOrigin, boolean stackTraceAsArray) {
9394
super(config, UTF_8, null, null);
9495
this.serviceName = serviceName;
96+
this.eventDataset = eventDataset;
9597
this.includeMarkers = includeMarkers;
9698
this.topLevelLabels = new HashSet<String>(topLevelLabels);
9799
this.topLevelLabels.addAll(EcsJsonSerializer.DEFAULT_TOP_LEVEL_LABELS);
@@ -136,6 +138,7 @@ private StringBuilder toText(LogEvent event, StringBuilder builder, boolean gcFr
136138
EcsJsonSerializer.serializeLogLevel(builder, event.getLevel().toString());
137139
serializeMessage(builder, gcFree, event.getMessage(), event.getThrown());
138140
EcsJsonSerializer.serializeServiceName(builder, serviceName);
141+
EcsJsonSerializer.serializeEventDataset(builder, eventDataset);
139142
EcsJsonSerializer.serializeThreadName(builder, event.getThreadName());
140143
EcsJsonSerializer.serializeLoggerName(builder, event.getLoggerName());
141144
serializeLabels(event, builder);
@@ -326,12 +329,14 @@ public static class Builder extends AbstractStringLayout.Builder<EcsLayout.Build
326329

327330
@PluginBuilderAttribute("serviceName")
328331
private String serviceName;
332+
@PluginBuilderAttribute("eventDataset")
333+
private String eventDataset;
329334
@PluginBuilderAttribute("includeMarkers")
330335
private boolean includeMarkers = false;
331336
@PluginBuilderAttribute("stackTraceAsArray")
332337
private boolean stackTraceAsArray = false;
333338
@PluginElement("AdditionalField")
334-
private KeyValuePair[] additionalFields = new KeyValuePair[] {};
339+
private KeyValuePair[] additionalFields = new KeyValuePair[]{};
335340
@PluginBuilderAttribute("topLevelLabels")
336341
private String topLevelLabels;
337342
@PluginBuilderAttribute("includeOrigin")
@@ -350,6 +355,10 @@ public String getServiceName() {
350355
return serviceName;
351356
}
352357

358+
public String getEventDataset() {
359+
return eventDataset;
360+
}
361+
353362
public boolean isIncludeMarkers() {
354363
return includeMarkers;
355364
}
@@ -382,6 +391,11 @@ public EcsLayout.Builder setServiceName(final String serviceName) {
382391
return asBuilder();
383392
}
384393

394+
public EcsLayout.Builder setEventDataset(String eventDataset) {
395+
this.eventDataset = eventDataset;
396+
return asBuilder();
397+
}
398+
385399
public EcsLayout.Builder setIncludeMarkers(final boolean includeMarkers) {
386400
this.includeMarkers = includeMarkers;
387401
return asBuilder();
@@ -405,7 +419,7 @@ public EcsLayout build() {
405419
topLevelLabelsList.add(label.trim());
406420
}
407421
}
408-
return new EcsLayout(getConfiguration(), serviceName, includeMarkers, additionalFields, topLevelLabelsList, includeOrigin, stackTraceAsArray);
422+
return new EcsLayout(getConfiguration(), serviceName, EcsJsonSerializer.computeEventDataset(eventDataset, serviceName), includeMarkers, additionalFields, topLevelLabelsList, includeOrigin, stackTraceAsArray);
409423
}
410424

411425
public boolean isStackTraceAsArray() {

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ void setUp() {
7171
.setIncludeOrigin(true)
7272
.setStackTraceAsArray(true)
7373
.setTopLevelLabels("top_level")
74+
.setEventDataset("testdataset.log")
7475
.setAdditionalFields(new KeyValuePair[]{
7576
new KeyValuePair("cluster.uuid", "9fe9134b-20b0-465e-acf9-8cc09ac9053b"),
7677
new KeyValuePair("node.id", "${node.id}"),

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
</Properties>
66
<Appenders>
77
<List name="TestAppender">
8-
<EcsLayout serviceName="test" includeMarkers="true" includeOrigin="true" stackTraceAsArray="true" topLevelLabels="top_level">
8+
<EcsLayout serviceName="test" includeMarkers="true" includeOrigin="true" stackTraceAsArray="true" topLevelLabels="top_level"
9+
eventDataset="testdataset.log">
910
<KeyValuePair key="cluster.uuid" value="9fe9134b-20b0-465e-acf9-8cc09ac9053b"/>
1011
<KeyValuePair key="node.id" value="${node.id}"/>
1112
<KeyValuePair key="empty" value="${empty}"/>

logback-ecs-encoder/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ All you have to do is to use the `co.elastic.logging.logback.EcsEncoder` instead
5959
|Parameter name |Type |Default|Description|
6060
|-----------------|-------|-------|-----------|
6161
|serviceName |String | |Sets the `service.name` field so you can filter your logs by a particular service |
62+
|eventDataset |String |`${serviceName}.log`|Sets the `event.dataset` field used by the machine learning job of the Logs app to look for anomalies in the log rate. |
6263
|includeMarkers |boolean|`false`|Log [Markers](https://logging.apache.org/log4j/2.0/manual/markers.html) as [`tags`](https://www.elastic.co/guide/en/ecs/current/ecs-base.html) |
6364
|stackTraceAsArray|boolean|`false`|Serializes the [`error.stack_trace`](https://www.elastic.co/guide/en/ecs/current/ecs-error.html) as a JSON array where each element is in a new line to improve readability. Note that this requires a slightly more complex [Filebeat configuration](../README.md#when-stacktraceasarray-is-enabled).|
6465
|includeOrigin |boolean|`false`|If `true`, adds the [`log.origin.file.name`](https://www.elastic.co/guide/en/ecs/current/ecs-log.html), [`log.origin.file.line`](https://www.elastic.co/guide/en/ecs/current/ecs-log.html) and [`log.origin.function`](https://www.elastic.co/guide/en/ecs/current/ecs-log.html) fields. Note that you also have to set `includeLocation="true"` on your loggers and appenders if you are using the async ones. |

logback-ecs-encoder/src/main/java/co/elastic/logging/logback/EcsEncoder.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public class EcsEncoder extends EncoderBase<ILoggingEvent> {
4545
private static final Charset UTF_8 = Charset.forName("UTF-8");
4646
private boolean stackTraceAsArray = false;
4747
private String serviceName;
48+
private String eventDataset;
4849
private boolean includeMarkers = false;
4950
private ThrowableProxyConverter throwableProxyConverter;
5051
private Set<String> topLevelLabels = new HashSet<String>(EcsJsonSerializer.DEFAULT_TOP_LEVEL_LABELS);
@@ -61,6 +62,7 @@ public void start() {
6162
super.start();
6263
throwableProxyConverter = new ThrowableProxyConverter();
6364
throwableProxyConverter.start();
65+
eventDataset = EcsJsonSerializer.computeEventDataset(eventDataset, serviceName);
6466
}
6567

6668
@Override
@@ -71,6 +73,7 @@ public byte[] encode(ILoggingEvent event) {
7173
EcsJsonSerializer.serializeFormattedMessage(builder, event.getFormattedMessage());
7274
serializeMarkers(event, builder);
7375
EcsJsonSerializer.serializeServiceName(builder, serviceName);
76+
EcsJsonSerializer.serializeEventDataset(builder, eventDataset);
7477
EcsJsonSerializer.serializeThreadName(builder, event.getThreadName());
7578
EcsJsonSerializer.serializeLoggerName(builder, event.getLoggerName());
7679
serializeAdditionalFields(builder);
@@ -155,6 +158,10 @@ public void addAdditionalField(Pair pair) {
155158
this.additionalFields.add(pair);
156159
}
157160

161+
public void setEventDataset(String eventDataset) {
162+
this.eventDataset = eventDataset;
163+
}
164+
158165
public static class Pair {
159166
private String key;
160167
private String value = "";

0 commit comments

Comments
 (0)