Snippets · Sources
Parse JSON log lines into attributes
Applications that log JSON lines already did the hard part; the collector only has to read the fields. The json_parser operator on the filelog receiver turns every top-level field into a log attribute, types included: numbers stay numbers and booleans stay booleans.
- Signals
- Logs
- Category
- CollectionParsing
- Source
- Log files (JSON lines)
- Components
- filelogbatchmemory_limiterotlphttp
- Destination
- OTLP/HTTP endpoint
OpenTelemetry Collector
extensions:
file_storage:
directory: /var/lib/otelcol/storage
create_directory: true
receivers:
filelog:
include: [/var/log/myapp/*.json.log]
start_at: end
storage: file_storage
operators:
# Every top-level JSON field becomes a log attribute; the original
# line stays in the body.
- type: json_parser
parse_from: body
parse_to: attributes
on_error: send
processors:
memory_limiter:
check_interval: 1s
limit_percentage: 80
spike_limit_percentage: 25
batch:
timeout: 5s
exporters:
otlphttp:
endpoint: https://your-backend:4318
service:
extensions: [file_storage]
pipelines:
logs:
receivers: [filelog]
processors: [memory_limiter, batch]
exporters: [otlphttp]
LinkMesh
Library › Processors › JSON Log Parser
LinkMesh adds these operators to the source's receiver (filelog/input_src_00000501):
operators:
- parse_from: body
type: json_parser
The same, as an API call (see automation recipes):
curl -X POST "$LINKMESH/pipelines" \
-H "Authorization: Bearer $LMSAT" \
-H "Content-Type: application/json" \
-d '{
"name": "JSON Log Parser",
"processors": [
{
"config": {},
"enabled": true,
"order": 1,
"templateSlug": "json-log-parser"
}
]
}'The rest of the collector config above (memory_limiter, batch, otlphttp) is not part of this template: in LinkMesh those are separate sources, processors and destinations on the route.
Generated from LinkMesh's template catalogue by linkmesh-server snippet-render 1.464.3, not written by hand.
Download config.yamlValidated with otelcol-contrib v0.161.0 on 2026-10-26
Complete config files, each checked with the collector's own validate command (otelcol-contrib v0.161.0). Replace https://your-backend:4318 with your own OTLP endpoint before you run it.
Before and after
Example telemetry in, and what this exact config sent out when we ran it in otelcol-contrib v0.161.0. CI re-runs it on every change and fails if the output differs. Changed values are highlighted.
3 log records in, 3 log records out
Before
- body
- {"level":"info","msg":"user signed in","user":"u-4711","duration_ms":12}
After
- body
- {"level":"info","msg":"user signed in","user":"u-4711","duration_ms":12}
- attributes.log.file.name
- input.log
- attributes.duration_ms
- 12
- attributes.level
- info
- attributes.msg
- user signed in
- attributes.user
- u-4711
Before
- body
- {"level":"error","msg":"payment provider timeout","order":"1002","retry":true}
After
- body
- {"level":"error","msg":"payment provider timeout","order":"1002","retry":true}
- attributes.log.file.name
- input.log
- attributes.retry
- true
- attributes.level
- error
- attributes.msg
- payment provider timeout
- attributes.order
- 1002
Before
- body
- WARN legacy line that is not JSON
After
- body
- WARN legacy line that is not JSON
- attributes.log.file.name
- input.log
The gotcha
A line that is not JSON is not dropped. With on_error: send it is shipped unparsed, with its raw text as the body and no attributes, and the collector logs an error for it: in our test the third line, plain text, arrived as-is next to two parsed ones. Mixed-format files produce a log error per plain line; on_error: send_quiet ships them without the noise.
Manage this across a fleet
LinkMesh manages collector configuration across a fleet from one self-hosted control plane, so a change like this is made once rather than host by host. The first 25 Collectors are free after a no-card registration in the OpenSight Customer Portal (5 without one).
Doing this in LinkMesh: Sources
Related snippets
- Parse Apache access logs into semantic conventionsTurn Apache combined-format access log lines into semantic-convention attributes, with typed status codes and sizes.
- Parse key=value log linesTurn logfmt-style key=value lines into attributes, quoted values with spaces included.
- Parse nginx access logs into semantic conventionsTurn nginx combined-format access log lines into OpenTelemetry semantic-convention attributes, with typed status codes.
- Map your log levels to OpenTelemetry severitySet severity_number from your level field, including names like warning, err and crit, so severity filters work.