How to redact sensitive attributes in the OpenTelemetry Collector

Redacting sensitive attributes in the OpenTelemetry Collector keeps secrets, personal identifiers, and payment-like values out of exported telemetry. The Collector can scrub records after receivers accept them and before exporters send them to an observability backend.

The redaction processor in the Collector Contrib distribution removes attributes that are not explicitly allowed and masks values that match blocked regular expressions. It belongs in the pipeline before the exporter that would otherwise send the original span, log, or metric datapoint.

Use an allowlist that keeps operational fields such as service.name and http.route while removing risky custom fields. Keep the processor summary set to debug only while testing because summary attributes can reveal the names of removed keys; use info or silent for normal traffic.

Steps to redact sensitive Collector attributes:

  1. Open the active Collector Contrib configuration file.
    $ sudoedit /etc/otelcol-contrib/config.yaml

    Use the path and binary name from the running distribution. The redaction processor is included in otelcol-contrib and the Kubernetes distribution, not every custom Collector build.

  2. Add the redaction processor before the exporter in the target pipeline.
    /etc/otelcol-contrib/config.yaml
    receivers:
      otlp:
        protocols:
          http:
            endpoint: 0.0.0.0:4318
    
    processors:
      redaction:
        allow_all_keys: false
        allowed_keys:
          - service.name
          - http.route
          - description
        blocked_values:
          - "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"
          - "4[0-9]{12}(?:[0-9]{3})?"
        summary: debug
    
    exporters:
      debug:
        verbosity: detailed
    
    service:
      pipelines:
        traces:
          receivers: [otlp]
          processors: [redaction]
          exporters: [debug]

    allow_all_keys: false makes the processor fail closed. Only keys listed under allowed_keys remain, and blocked_values masks matching substrings inside allowed attribute values.

    debug exporter output and summary: debug are for validation only. Both can write telemetry details or removed key names to Collector logs.

  3. Validate the Collector configuration.
    $ otelcol-contrib validate --config=/etc/otelcol-contrib/config.yaml

    No output with a zero exit status means the file parsed and the referenced receiver, processor, exporter, and pipeline exist in the Collector build.

  4. Start the Collector with the redaction configuration.
    $ otelcol-contrib --config=/etc/otelcol-contrib/config.yaml
    2026-06-18T07:29:33.165Z info Starting HTTP server {"otelcol.component.id":"otlp","otelcol.component.kind":"receiver","endpoint":"[::]:4318"}
    2026-06-18T07:29:33.165Z info Everything is ready. Begin running and processing data.

    For a packaged service, restart the otelcol-contrib unit and read the same startup lines from the service logs.

  5. Create an OTLP/HTTP trace payload with safe and sensitive attributes.
    trace.json
    {
      "resourceSpans": [
        {
          "resource": {
            "attributes": [
              {
                "key": "service.name",
                "value": {
                  "stringValue": "checkout-api"
                }
              }
            ]
          },
          "scopeSpans": [
            {
              "scope": {
                "name": "manual-redaction-smoke"
              },
              "spans": [
                {
                  "traceId": "5b8efff798038103d269b633813fc60c",
                  "spanId": "eee19b7ec3c1b174",
                  "name": "checkout",
                  "kind": 1,
                  "startTimeUnixNano": "1717260000000000000",
                  "endTimeUnixNano": "1717260001000000000",
                  "attributes": [
                    {
                      "key": "http.route",
                      "value": {
                        "stringValue": "/checkout"
                      }
                    },
                    {
                      "key": "description",
                      "value": {
                        "stringValue": "customer alice@example.com paid with 4111111111111111"
                      }
                    },
                    {
                      "key": "user.email",
                      "value": {
                        "stringValue": "alice@example.com"
                      }
                    },
                    {
                      "key": "session.token",
                      "value": {
                        "stringValue": "Bearer eyJhbGciOiJIUzI1NiJ9.example"
                      }
                    }
                  ]
                }
              ]
            }
          ]
        }
      ]
    }

    The payload uses synthetic values only. service.name and http.route should remain, description should be masked, and user.email plus session.token should be removed.

  6. Send the trace payload to the local OTLP/HTTP receiver.
    $ curl --silent --show-error --include --request POST http://127.0.0.1:4318/v1/traces \
      --header 'Content-Type: application/json' \
      --data @trace.json
    HTTP/1.1 200 OK
    Content-Type: application/json
    Content-Length: 21
    
    {"partialSuccess":{}}

    The 200 OK response confirms that the receiver accepted the trace. The redaction result appears in the Collector terminal because the pipeline exports to debug.

  7. Inspect the debug exporter output for the redacted attributes.
    2026-06-18T07:29:54.707Z info ResourceSpans #0
    Resource attributes:
         -> service.name: Str(checkout-api)
    ScopeSpans #0
    InstrumentationScope manual-redaction-smoke
    Span #0
        Trace ID       : 5b8efff798038103d269b633813fc60c
        ID             : eee19b7ec3c1b174
        Name           : checkout
    Attributes:
         -> http.route: Str(/checkout)
         -> description: Str(customer **** paid with ****)
         -> redaction.redacted.keys: Str(session.token,user.email)
         -> redaction.redacted.count: Int(2)
         -> redaction.masked.keys: Str(description)
         -> redaction.masked.count: Int(1)

    service.name and http.route passed through, sensitive substrings inside description were masked, and the unapproved session.token and user.email attributes were removed.

  8. Replace the test exporter settings before normal export.
    /etc/otelcol-contrib/config.yaml
    processors:
      redaction:
        allow_all_keys: false
        allowed_keys:
          - service.name
          - http.route
          - description
        blocked_values:
          - "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"
          - "4[0-9]{12}(?:[0-9]{3})?"
        summary: silent
    
    service:
      pipelines:
        traces:
          receivers: [otlp]
          processors: [redaction]
          exporters: [otlp]

    Keep redaction before every exporter that could send the original data. Add the processor to metrics and logs pipelines separately when those signals can carry sensitive attributes.