Snippets · Pipelines
Windows event logs, reduced: noisy events dropped, rendered text removed
The windowseventlog receiver turns every event into a structured body: provider, event_id, level, event_data and more. It also carries the event's rendered text - and carries it twice. This config drops events by provider and id that rarely matter (Service Control Manager 7036 "service entered the running state", Security-SPP 16384) and deletes the rendered text, keeping the structured fields. On a GitLab Windows Server runner, reading System and Application from the beginning, it cut 4,519 events to 3,553 and the body bytes by 51%.
- Signals
- Logs
- Category
- CollectionReduction
- Source
- Windows Event Log (System, Application)
- Destination
- OTLP/HTTP endpoint
Included steps
- Read the System and Application channels
- Drop noisy events by provider and id
- Delete the rendered text (message, rendering_info)
- memory_limiter first, batch last
OpenTelemetry Collector
receivers:
windowseventlog/system:
channel: System
windowseventlog/application:
channel: Application
processors:
memory_limiter:
check_interval: 1s
limit_percentage: 80
spike_limit_percentage: 25
# Noisy, low-value events, by provider and id. Extend with your own.
filter/noisy-events:
error_mode: ignore
logs:
log_record:
- body["provider"]["name"] == "Microsoft-Windows-Security-SPP" and body["event_id"]["id"] == 16384
- body["provider"]["name"] == "Service Control Manager" and body["event_id"]["id"] == 7036
# The rendered text is in the body twice - message, and again in
# rendering_info - and repeats event_data in prose. Keep the structured fields.
transform/drop-rendered:
error_mode: ignore
log_statements:
- context: log
statements:
- delete_key(body, "message")
- delete_key(body, "rendering_info")
batch:
timeout: 5s
exporters:
otlphttp:
endpoint: https://your-backend:4318
service:
pipelines:
logs:
receivers: [windowseventlog/system, windowseventlog/application]
processors: [memory_limiter, filter/noisy-events, transform/drop-rendered, batch]
exporters: [otlphttp]
LinkMesh
Library › Sources › Windows Event Log
- Channel
- System
- Max Reads
- 100
- Start At
- end
What LinkMesh then pushes to the collector, under receivers:
windowseventlog/input_src_00000501:
channel: System
max_reads: 100
start_at: end
The same, as an API call (see automation recipes):
curl -X POST "$LINKMESH/sources" \
-H "Authorization: Bearer $LMSAT" \
-H "Content-Type: application/json" \
-d '{
"defaultConfig": {
"channel": "System",
"max_reads": 100,
"start_at": "end"
},
"name": "Windows Event Log",
"receiverType": "windowseventlog"
}'Library › Sources › Windows Event Log
- Channel
- Application
- Max Reads
- 100
- Start At
- end
What LinkMesh then pushes to the collector, under receivers:
windowseventlog/input_src_00000501:
channel: Application
max_reads: 100
start_at: end
The same, as an API call (see automation recipes):
curl -X POST "$LINKMESH/sources" \
-H "Authorization: Bearer $LMSAT" \
-H "Content-Type: application/json" \
-d '{
"defaultConfig": {
"channel": "Application",
"max_reads": 100,
"start_at": "end"
},
"name": "Windows Event Log",
"receiverType": "windowseventlog"
}'The rest of the collector config above (memory_limiter, filter, transform, batch, otlphttp) is not part of these templates: 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 on Windows 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.
The gotcha
The rendered text is in the body twice: in message and again in rendering_info.message. On our runner rendering_info was the largest key of all - 25% of the body bytes, against 12% for message - so deleting only message, as most examples do, leaves most of the saving on the table. This config deletes both.
What it does not catch
No before/after table: the receiver exists only in the Windows build of the collector (on macOS, validate stops with "windows eventlog receiver is only supported on Windows"), and the behaviour harness runs on Linux. The figures above are from a measured run on a GitLab SaaS Windows runner; CI validates this config there on every change to it.
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).
Related snippets
- Collect Windows Event Log (Application, System, Security)Application, System and Security events as structured logs - provider, event id, level, event data - without the rendered text twice over.
- Drop sensitive attributes before exportDelete named attributes, and every captured HTTP request header, from logs, spans and metrics before they are exported.
- Drop all telemetry from a serviceDrop everything a load generator or synthetic probe sends, by service.name, across logs, metrics and traces.
- Drop health-check logs and spansStop paying to store Kubernetes probe traffic: drop /healthz, /readyz and /livez logs and spans on the collector.