Last updated: July 28, 2025

Mastering the OpenTelemetry Attributes Processor

The OpenTelemetry Collector plays a central role in shaping and managing observability data across modern systems.

Among its many components, the attributes processor is one you’ll often reach out for when you need to enrich, redact, or standardize the data flowing through your pipelines.

While the official documentation provides a foundational understanding, this guide aims to go beyond the basics by offering a comprehensive and practical deep dive.

By the end of this article, you’ll be able to wield the attributes processor with confidence to tailor your telemetry and drive clearer insights.

Let's get started!

What are OpenTelemetry attributes?

In OpenTelemetry, attributes are key-value pairs that describe specific characteristics of the events, operations, or entities being observed.

They add context to your telemetry data, making it searchable, filterable, and ultimately more actionable. For example, a span representing an HTTP request might include attributes like http.request.method, http.route, and http.response.status_code.

In the OpenTelemetry model, you’ll encounter attributes in several places including Resources, Instrumentation Scopes, Metric Points, Spans, Span Events, Span Links, and Log Records.

In the OpenTelemetry debug exporter, attributes appear like this:

OpenTelemetry debug exporter showing attributes

When to use the attributes processor

The attributes processor is useful anytime you need to clean up, enrich, or standardize telemetry data in-flight. Common use cases include:

  • Standardizing attribute keys across your services and teams.
  • Injecting metadata from various sources.
  • Removing or obfuscating personally identifiable information (PII) before it leaves your systems.
  • Fixing misnamed or malformed attributes from sources you don’t control.
  • Driving pipeline logic based on attribute values.

Note that the attributes processor operates on span, log, and metric attributes alone (shown as Attributes in the debug exporter). For attribute manipulation beyond this scope, other specialized processors in the OpenTelemetry Collector are available:

Quick Start: adding the attributes processor

To begin using the attributes processor, define it in the processors section of your Collector configuration, then reference it in the pipelines where you want it applied:

yaml
otelcol.yaml
12345678910111213141516171819202122
processors:
attributes:
actions:
# Your attribute modification actions will go here
- key: some_attribute
value: some_value
action: upsert
service:
pipelines:
traces:
receivers: [otlp]
processors: [attributes] # Apply to traces
exporters: [otlp]
metrics:
receivers: [otlp]
processors: [attributes] # Apply to metrics
exporters: [otlp]
logs:
receivers: [otlp]
processors: [attributes] # Apply to logs
exporters: [otlp]

You can apply different sets of attribute modifications to various pipelines or for distinct purposes, by defining multiple instances of the attributes processor, each with a unique name:

yaml
otelcol.yaml
12345678910111213
processors:
attributes/my_enricher:
actions:
- key: some_attribute
value: some_value
action: insert
attributes/my_redactor:
actions:
- key: user.email
action: hash
- pattern: ".*password.*"
action: delete

Understanding attribute processor actions

The attributes processor supports a variety of actions for modifying telemetry data. These actions are executed in the order they appear in your configuration, allowing predictable control over how attributes are handled.

Adding and modifying attributes

The following actions are provided for managing attribute values:

insert

This adds an attribute only if it does not already exist:

yaml
otelcol.yaml
123
- key: new_attribute
value: "some_value"
action: insert # Adds `new_attribute` only if it's missing

update

Modifies an attribute only if it already exists:

yaml
otelcol.yaml
123
- key: existing_attribute
value: "updated_value"
action: update # Updates `existing_attribute` if it exists

upsert

Adds or updates an attribute (whichever is needed). This is often the most convenient and commonly used action:

yaml
otelcol.yaml
123
- key: some_attribute
value: some_value
action: upsert # Ensures `some_attribute` is set to `some_value`

Populating attribute values

When using the insert, update, or upsert actions, you have three ways to populate the attribute value:

value

This lets you provide a literal value whose type is inferred automatically:

yaml
otelcol.yaml
1234567891011121314
attributes:
actions:
- key: string_example
value: This is a string attribute
action: upsert
- key: int_example
value: 12345
action: upsert
- key: bool_example
value: true
action: upsert
- key: double_example
value: 98.765
action: upsert
Screenshot of attribute types in debug exporter

from_attribute

This copies the new attribute value from an existing attribute in the same telemetry signal:

yaml
otelcol.yaml
12345
# Copy `http.method` to `http.request.method`
actions:
- key: http.request.method
from_attribute: http.method
action: upsert
Before applying the from_attribute fieldAfter applying the from_attribute field
Before and after applying the from_attribute property

A common pattern is using from_attribute to copy a value to a new attribute, and then deleting the original:

yaml
otelcol.yaml
1234567
# Copy `http.method` to `http.request.method`
actions:
- key: http.request.method
from_attribute: http.method
action: upsert
- key: http.method
action: delete

If the source attribute (http.method in this case) doesn’t exist, the action is skipped.

from_context

This extracts values from the OpenTelemetry Collector’s internal context, such as gRPC metadata, HTTP headers, client address, or authentication info. Here are the available patterns:

  • metadata.<key>: To extract HTTP headers or gRPC metadata, you must use the metadata prefix. You’ll need to enable include_metadata: true on your OTLP receiver before you can access these attributes:
yaml
otelcol.yaml
1234567891011121314
receivers:
otlp:
protocols:
grpc:
include_metadata: true # Essential for 'from_context: metadata.*'
http:
include_metadata: true # Essential for 'from_context: metadata.*'
processors:
attributes/headers:
actions:
- key: user_agent
from_context: metadata.user-agent # Extract User-Agent header
action: upsert
Using from_context to extract user-agent header
  • auth.<key>: Accesses authentication details provided by server authenticators. The specific keys depend on the authenticator used, so you’ll need to refer to its documentation.
yaml
otelcol.yaml
123
- key: auth.client_id
from_context: auth.client.id # If an authenticator exposes client.id
action: upsert
  • client.address: Captures the IP address of the client sending data to the Collector.
yaml
otelcol.yaml
123
- key: client_address
from_context: client.address
action: upsert

Removing unwanted attributes

The delete action removes attributes by name or pattern. Use key for an exact match, or pattern for regex-based deletion:

yaml
otelcol.yaml
1234567
# Delete a specific attribute
- key: sensitive_data
action: delete
# Delete all attributes starting with "internal."
- pattern: ^internal\..*
action: delete

Redacting sensitive information

The hash action replaces an attribute’s value with its SHA-256 hash. This allows you to redact sensitive information while preserving uniqueness for correlation or grouping.

As with delete, you can provide a specific key or a regular expression pattern:

yaml
otelcol.yaml
1234567
# Hash a specific attribute
- key: user.email
action: hash
# Hash any attribute containing "email" in its name
- pattern: .*email.*
action: hash
Hashing sensitive data with the attributes processor

For a deeper dive, see our guide on scrubbing sensitive data from logs, traces, and metrics.

Parsing values with regular expressions

The extract action lets you parse parts of an attribute’s value using a regular expression and populate the results into new attributes.

For example, consider an unstructured log like this:

plain text
1
log.record.original: "User 'jane.doe@example.com' with session ID 'ABC123XYZ' failed to authenticate from IP: 203.0.113.42 due to invalid credentials. ErrorCode: 401"

You can extract the email, session ID, client IP address, and error code into discrete attributes using the following configuration:

yaml
otelcol.yaml
12345
attributes/add_various_types:
actions:
- key: log.record.original
pattern: "^User '(?P<user_email>[^']+)' with session ID '(?P<session_id>[^']+)' failed to authenticate from IP: (?P<client_ip>\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}) due to invalid credentials\\. ErrorCode: (?P<error_code>\\d+)"
action: extract

The extract action requires both a key and a regex pattern that must use named capture groups. In this example:

  • (?P<user_email>[^']+) captures the email address into a new user_email attribute.
  • (?P<session_id>[^']+) captures the session ID into a new session_id attribute.
  • (?P<client_ip>\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}) captures the IPv4 address into a new client_ip attribute.
  • (?P<error_code>\\d+) captures the numeric error code into a new error_code attribute.

The extracted values are automatically added as attributes on the signal. If any of the target attributes already exist, they will be overwritten.

Using the extract action in the attributes processor

Changing attribute types

The convert action allows you to change the type of an attribute’s value to one of the supported types: int, double, or string. This is useful when normalizing data to meet semantic conventions or backend requirements.

yaml
otelcol.yaml
123
- key: response_time_ms
action: convert
converted_type: double # Converts a string '123.45' to a float

If the value cannot be converted (e.g., trying to convert “abc” to an int), the original value remains unchanged.

Tailoring attribute modifications with filters

So far, we’ve focused on how to modify attributes. But in practice, you often don’t want these actions applied to every signal in your pipeline.

That’s where include and exclude filters come in. They let you precisely control which traces, metrics, or logs your attribute actions apply to.

How filtering works

If both include and exclude are specified, the include rules are evaluated first, and exclude is then applied to the result of the include set.

You must also specify a match_type which determines how values are matched. It can be set to either strict for exact string comparisons, or regexp for more flexible pattern matching using regular expressions.

Filtering by telemetry type

Within the include and exclude fields, the available filtering options depend on the telemetry signal.

For spans, you can filter by services, span_names, span_kinds, attributes, resources, and libraries:

yaml
otelcol.yaml
123456
processors:
attributes/filter_spans:
include:
match_type: strict
services: [my-backend-service] # Only process spans from this service
span_names: [/api/v1/users] # Only process this specific span name

For log records, the valid fields are log_bodies, log_severity_texts, log_severity_number, attributes, resources, and libraries:

yaml
otelcol.yaml
12345678
processors:
attributes/filter_logs:
exclude:
match_type: regexp
log_bodies: [.*healthcheck.*] # Exclude logs containing "healthcheck"
log_severity_number:
min: 21
match_undefined: false # Do not match logs with undefined severity

Finally, for metrics, only metric_names and resources are supported for filtering:

yaml
otelcol.yaml
12345678
processors:
attributes:
include:
match_type: regexp
regexp:
cacheenabled: true
cachemaxnumentries: 1000 # Cache up to 1000 regex matches
span_names: ["^/api/v\\d+/.*"]

Caching regular expression matches

When match_type is regexp, you can enable optional regex result caching to improve performance, especially in high-throughput environments or when patterns repeat frequently.

yaml
otelcol.yaml
12345678
processors:
attributes:
include:
match_type: regexp
regexp:
cacheenabled: true
cachemaxnumentries: 1000 # Cache up to 1000 regex matches
span_names: ["^/api/v\\d+/.*"]

By setting cacheenabled: true and optionally cachemaxnumentries (to limit the cache size), the processor caches results of regex matches. This avoids redundant regex evaluations and helps reduce CPU usage while increasing throughput.

Attributes processor tips and best practices

  • Action order matters: Actions are executed in the order they’re defined. For example, if you’re copying an attribute and then deleting the original, make sure the copy comes first.
  • Test before deploying: Use the debug exporter to validate your configuration and confirm attribute changes behave as expected before rolling out to production.
  • Watch for performance impact: While the attributes processor is generally efficient, complex regex patterns or a very large number of rules can introduce significant overhead. Be sure to keep tabs on your collector’s performance metrics accordingly.
  • Avoid unintended metric identity changes: If you change attributes that define a metric’s identity, you could inadvertently create new metric streams or cause data loss if the backend expects a specific identity.

Final thoughts

The OpenTelemetry attributes processor is a powerful tool for shaping high-quality telemetry. With a solid grasp of its actions, filtering logic, and best practices, you can clean, enrich, and standardize your traces, metrics, and logs before they reach your observability backend.

Once your data is clean and your attributes are well defined, the next step is sending it to an OpenTelemetry-native platform like Dash0 to help you transform them into actionable insights.

Dash0 trace view

Take control of your observability data and try Dash0 today by signing up for a free trial.

Authors
Ayooluwa Isaiah
Ayooluwa Isaiah