LinkMesh

Search docs, blog and changelog

ENDE

Snippets · Processors

Drop sensitive attributes before export

Some attributes should never leave the host - captured cookies and Authorization headers, a user's e-mail, a session ID - and some are simply too expensive to store. delete_key removes one key by name; delete_matching_keys removes every key matching a pattern, which is how this config catches all http.request.header.* attributes at once.

Signals
LogsMetricsTraces
Category
ReductionCompliance
Source
OTLP
Components
otlpbatchmemory_limitertransformotlphttp
Destination
OTLP/HTTP endpoint

OpenTelemetry Collector

OpenTelemetry Collector YAML
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317

processors:
  memory_limiter:
    check_interval: 1s
    limit_percentage: 80
    spike_limit_percentage: 25
  # Removes named attributes, and every captured HTTP request header, from
  # log records, spans and metric data points.
  transform/drop-attributes:
    error_mode: ignore
    log_statements:
      - context: log
        statements:
          - delete_key(attributes, "user.email")
          - delete_key(attributes, "session.id")
          - delete_matching_keys(attributes, "^http\\.request\\.header\\..*")
    trace_statements:
      - context: span
        statements:
          - delete_key(attributes, "user.email")
          - delete_key(attributes, "session.id")
          - delete_matching_keys(attributes, "^http\\.request\\.header\\..*")
    metric_statements:
      - context: datapoint
        statements:
          - delete_key(attributes, "user.email")
          - delete_key(attributes, "session.id")
  batch:
    timeout: 5s

exporters:
  otlphttp:
    endpoint: https://your-backend:4318

service:
  pipelines:
    logs:
      receivers: [otlp]
      processors: [memory_limiter, transform/drop-attributes, batch]
      exporters: [otlphttp]
    traces:
      receivers: [otlp]
      processors: [memory_limiter, transform/drop-attributes, batch]
      exporters: [otlphttp]
    metrics:
      receivers: [otlp]
      processors: [memory_limiter, transform/drop-attributes, batch]
      exporters: [otlphttp]

LinkMesh

LinkMesh has no built-in template for this job. Add it as a custom processor in raw mode, with transform as the component type and this body - the same lines as under transform/drop-attributes in the collector config:

Custom processor body (transform)
error_mode: ignore
log_statements:
  - context: log
    statements:
      - delete_key(attributes, "user.email")
      - delete_key(attributes, "session.id")
      - delete_matching_keys(attributes, "^http\\.request\\.header\\..*")
trace_statements:
  - context: span
    statements:
      - delete_key(attributes, "user.email")
      - delete_key(attributes, "session.id")
      - delete_matching_keys(attributes, "^http\\.request\\.header\\..*")
metric_statements:
  - context: datapoint
    statements:
      - delete_key(attributes, "user.email")
      - delete_key(attributes, "session.id")

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.

1 log record in, 1 log record out

  1. Before

    body
    GET /cart 200
    attributes.http.request.method
    GET
    attributes.http.request.header.cookie
    sid=abc
    attributes.http.request.header.authorization
    Bearer x
    attributes.user.email
    anna.meier@example.ch
    attributes.session.id
    s-81723
    attributes.url.path
    /cart
    resource.service.name
    shop
    resource.user.email
    ops@example.ch

    After

    body
    GET /cart 200
    attributes.http.request.method
    GET
    attributes.url.path
    /cart
    resource.service.name
    shop
    resource.user.email
    ops@example.ch

The gotcha

These statements run on the record: a log record, a span, a data point. The same key set on the resource is untouched. In our test user.email was deleted from the log record and arrived intact on the resource. To remove it there too, add a resource context with delete_key(attributes, "user.email").

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: Mask PII