Snippets · Processors
Drop health-check logs and spans
Liveness and readiness probes hit every pod every few seconds, and each hit can produce a log line and a span that nobody will ever read. This filter processor drops log records and spans whose url.path is a health, readiness or liveness endpoint. The regex is anchored, so /api/health-insurance/quotes is kept.
OpenTelemetry Collector
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
processors:
memory_limiter:
check_interval: 1s
limit_percentage: 80
spike_limit_percentage: 25
# Drops probe traffic: log records and spans whose url.path is a health,
# readiness or liveness endpoint.
filter/drop-health-checks:
error_mode: ignore
logs:
log_record:
- IsMatch(attributes["url.path"], "^/(health|healthz|ready|readyz|live|livez)$")
traces:
span:
- IsMatch(attributes["url.path"], "^/(health|healthz|ready|readyz|live|livez)$")
batch:
timeout: 5s
exporters:
otlphttp:
endpoint: https://your-backend:4318
service:
pipelines:
logs:
receivers: [otlp]
processors: [memory_limiter, filter/drop-health-checks, batch]
exporters: [otlphttp]
traces:
receivers: [otlp]
processors: [memory_limiter, filter/drop-health-checks, batch]
exporters: [otlphttp]
LinkMesh
LinkMesh has no built-in template for this job. Add it as a custom processor in raw mode, with filter as the component type and this body - the same lines as under filter/drop-health-checks in the collector config:
error_mode: ignore
logs:
log_record:
- IsMatch(attributes["url.path"], "^/(health|healthz|ready|readyz|live|livez)$")
traces:
span:
- IsMatch(attributes["url.path"], "^/(health|healthz|ready|readyz|live|livez)$")
How custom components are validated and rolled out: create a custom processor.
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.
5 log records in, 3 log records out
Before
- body
- GET /healthz 200
- attributes.http.request.method
- GET
- attributes.url.path
- /healthz
- attributes.http.response.status_code
- 200
- resource.service.name
- checkout
After
Dropped
Before
- body
- GET /readyz 200
- attributes.http.request.method
- GET
- attributes.url.path
- /readyz
- attributes.http.response.status_code
- 200
- resource.service.name
- checkout
After
Dropped
Before
- body
- POST /orders 201
- attributes.http.request.method
- POST
- attributes.url.path
- /orders
- attributes.http.response.status_code
- 201
- resource.service.name
- checkout
After
- body
- POST /orders 201
- attributes.http.request.method
- POST
- attributes.url.path
- /orders
- attributes.http.response.status_code
- 201
- resource.service.name
- checkout
Before
- body
- GET /healthz 200
- resource.service.name
- checkout
After
- body
- GET /healthz 200
- resource.service.name
- checkout
Before
- body
- GET /api/health-insurance/quotes 200
- attributes.url.path
- /api/health-insurance/quotes
- resource.service.name
- checkout
After
- body
- GET /api/health-insurance/quotes 200
- attributes.url.path
- /api/health-insurance/quotes
- resource.service.name
- checkout
3 spans in, 2 spans out
Before
- span
- GET /healthz
- attributes.url.path
- /healthz
- resource.service.name
- checkout
After
Dropped
Before
- span
- GET /healthz
- attributes.http.target
- /healthz
- resource.service.name
- checkout
After
- span
- GET /healthz
- attributes.http.target
- /healthz
- resource.service.name
- checkout
Before
- span
- POST /orders
- attributes.url.path
- /orders
- resource.service.name
- checkout
After
- span
- POST /orders
- attributes.url.path
- /orders
- resource.service.name
- checkout
The gotcha
It matches the url.path attribute, and only that. In our test two probes got through: a log line that carried "GET /healthz" only in its body, and a span from older instrumentation that set http.target instead of url.path. 5 log records in, 3 out; 3 spans in, 2 out. Check which attribute your instrumentation sets before you rely on 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).
Doing this in LinkMesh: Drop noisy logs
Related snippets
- Drop all telemetry from a serviceDrop everything a load generator or synthetic probe sends, by service.name, across logs, metrics and traces.
- Drop the collector's own metricsKeep the collector's own otelcol_* metrics out of the application metrics you pay to store.
- Filter logs by severity (WARN and above)Drop DEBUG and INFO on the collector, without silently losing the logs that never set a severity.
- Keep only error logsShip only ERROR and FATAL log records from a noisy source, and drop the rest on the collector.