elastic / elastic/ecs-logging-java

MDC values for event.type and event.category are not properly serialized as JSON arrays

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

説明

## Description
When using logback-ecs-encoder with SLF4J's MDC to set array-type fields (like event.type and event.category), the values are serialized as string literals instead of proper JSON arrays. While MDC only supports String values by design, the ECS encoder could detect and properly format string values that represent arrays for fields that are defined as arrays in the ECS specification.

## Current Behavior
When setting an array value in MDC (which only accepts strings):
```java
MDC.put("event.type", Arrays.asList("connection", "allowed").toString());
```

The current output in logs:

```json
{
"@timestamp": "2025-01-08T13:00:53.318Z",
"event.type": "[connection, allowed]",
// other fields...
}
```

## Expected Behaviour
The log output should contain a proper JSON array according to ECS specification:
```json
{
"@timestamp": "2025-01-08T13:00:53.318Z",
"event.type": ["connection", "allowed"],
// other fields...
}
```

## Technical Details
The issue is in `EcsJsonSerializer.serializeMDC()` where all MDC values are treated as string literals:
```java
builder.append("\":\"");
JsonUtils.quoteAsString(toNullSafeString(String.valueOf(entry.getValue())), builder);
builder.append("\",");
```

While we understand that MDC only supports string values, the ECS encoder could detect and properly format these string values for fields that are defined as arrays in the ECS specification.

## Impact
This limitation affects any field that should be an array according to ECS specification, particularly:

- event.type
- event.category
- tags
- labels

This makes it difficult to use the library with standard Java collections for fields that should be arrays according to the ECS specification.

## Suggested Solution
The serializer could:

- Check if the field name matches known array fields from ECS specification
- Check if the string value represents a list (e.g., starts with '[' and ends with ']')
- Parse and format such values as proper JSON arrays

Example implementation approach:

```java
private static final Set ARRAY_FIELDS = Set.of(
"event.type",
"event.category",
"tags",
"labels"
);

public static void serializeMDC(StringBuilder builder, Map properties) {
if (properties != null && !properties.isEmpty()) {
for (Map.Entry entry : properties.entrySet()) {
builder.append('\"');
String key = entry.getKey();
JsonUtils.quoteAsString(key, builder);

String value = toNullSafeString(String.valueOf(entry.getValue()));
if (value.startsWith("[") && value.endsWith("]")) {
List items = Arrays.stream(
value.substring(1, value.length() - 1)
.split(","))
.map(String::trim)
.collect(Collectors.toList());

builder.append("\":");
builder.append(formatAsJsonArray(items));
builder.append(",");
} else {
builder.append("\":\"");
JsonUtils.quoteAsString(toNullSafeString(String.valueOf(entry.getValue())), builder);
builder.append("\",");
}
}
}
}
```

## Environment

- logback-ecs-encoder version: 1.6.0
- slf4j-api version: 2.0.9
- Java version: 11
- Logback version: 1.4.12

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

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

調査の方向性

MDCの値が現在文字列として引用符で囲まれている EcsJsonSerializer.serializeMDC() から始め、issueで指定されているECSフィールド event.type、event.category、tags、labels を確認します。既存のJSONシリアライゼーションの動作を検証し、対応する配列値のMDCフィールドについて有効なJSON配列を出力し、それ以外のフィールドでは文字列としての処理を維持することを完了条件とします。

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

評価

技術スタック
java
領域
observability-sre
issue の種類
バグ
難易度
3/5
見積もり時間
1〜2日
活発さ
停滞
明瞭さ
おおむね明確
初心者へのやさしさ
38/100

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

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