Open5
既存のログをopentelemetryで送りたい

jsonでローカルに出力されているログがある (/app/log/production.json
に出力しているとする)
これをopentelemetryの形式で送りたい。

opentelemetry-collectorにある、File Log Exporterを使えば送れる。
たとえば、下のconfigを書けばいい。
receivers:
filelog:
include:
- /app/log/production.json
exporters:
debug:
verbosity: detailed
service:
pipelines:
logs:
receivers: [filelog]
exporters: [debug]
実行例:
- dockerでotel-collector起動
docker run -v $(pwd)/config.yaml:/etc/otelcol-contrib/config.yaml -v $(pwd)/log.json:/app/log/production.json otel/opentelemetry-collector-contrib:latest`
- ログを書く
echo '{"hello": "world", "span_id": "951b4fe22451495a", "trace_id": "951b4fe22451495aaa5a79e9ff254fa0"}' >> log.json
- dockerのstdoutを見ると、ログが取り込まれたことがわかる
Resource SchemaURL: ScopeLogs #0 ScopeLogs SchemaURL: InstrumentationScope LogRecord #0 ObservedTimestamp: 2025-09-06 11:30:18.032015596 +0000 UTC Timestamp: 1970-01-01 00:00:00 +0000 UTC SeverityText: SeverityNumber: Unspecified(0) Body: Str({"hello": "world", "span_id": "951b4fe22451495a", "trace_id": "951b4fe22451495aaa5a79e9ff254fa0"}) Attributes: -> log.file.name: Str(production.json) Trace ID: Span ID: Flags: 0 {"resource": {"service.instance.id": "cd0ef880-afbf-447a-b19d-1882d5485169", "service.name": "otelcol-contrib", "service.version": "0.134.0"}, "otelcol.component.id": "debug", "otelcol.component.kind": "exporter", "otelcol.signal": "logs"}

ただし、上の例だとTrace ID
とSpan ID
が空白になっていて、trace_idが紐付いていないことがわかる。
紐付いていなくても検索はできるけれど、紐付いていたほうがotelに則っているから、都合が良いことがあるはず。
紐付けたい

operators
を使って、ログの内容を変えればいい。
つまり、File Log Receiver
をこう書けばいい。
receivers:
filelog:
include:
- /app/log/production.json
operators:
- type: json_parser
parse_from: body
parse_to: attributes.tmp
- type: trace_parser
trace_id:
parse_from: attributes.tmp.trace_id
span_id:
parse_from: attributes.tmp.span_id
- type: remove
field: attributes.tmp
すると、Trace ID
とSpan ID
が増える。
...
SeverityNumber: Unspecified(0)
Body: Str({"hello": "world", "span_id": "951b4fe22451495a", "trace_id": "951b4fe22451495aaa5a79e9ff254fa0"})
Attributes:
-> log.file.name: Str(production.json)
+ Trace ID: 951b4fe22451495aaa5a79e9ff254fa0
+ Span ID: 951b4fe22451495a
- Trace ID:
- Span ID:
Flags: 0
{"resource": {"service.instance.id": "5fb1aac0-c76e-41b2-a569-b4e39824df7e", "service.name": "otelcol-contrib", "service.version": "0.134.0"}, "otelcol.component.id": "debug", "otelcol.component.kind": "exporter", "otelcol.signal": "logs"}
operators
に書いた内容は、
- ファイルの内容(body)をパースする
- type: json_parser parse_from: body parse_to: attributes.tmp
- パース結果(attributes.tmp)からtrace_idとspan_idを抜き出す
- type: trace_parser trace_id: parse_from: attributes.tmp.trace_id span_id: parse_from: attributes.tmp.span_id
- パース結果を削除する
- type: remove field: attributes.tmp

紐付いた。
あとは出力先をstdoutから適当なバックエンドに変えればいい。
(attributes.tmp
を経由しているのが気持ち悪いが、動いたからよしとする)
これで、既存のファイルをotelで出力できるようになった。
以上