> ## Documentation Index
> Fetch the complete documentation index at: https://docs.honeycomb.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Handle Sensitive Information with the OpenTelemetry Collector

> Filter, redact, and hash PII, credit card numbers, and other sensitive data from your telemetry before it reaches Honeycomb.

Sensitive data, such as personally identifiable information (PII), credit card numbers, and email addresses, can be useful for incident diagnosis, but security and compliance considerations may require you to remove or mask it before it reaches any observability backend.

The [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/) can filter and redact sensitive data before it leaves your environment using [processors](/send-data/opentelemetry/collector/processors), which are components that sit between [receivers](/send-data/opentelemetry/collector/receivers) and [exporters](/send-data/opentelemetry/collector/exporters) in the Collector pipeline and transform, filter, or redact telemetry data in transit.
This page covers three processors for handling sensitive data: `attributes`, `redaction`, and `transform`.
To learn more about these processors, visit [OpenTelemetry Collector Processors](/send-data/opentelemetry/collector/processors).

Each example on this page includes both the processor configuration and the [service pipeline](/send-data/opentelemetry/collector/configure) entry required to activate it.

<Note>
  Filtering sensitive data reduces your ability to diagnose and troubleshoot problems.
  Carefully consider the trade-offs between security and usability before configuring sensitive data filtering.
</Note>

## Choosing an approach

The right approach depends on how much of the value you need to preserve and which signal types you are working with:

| Goal                                                                                               | Processor    | Approach            | Signals               |
| -------------------------------------------------------------------------------------------------- | ------------ | ------------------- | --------------------- |
| [Remove an attribute entirely](#deleting-a-specific-attribute)                                     | `attributes` | `delete`            | traces, metrics, logs |
| [Replace a value with a static placeholder](#redacting-or-hashing-a-specific-attribute-value)      | `attributes` | `upsert`            | traces, metrics, logs |
| [Hash a value (SHA1)](#redacting-or-hashing-a-specific-attribute-value)                            | `attributes` | `hash` (SHA1)       | traces, metrics, logs |
| [Hash a value (SHA256)](#using-sha256-for-stronger-hashing)                                        | `transform`  | `SHA256()`          | traces, metrics, logs |
| [Block values matching a regex pattern](#blocking-values-matching-a-pattern)                       | `redaction`  | `blocked_values`    | traces only           |
| [Restrict which attributes are allowed through](#restricting-which-attributes-are-allowed-through) | `redaction`  | `allowed_keys`      | traces only           |
| [Mask part of a value while preserving context](#masking-values-using-pattern-matching)            | `transform`  | `replace_pattern()` | traces, metrics, logs |
| [Anonymize an IP address by truncating the last octet](#anonymizing-ip-addresses)                  | `transform`  | `replace_pattern()` | traces, metrics, logs |
| [Keep only specific attributes](#keep-only-specific-attributes)                                    | `transform`  | `keep_keys()`       | traces, metrics, logs |

For metrics and logs, use the `attributes` or `transform` processor.
The `redaction` processor supports traces only.

## OpenTelemetry Transformation Language (OTTL)

Several examples on this page use [OpenTelemetry Transformation Language (OTTL)](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/pkg/ottl), a scripting language used by the `transform` processor (and others) that lets you match and modify telemetry data using expressions.
If you encounter OTTL syntax in an example and want to understand it before configuring your own rules, visit OpenTelemetry's GitHub resources on:

* [OTTL syntax](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/pkg/ottl/README.md)
* [OTTL functions](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/pkg/ottl/ottlfuncs)
* [OTTL contexts](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/pkg/ottl/contexts)

## Deleting a specific attribute

Use the [`attributes` processor](/send-data/opentelemetry/collector/processors#attributes-processor) to remove an attribute entirely from spans, metrics, or logs.
This is the simplest approach when an attribute should never reach Honeycomb under any circumstances.

```yaml theme={}
processors:
  attributes:
    actions:
      - key: account_password
        action: delete
...
service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [attributes, batch]
      exporters: [otlp_http]
```

## Redacting or hashing a specific attribute value

Use the [`attributes` processor](/send-data/opentelemetry/collector/processors#attributes-processor) to replace a sensitive value with a static placeholder, remove it entirely, or replace it with a SHA1 hash.
Hashing preserves the ability to correlate data (for example, identifying that two spans share the same email address) without exposing the raw value.

The following configuration redacts a credit card number using `upsert` to guarantee the placeholder is set whether or not the attribute exists, deletes a password, and hashes an email address:

```yaml theme={}
processors:
  attributes:
    actions:
      - key: cc_number
        value: redacted
        action: upsert
      - key: account_password
        action: delete
      - key: account_email
        action: hash
...
service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [attributes, batch]
      exporters: [otlp_http]
    metrics:
      receivers: [otlp]
      processors: [attributes, batch]
      exporters: [otlp_http]
    logs:
      receivers: [otlp]
      processors: [attributes, batch]
      exporters: [otlp_http]
```

After processing, the attributes appear in Honeycomb as follows:

| Attribute          | Before             | After                                      |
| ------------------ | ------------------ | ------------------------------------------ |
| `cc_number`        | `4111111111111111` | `redacted`                                 |
| `account_password` | `mysecretpassword` | *absent*                                   |
| `account_email`    | `user@example.com` | `63a710569261a24b3766275b7000ce8d7b32e2f7` |

<Note>
  The `attributes` processor `hash` action uses SHA1.
  SHA1 is no longer recommended by NIST and is vulnerable to rainbow table attacks if the set of possible values is small or predictable.
  For stronger anonymization, use the `transform` processor with SHA256 instead.
  For an example, refer to the [Using SHA256 for stronger hashing](#using-sha256-for-stronger-hashing) section.
</Note>

### Using SHA256 for stronger hashing

The `transform` processor supports SHA256 via OTTL, which is significantly stronger than the SHA1 used by the `attributes` processor's `hash` action.
The following configuration replaces `user.email` with its SHA256 hash and deletes the original:

```yaml theme={}
processors:
  transform:
    trace_statements:
      - context: span
        statements:
          - set(attributes["user.email"], SHA256(attributes["user.email"])) where attributes["user.email"] != nil
...
service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [transform, batch]
      exporters: [otlp_http]
```

| Attribute    | Before             | After                                                              |
| ------------ | ------------------ | ------------------------------------------------------------------ |
| `user.email` | `user@example.com` | `b4c9a289323b21a01c3e940f150eb9b8c542587f1abfd8f0e1cc1ffc5e475514` |

For the full OTTL syntax and function reference, visit the [OpenTelemetry Transformation Language (OTTL)](#opentelemetry-transformation-language-ottl) section.

<Note>
  SHA256 is deterministic: the same input always produces the same hash, which preserves correlability.
  However, if the set of possible values is small or predictable (for example, a fixed list of internal user IDs), hashes can be reversed using a lookup table.
  For high-sensitivity requirements, consult your security team about whether deterministic hashing meets your compliance obligations.
</Note>

## Blocking values matching a pattern

Use this approach when sensitive data could appear in any attribute value and you can't enumerate every key in advance, such as credit card numbers or IP addresses that may surface across multiple fields.

### For traces

Use the [`redaction` processor](/send-data/opentelemetry/collector/processors#redaction-processor) to mask attribute values that match regex patterns.

<Note>
  The redaction processor supports traces only.
  For metrics or logs, use the attributes or transform processor instead.
</Note>

The following configuration blocks credit card numbers for Visa, Amex, and Mastercard, and IP addresses:

```yaml theme={}
processors:
  redaction:
    allow_all_keys: true
    blocked_values:
      - "^4[0-9]{12}(?:[0-9]{3})?$"          ## Visa
      - "^3[47][0-9]{13}$"                    ## Amex
      - "^(5[1-5][0-9]{14}|2(22[1-9][0-9]{12}|2[3-9][0-9]{13}|[3-6][0-9]{14}|7[0-1][0-9]{13}|720[0-9]{12}))$" ## Mastercard
      - "\b((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}\b" ## IP address
...
service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [redaction, batch]
      exporters: [otlp_http]
```

<Note>
  The `redaction` processor only masks string attribute values.
  Numeric attributes, such as a credit card number stored as an integer rather than a string, won't be caught by `blocked_values` patterns.
  If your application may store sensitive values as non-string types, use the `attributes` or `transform` processor instead.
</Note>

Matching values are replaced with `***` in Honeycomb.
The attribute key is preserved but the value is obscured:

| Attribute      | Before             | After |
| -------------- | ------------------ | ----- |
| `payment.card` | `4111111111111111` | `***` |
| `client.ip`    | `192.168.1.42`     | `***` |

### For metrics and logs

The `redaction` processor supports traces only.
For metrics and logs, choose based on how much of the value you need to preserve:

* To completely remove or hash a value, use the `attributes` processor.
  Hashing replaces the value with a SHA1 hash, which is unreadable but consistent, so you can still correlate events without exposing the original value.
* When you need partial masking that preserves part of the value for readability, such as keeping an email domain while obscuring the local part, use the `transform` processor.

#### Completely removing or hashing a value

To block sensitive values in metrics or logs, use the `attributes` processor with the `hash` or `upsert` action to mask values, or `delete` to remove them entirely:

```yaml theme={}
processors:
  attributes:
    actions:
      - key: account_email
        action: hash
      - key: account_password
        action: delete
...
service:
  pipelines:
    metrics:
      receivers: [otlp]
      processors: [attributes, batch]
      exporters: [otlp_http]
    logs:
      receivers: [otlp]
      processors: [attributes, batch]
      exporters: [otlp_http]
```

#### Partially masking a value

Use the `transform` processor to mask values using `replace_pattern` for more complex pattern matching:

```yaml theme={}
processors:
  transform:
    metric_statements:
      - context: datapoint
        statements:
          - replace_pattern(attributes["account_email"], "^(.+)@(.+)$", "****@$2")
    log_statements:
      - context: log
        statements:
          - replace_pattern(attributes["account_email"], "^(.+)@(.+)$", "****@$2")
...
service:
  pipelines:
    metrics:
      receivers: [otlp]
      processors: [transform, batch]
      exporters: [otlp_http]
    logs:
      receivers: [otlp]
      processors: [transform, batch]
      exporters: [otlp_http]
```

The local part of the email address is masked while the domain is preserved:

| Attribute       | Before             | After              |
| --------------- | ------------------ | ------------------ |
| `account_email` | `user@example.com` | `****@example.com` |

For the full OTTL syntax and function reference, visit the [OpenTelemetry Transformation Language (OTTL)](#opentelemetry-transformation-language-ottl) section.

## Restricting which attributes are allowed through

Use this approach when you need the strictest possible data governance: you know exactly which attributes should reach Honeycomb and want to
guarantee that nothing unexpected gets through, including attributes added by future instrumentation changes.

### For traces

Use the [`redaction` processor](/send-data/opentelemetry/collector/processors#redaction-processor) in allowlist mode to remove every attribute except those you explicitly permit.

<Note>
  The `redaction` processor supports traces only.
  For metrics or logs, use the `attributes` processor with `delete` actions instead.
</Note>

The following configuration removes all attributes except `description`, `group`, and `id`:

```yaml theme={}
processors:
  redaction:
    allow_all_keys: false
    allowed_keys:
      - description
      - group
      - id
...
service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [redaction, batch]
      exporters: [otlp_http]
```

### For metrics and logs

The `redaction` processor supports traces only.
To restrict attributes on metrics or logs, use the `attributes` processor to explicitly delete each attribute you want to remove.
Unlike the `redaction` processor's allowlist approach, you enumerate the attributes to remove rather than the attributes to keep:

```yaml theme={}
processors:
  attributes:
    actions:
      - key: account_password
        action: delete
      - key: cc_number
        action: delete
      - key: user.full_name
        action: delete
...
service:
  pipelines:
    metrics:
      receivers: [otlp]
      processors: [attributes, batch]
      exporters: [otlp_http]
    logs:
      receivers: [otlp]
      processors: [attributes, batch]
      exporters: [otlp_http]
```

## Masking values using pattern matching

Use the [`transform` processor](/send-data/opentelemetry/collector/processors#transform-processor) with [OpenTelemetry Transformation Language (OTTL)](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/pkg/ottl) to mask sensitive values that appear within larger strings, such as passwords embedded in command line arguments or URLs.

### Masking passwords in command line arguments

The following configuration masks any password appearing in a command line attribute, such as `$env password=mysecret username=myusername python run-my-app.py`:

```yaml theme={}
processors:
  transform:
    trace_statements:
      - context: resource
        statements:
          - replace_pattern(attributes["process.command_line"], "password\\=[^\\s]*(\\s?)", "password=***")
...
service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [transform, batch]
      exporters: [otlp_http]
```

The password value is replaced while the rest of the command line is preserved:

| Attribute              | Before                              | After                          |
| ---------------------- | ----------------------------------- | ------------------------------ |
| `process.command_line` | `python app.py --password=mysecret` | `python app.py --password=***` |

For the full OTTL syntax and function reference, visit the [OpenTelemetry Transformation Language (OTTL)](#opentelemetry-transformation-language-ottl) section.

### Anonymizing IP addresses

The following configuration drops the last octet of an IPv4 address in the `client.address` attribute, replacing it with `0` to anonymize the address while preserving the network prefix:

```yaml theme={}
processors:
  transform:
    trace_statements:
      - context: span
        statements:
          - replace_pattern(attributes["client.address"], "\\.\\d+$", ".0")
...
service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [transform, batch]
      exporters: [otlp_http]
```

The last octet is replaced with `0`, anonymizing the host while preserving the network prefix:

| Attribute        | Before         | After         |
| ---------------- | -------------- | ------------- |
| `client.address` | `192.168.1.42` | `192.168.1.0` |

For the full OTTL syntax and function reference, visit the [OpenTelemetry Transformation Language (OTTL)](#opentelemetry-transformation-language-ottl) section.

## Keeping only specific attributes

Use the [`transform` processor](/send-data/opentelemetry/collector/processors#transform-processor) with the `keep_keys` OTTL function to remove all attributes except those you specify.
This is useful when you want to reduce the attribute surface to a known safe set before data reaches Honeycomb.

The following configuration keeps only `service.name`, `service.namespace`, `cloud.region`, and `process.command_line`, removing everything else:

```yaml theme={}
processors:
  transform:
    trace_statements:
      - context: resource
        statements:
          - keep_keys(attributes, "service.name", "service.namespace", "cloud.region", "process.command_line")
...
service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [transform, batch]
      exporters: [otlp_http]
```

Any attribute not in the list, such as `http.url` or `db.statement`, is removed before data reaches Honeycomb.

For the full OTTL syntax and function reference, visit the [OpenTelemetry Transformation Language (OTTL)](#opentelemetry-transformation-language-ottl) section.
