LinkMesh

Search docs, blog and changelog

ENDE

Snippets · Processors

Redact everything except an attribute allowlist

Masking by pattern only catches what you thought of. The redaction processor works the other way round: list the attribute keys you need, and every other key is removed before export, including the ones a developer adds next month. Values on kept keys that match a blocked pattern are replaced with ****. Use it where an unknown attribute is a bigger risk than a missing one; use the mask-pii snippet when you want the record intact and only the value rewritten.

Signals
Logs
Category
Compliance
Source
OTLP
Components
otlpbatchmemory_limiterotlphttp
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
  # Keeps only the attribute keys listed, removes every other one, and masks
  # any kept value that matches a blocked pattern.
  redaction:
    allow_all_keys: false
    allowed_keys:
      # Resource attributes are redacted too: without these the backend
      # receives every record as an unknown service.
      - service.name
      - service.namespace
      - deployment.environment.name
      - host.name
      # Record attributes this pipeline needs.
      - http.request.method
      - http.response.status_code
      - http.route
      - url.path
      - user.email
    blocked_values:
      - "[A-Za-z0-9._%+-]+@[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*\\.[A-Za-z]{2,}"
      - "\\b(4[0-9]{3}|5[1-5][0-9]{2}|2[2-7][0-9]{2})([ -]?[0-9]{4}){3}\\b"
    summary: info
  batch:
    timeout: 5s

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

service:
  pipelines:
    logs:
      receivers: [otlp]
      processors: [memory_limiter, redaction, batch]
      exporters: [otlphttp]

LinkMesh

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

Custom processor body (redaction)
allow_all_keys: false
allowed_keys:
  - service.name
  - service.namespace
  - deployment.environment.name
  - host.name
  - http.request.method
  - http.response.status_code
  - http.route
  - url.path
  - user.email
blocked_values:
  - "[A-Za-z0-9._%+-]+@[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*\\.[A-Za-z]{2,}"
  - "\\b(4[0-9]{3}|5[1-5][0-9]{2}|2[2-7][0-9]{2})([ -]?[0-9]{4}){3}\\b"
summary: info

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
    checkout failed for anna.meier@example.ch
    attributes.http.request.method
    POST
    attributes.http.route
    /checkout
    attributes.http.response.status_code
    502
    attributes.user.email
    anna.meier@example.ch
    attributes.http.request.header.authorization
    Bearer abc
    attributes.session.id
    s-81723
    resource.service.name
    shop
    resource.host.name
    web-1

    After

    body
    checkout failed for ****
    attributes.http.request.method
    POST
    attributes.http.route
    /checkout
    attributes.http.response.status_code
    502
    attributes.user.email
    ****
    attributes.redaction.redacted.count
    2
    attributes.redaction.masked.count
    1
    attributes.redaction.body.masked.count
    1
    resource.service.name
    shop
    resource.host.name
    web-1

The gotcha

The allowlist applies to resource attributes too. In our test, with only record-level keys listed, service.name and host.name were removed from the resource, so the records left the collector with no service name at all. That is why service.name, service.namespace, deployment.environment.name and host.name are on the list here. The processor also masked the blocked e-mail pattern in the log body, not only in attributes.

What it does not catch

It removes and masks keys and values, it does not inspect meaning: a name or address in a kept attribute or in the body passes through unless a blocked_values pattern matches it. summary: info adds redaction.* count attributes to each record; set summary: silent if your backend should not see them.

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: Create a custom processor