Skip to content

Commit 806d815

Browse files
authored
Support additional fields in logback encoder (#59)
1 parent f946ae1 commit 806d815

File tree

5 files changed

+84
-1
lines changed

5 files changed

+84
-1
lines changed

logback-ecs-encoder/README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,16 @@ All you have to do is to use the `co.elastic.logging.logback.EcsEncoder` instead
6464
|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) |
6565
|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).|
6666
|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. |
67+
68+
To include any custom field in the output, use following syntax:
69+
70+
```xml
71+
<additionalField>
72+
<key>foo</key>
73+
<value>bar</value>
74+
</additionalField>
75+
<additionalField>
76+
<key>baz</key>
77+
<value>qux</value>
78+
</additionalField>
79+
```

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

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,14 @@
3030
import ch.qos.logback.classic.spi.ThrowableProxy;
3131
import ch.qos.logback.core.encoder.EncoderBase;
3232
import co.elastic.logging.EcsJsonSerializer;
33+
import co.elastic.logging.JsonUtils;
3334
import org.slf4j.Marker;
3435

3536
import java.nio.charset.Charset;
37+
import java.util.ArrayList;
3638
import java.util.HashSet;
3739
import java.util.Iterator;
40+
import java.util.List;
3841
import java.util.Set;
3942

4043
public class EcsEncoder extends EncoderBase<ILoggingEvent> {
@@ -46,6 +49,7 @@ public class EcsEncoder extends EncoderBase<ILoggingEvent> {
4649
private ThrowableProxyConverter throwableProxyConverter;
4750
private Set<String> topLevelLabels = new HashSet<String>(EcsJsonSerializer.DEFAULT_TOP_LEVEL_LABELS);
4851
private boolean includeOrigin;
52+
private List<Pair> additionalFields = new ArrayList<Pair>();
4953

5054
@Override
5155
public byte[] headerBytes() {
@@ -69,6 +73,7 @@ public byte[] encode(ILoggingEvent event) {
6973
EcsJsonSerializer.serializeServiceName(builder, serviceName);
7074
EcsJsonSerializer.serializeThreadName(builder, event.getThreadName());
7175
EcsJsonSerializer.serializeLoggerName(builder, event.getLoggerName());
76+
serializeAdditionalFields(builder);
7277
EcsJsonSerializer.serializeLabels(builder, event.getMDCPropertyMap(), topLevelLabels);
7378
if (includeOrigin) {
7479
StackTraceElement[] callerData = event.getCallerData();
@@ -86,7 +91,22 @@ public byte[] encode(ILoggingEvent event) {
8691
// all these allocations kinda hurt
8792
return builder.toString().getBytes(UTF_8);
8893
}
89-
94+
95+
private void serializeAdditionalFields(StringBuilder builder) {
96+
if (!additionalFields.isEmpty()) {
97+
for (int i = 0, size = additionalFields.size(); i < size; i++) {
98+
Pair additionalField = additionalFields.get(i);
99+
if (additionalField.getKey() != null) {
100+
builder.append('\"');
101+
JsonUtils.quoteAsString(additionalField.getKey(), builder);
102+
builder.append("\":\"");
103+
JsonUtils.quoteAsString(additionalField.getValue(), builder);
104+
builder.append("\",");
105+
}
106+
}
107+
}
108+
}
109+
90110
public void addTopLevelLabel(String topLevelLabel) {
91111
this.topLevelLabels.add(topLevelLabel);
92112
}
@@ -130,4 +150,37 @@ public void setStackTraceAsArray(boolean stackTraceAsArray) {
130150
public void setIncludeOrigin(boolean includeOrigin) {
131151
this.includeOrigin = includeOrigin;
132152
}
153+
154+
public void addAdditionalField(Pair pair) {
155+
this.additionalFields.add(pair);
156+
}
157+
158+
public static class Pair {
159+
private String key;
160+
private String value = "";
161+
162+
public Pair() {
163+
}
164+
165+
public Pair(String key, String value) {
166+
this.key = key;
167+
this.value = value;
168+
}
169+
170+
public String getKey() {
171+
return key;
172+
}
173+
174+
public void setKey(String key) {
175+
this.key = key;
176+
}
177+
178+
public String getValue() {
179+
return value;
180+
}
181+
182+
public void setValue(String value) {
183+
this.value = value;
184+
}
185+
}
133186
}

logback-ecs-encoder/src/test/java/co/elastic/logging/logback/AbstractEcsEncoderTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ public void debug(String message) {
4747
logger.debug(message);
4848
}
4949

50+
@Test
51+
void testAdditionalFields() throws Exception {
52+
debug("test");
53+
assertThat(getLastLogLine().get("foo").textValue()).isEqualTo("bar");
54+
assertThat(getLastLogLine().get("baz").textValue()).isEqualTo("qux");
55+
}
56+
5057
@Test
5158
void testMarker() throws Exception {
5259
Marker parent = MarkerFactory.getMarker("parent");

logback-ecs-encoder/src/test/java/co/elastic/logging/logback/EcsEncoderTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ void setUp() {
4747
ecsEncoder.setStackTraceAsArray(true);
4848
ecsEncoder.setIncludeOrigin(true);
4949
ecsEncoder.addTopLevelLabel("top_level");
50+
ecsEncoder.addAdditionalField(new EcsEncoder.Pair("foo", "bar"));
51+
ecsEncoder.addAdditionalField(new EcsEncoder.Pair("baz", "qux"));
5052
ecsEncoder.start();
5153
appender.setEncoder(ecsEncoder);
5254
appender.start();

logback-ecs-encoder/src/test/resources/logback-config.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@
77
<includeOrigin>true</includeOrigin>
88
<stackTraceAsArray>true</stackTraceAsArray>
99
<topLevelLabel>top_level</topLevelLabel>
10+
<additionalField>
11+
<key>foo</key>
12+
<value>bar</value>
13+
</additionalField>
14+
<additionalField>
15+
<key>baz</key>
16+
<value>qux</value>
17+
</additionalField>
1018
</encoder>
1119
</appender>
1220
<root level="DEBUG">

0 commit comments

Comments
 (0)