elastic / elastic/ecs-logging-java

feature request: objectMessageAsJsonObject

オープン
#187 コメント 1 件 リアクション 1 件 担当者 0 名 GitHub で見る
agent-java community triage
主要言語
Java
スター
148
フォーク
82
平均マージ
2日 17時間
マージ済み PR(30日)
3

説明

Log4j2 `ObjectMessage`s are automatically converted to json objects.
This makes the log statements fail, if the object cannot be converted to json or it generates invalid json.

I would propose a `objectMessageAsJsonObject` config.
Putting it to false would just put the objects `toString()` result into the `message` field, as described in the documentation of [log4j2](https://logging.apache.org/log4j/2.x/manual/messages.html#ObjectMessage).

e.g.

```java
public class EcsLogTest {

static class A {
String getA() {
Objects.requireNonNull(null);
return null;
}
}

@Test
void test() {
LogManager.getLogger().info(new A());
}
}
```
produces:

```
{"@timestamp":"2022-05-16T12:06:08.284Z", "log.level": "INFO", , "ecs.version": "1.2.0","process.thread.name":"main","log.logger":"EcsLogTest"}
```

This patch would probably enough to implement this feature:

```diff
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 1a99742..41937c7 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
@@ -79,9 +79,10 @@ public class EcsLayout extends AbstractStringLayout {
private final boolean includeOrigin;
private final PatternFormatter[] exceptionPatternFormatter;
private final ConcurrentMap, Boolean> supportsJson = new ConcurrentHashMap, Boolean>();
+ private final boolean objectMessageAsJsonObject;

private EcsLayout(Configuration config, String serviceName, String serviceVersion, String serviceEnvironment, String serviceNodeName, String eventDataset, boolean includeMarkers,
- KeyValuePair[] additionalFields, boolean includeOrigin, String exceptionPattern, boolean stackTraceAsArray) {
+ KeyValuePair[] additionalFields, boolean includeOrigin, String exceptionPattern, boolean stackTraceAsArray, boolean objectMessageAsJsonObject) {
super(config, UTF_8, null, null);
this.serviceName = serviceName;
this.serviceVersion = serviceVersion;
@@ -92,6 +93,7 @@ public class EcsLayout extends AbstractStringLayout {
this.includeOrigin = includeOrigin;
this.stackTraceAsArray = stackTraceAsArray;
this.additionalFields = additionalFields;
+ this.objectMessageAsJsonObject = objectMessageAsJsonObject;
fieldValuePatternFormatter = new PatternFormatter[additionalFields.length][];
for (int i = 0; i < additionalFields.length; i++) {
KeyValuePair additionalField = additionalFields[i];
@@ -253,7 +255,7 @@ public class EcsLayout extends AbstractStringLayout {
} else {
serializeSimpleMessage(builder, gcFree, message, thrown);
}
- } else if (JACKSON_SERIALIZER != null && message instanceof ObjectMessage) {
+ } else if (JACKSON_SERIALIZER != null && message instanceof ObjectMessage && objectMessageAsJsonObject) {
final StringBuilder jsonBuffer = EcsJsonSerializer.getMessageStringBuilder();
JACKSON_SERIALIZER.formatTo(jsonBuffer, (ObjectMessage) message);
addJson(builder, jsonBuffer);
@@ -377,6 +379,8 @@ public class EcsLayout extends AbstractStringLayout {
private KeyValuePair[] additionalFields = new KeyValuePair[]{};
@PluginBuilderAttribute("includeOrigin")
private boolean includeOrigin = false;
+ @PluginBuilderAttribute("objectMessageAsJsonObject")
+ private boolean objectMessageAsJsonObject = true;

Builder() {
}
@@ -428,6 +432,10 @@ public class EcsLayout extends AbstractStringLayout {
return exceptionPattern;
}

+ public boolean isObjectMessageAsJsonObject() {
+ return objectMessageAsJsonObject;
+ }
+
/**
* Additional fields to set on each log event.
*
@@ -483,11 +491,16 @@ public class EcsLayout extends AbstractStringLayout {
return this;
}

+ public EcsLayout.Builder setObjectMessageAsJsonObject(boolean objectMessageAsJsonObject) {
+ this.objectMessageAsJsonObject = objectMessageAsJsonObject;
+ return this;
+ }
+
@Override
public EcsLayout build() {
return new EcsLayout(getConfiguration(), serviceName, serviceVersion, serviceEnvironment, serviceNodeName,
EcsJsonSerializer.computeEventDataset(eventDataset, serviceName),
- includeMarkers, additionalFields, includeOrigin, exceptionPattern, stackTraceAsArray);
+ includeMarkers, additionalFields, includeOrigin, exceptionPattern, stackTraceAsArray, objectMessageAsJsonObject);
}
}
}
```

コントリビューションガイド

コントリビューションガイドを開く

調査の方向性

log4j2-ecs-layout/src/main/java/co/elastic/logging/log4j2/EcsLayout.java から始め、ObjectMessage の処理と EcsLayout.Builder の設定を調べます。失敗するケースを含め、EcsLogTest で示されている動作を確認し、その後、オブジェクトから JSON への変換を無効にする場合のカバレッジを追加します。設定が false を受け入れ、オブジェクトの toString() の結果が message フィールドに出力されれば完了です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
java
領域
observability
issue の種類
機能追加
難易度
3/5
見積もり時間
1〜2日
活発さ
停滞
明瞭さ
明確に書かれている
初心者へのやさしさ
35/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。