Transformations
Transformations let you modify ingested telemetry before it reaches storage. Each operation is a small YAML rule applied to spans, logs, events, or metric datapoints — in the order you define. Use them to clean up noisy data, normalize attribute names, reduce cardinality, and control costs.
To create an operation:
- Go to Project → Transformations in the left navigation.
- Click New Operation → New operation from YAML.
- Paste a YAML rule and click Create.
Common recipes
Drop health check spans
name: Drop healthcheck spans
scope: [spans]
type: drop
if: spanName() == "GET /healthz" && spanStatusCode() != "error"
Sample successful requests
name: Sample 10% of successful spans
scope: [spans]
type: sample
fraction: 0.1
if: spanStatusCode() != "error"
Sampling for spans is trace-aware: all spans in the same trace are either kept or dropped together, preserving trace completeness.
Rename a legacy attribute
name: Rename service to service_name
scope: [spans, logs, events, datapoints]
type: rename_attr
old_key: service
new_key: service_name
Reduce URL cardinality
name: Normalize user profile URLs
scope: [spans]
type: script
if: hasAttr("http_target")
then:
- setAttr("http_target", replaceGlob(attr("http_target"), "/user/*/profile", "/user/{id}/profile"))
Build a full-text index
name: Index request and exception attributes
scope: [spans, logs, events]
type: text_index
include:
- log_message
- exception_message
- http.request.**
exclude:
- http.request.headers.**
Once configured, search indexed content with *:value in the search bar.
Enrich IP addresses with geo data
name: Enrich client IP with geo data
scope: [spans, logs, events]
type: ip_geo_attrs
keys:
- custom_ip_address
Adds {key}_country_code, {key}_country_name, and {key}_city attributes for each specified key.
How operations work
Scope
Every operation requires a scope field that limits it to specific signal types:
spanslogseventsdatapoints
Conditions
Narrow which records an operation applies to using an if expression written in Expr:
name: Rename service to service_name
scope: [spans, logs, events, datapoints]
type: rename_attr
old_key: service
new_key: service_name
if: attr("deployment_environment") == "prod"
Execution order
Uptrace runs all operations in order after normalising attribute names (e.g. service.name → service_name). A drop operation stops execution for that record. All other operations always run to completion regardless of errors.
Use priority to control order when two operations must run in a specific sequence:
name: Rename service to service_name
scope: [spans, logs, events, datapoints]
priority: 100
type: rename_attr
old_key: service
new_key: service_name
Transformations run before Uptrace processes data internally, so certain computed columns are not yet available. Use these replacements:
| Uptrace column | Replacement |
|---|---|
_display_name | spanName(), eventName(), attr("log_message") |
db_arg_* | attr("db_statement") contains "something" |
http_response_status_class | http_response_status_code |
user_agent_* | user_agent_original |
Next steps
- Operations & functions reference — all operation types and built-in functions
- Searching — use
*:valueafter configuring a text index - Observability as Code — manage transformation rules as version-controlled YAML files