Skip to main content

OTTL Functions Reference

OTTL (OpenTelemetry Transformation Language) is the built-in language for modifying spans, metrics, and logs inside the OpenTelemetry Collector. OTTL functions fall into two categories: editors that change data in place and converters that return computed values.

This reference covers every OTTL function with working Collector YAML configs — editors like set, delete_key, and flatten; converters like ParseJSON, SHA256, and IsMatch; plus ready-to-use recipes for PII redaction, span normalization, and noise filtering. It powers the transform processor and filter processor.

How OTTL Functions Work

An OTTL statement has three parts:

<editor>(<args>) where <condition>
  • Editors modify data in place (set a field, delete a key, flatten a map)
  • Converters are pure functions that return a value (parse JSON, compute a hash, check a type)
  • Conditions use where clauses with converters to control when a statement runs
processors:
transform:
trace_statements:
- context: span
statements:
# Editor: set span name from an attribute
- set(name, attributes["http.route"]) where attributes["http.route"] != nil
# Editor + Converter: hash a user ID
- set(attributes["user.id"], SHA256(attributes["user.id"]))

Contexts

OTTL operates within signal-specific contexts. Each context determines which fields (paths) you can read and write.

SignalContextsKey Paths
Tracesresource, scope, span, spaneventname, attributes, status, kind, trace_id, span_id, start_time_unix_nano, end_time_unix_nano, events, links
Metricsresource, scope, metric, datapointmetric.name, metric.type, attributes, value_int, value_double, start_time_unix_nano, time_unix_nano
Logsresource, scope, logbody, severity_text, severity_number, attributes, trace_id, span_id, time_unix_nano

All contexts can also access resource.attributes and instrumentation_scope.name.

Context Hierarchy

Statements in a lower context can read fields from higher contexts:

resource → scope → span/metric/log → spanevent/datapoint

A span statement can read resource.attributes["service.name"], but a resource statement cannot read individual span fields.


Editor Functions

OTTL editor functions transform telemetry data in place. Each runs as a standalone statement in the transform processor.

set

Assigns a value to a field. The most commonly used OTTL function.

statements:
- set(attributes["environment"], "production")
- set(name, attributes["http.route"]) where attributes["http.route"] != nil
- set(severity_text, "ERROR") where severity_number >= 17

delete

Drops the current telemetry record entirely. Use with a where clause to filter out unwanted spans, logs, or datapoints.

statements:
- delete() where name == "healthcheck"
- delete() where attributes["http.target"] == "/metrics"
- delete() where severity_number < 9

delete_key

Removes a single key from a map.

statements:
- delete_key(attributes, "credit_card_number")
- delete_key(resource.attributes, "internal.debug.id")

delete_matching_keys

Removes all keys matching a regex pattern.

statements:
# Remove all internal debugging attributes
- delete_matching_keys(attributes, "internal\\.debug\\..*")
# Remove all PII-prefixed fields
- delete_matching_keys(attributes, "pii\\..*")

keep_matching_keys

Retains only keys matching a pattern, removing everything else.

statements:
# Keep only http.* and service.* attributes
- keep_matching_keys(attributes, "(http|service)\\..*")

keep_keys

Keeps only the specified keys in a map.

statements:
- keep_keys(attributes, ["http.method", "http.status_code", "http.route"])

replace_pattern

Replaces parts of a string matching a regex.

statements:
# Mask credit card numbers
- replace_pattern(attributes["http.url"], "(card=)\\d+", "$1****")
# Normalize user IDs in span names
- replace_pattern(name, "/users/[0-9]+", "/users/{id}")

replace_match

Replaces the entire string if it matches a glob pattern.

statements:
- replace_match(name, "GET /health*", "healthcheck")

replace_all_patterns

Replaces regex matches across all values in a map.

statements:
# Redact email addresses in all attributes
- replace_all_patterns(attributes, "value", "[a-zA-Z0-9.]+@[a-zA-Z0-9.]+", "REDACTED")

replace_all_matches

Replaces glob-pattern matches across all values in a map.

statements:
- replace_all_matches(attributes, "password=*", "password=***")

flatten

Flattens a nested map into dot-separated keys at the root level.

statements:
# {"http": {"method": "GET"}} → {"http.method": "GET"}
- flatten(attributes)
# With prefix
- flatten(attributes, "app")

merge_maps

Merges one map into another using a conflict resolution strategy.

statements:
# Strategies: insert (skip existing), update (overwrite existing), upsert (always write)
- merge_maps(attributes, resource.attributes, "insert")

limit

Reduces a map to a maximum number of keys, keeping priority keys.

statements:
- limit(attributes, 20, ["http.method", "http.status_code", "service.name"])

truncate_all

Limits string length for all values in a map.

statements:
# Truncate all attribute values to 256 bytes
- truncate_all(attributes, 256)

append

Adds values to a field, converting scalars to arrays if needed.

statements:
- append(attributes["tags"], "processed")

delete_index

Removes elements from a slice by index.

statements:
- delete_index(attributes["items"], 0)

Converter Functions

OTTL converter functions are pure functions — they return a value and do not modify data directly. Use them as arguments inside editors or where conditions. Both the transform processor and filter processor support all converter functions listed below.

String Parsing and Formatting

FunctionDescriptionExample
Concat(values[], delimiter)Joins values into a stringConcat([attributes["first"], attributes["last"]], " ")
Split(value, delimiter)Splits a string into a sliceSplit(attributes["tags"], ",")
Substring(value, start, length)Extracts a substringSubstring(attributes["trace_id"], 0, 8)
Format(fmt, values[])Printf-style formattingFormat("%s-%d", [attributes["svc"], attributes["ver"]])
Trim(value, cutset)Trims characters from both endsTrim(attributes["path"], "/")
TrimPrefix(value, prefix)Removes a prefixTrimPrefix(name, "GET ")
TrimSuffix(value, suffix)Removes a suffixTrimSuffix(name, ".internal")
HasPrefix(value, prefix)Checks if string starts with prefixUsed in where clauses
HasSuffix(value, suffix)Checks if string ends with suffixUsed in where clauses

Case Conversion

FunctionDescription
ToLowerCase(value)Converts to lowercase
ToUpperCase(value)Converts to UPPERCASE
ToCamelCase(value)Converts to camelCase
ToSnakeCase(value)Converts to snake_case
ConvertCase(value, format)General case conversion

Data Parsing

FunctionDescriptionExample
ParseJSON(value)Parses a JSON stringParseJSON(body)["level"]
ParseCSV(value)Parses CSV to a sliceParseCSV(body)
ParseKeyValue(value, delim, assign)Parses key=value stringsParseKeyValue(body, " ", "=")
ParseXML(value)Parses XML to a mapParseXML(body)
ParseSimplifiedXML(value)Parses XML with flat structureParseSimplifiedXML(body)
ParseInt(value, base, bits)Parses a string to integerParseInt("FF", 16, 64)
ParseSeverity(value)Converts severity text to numberParseSeverity("ERROR")
ExtractPatterns(value, regex)Extracts named regex groupsExtractPatterns(body, "status=(?P<status>\\d+)")
ExtractGrokPatterns(value, pattern)Extracts using Grok syntaxExtractGrokPatterns(body, "%{COMMONAPACHELOG}")
UserAgent(value)Parses User-Agent headersUserAgent(attributes["http.user_agent"])
URL(value)Parses a URL into componentsURL(attributes["http.url"])

Type Conversion and Checking

FunctionDescription
Int(value)Converts to integer
Double(value)Converts to float
String(value)Converts to string
Bool(value)Converts to boolean
IsInt(value)Returns true if integer
IsDouble(value)Returns true if float
IsString(value)Returns true if string
IsBool(value)Returns true if boolean
IsMap(value)Returns true if map
IsList(value)Returns true if list/slice

Pattern Matching

FunctionDescriptionExample
IsMatch(value, pattern)Glob pattern matchIsMatch(name, "GET /api/*")
IsRootSpan()True if span has no parentUsed in where clauses

Hashing

FunctionOutput
SHA256(value)SHA-256 hex string
SHA512(value)SHA-512 hex string
SHA1(value)SHA-1 hex string
MD5(value)MD5 hex string
FNV(value)FNV-1a hash
Murmur3Hash(value)Murmur3 32-bit hash
XXH3(value)XXHash3 hash

Time Functions

FunctionDescriptionExample
Now()Current time (Unix nanoseconds)set(attributes["processed_at"], Now())
Time(value, format)Parses a time stringTime("2024-01-15", "2006-01-02")
FormatTime(value, format)Formats time to stringFormatTime(start_time, "2006-01-02")
TruncateTime(value, duration)Rounds time downTruncateTime(start_time, Duration("1h"))
Duration(value)Parses duration stringDuration("5m30s")
Unix(value)Time to Unix seconds
UnixMilli(value)Time to Unix milliseconds
UnixMicro(value)Time to Unix microseconds
UnixNano(value)Time to Unix nanoseconds

Time component extractors: Year, Month, Day, Hour, Minute, Second, Nanosecond, Weekday.

Duration converters: Hours, Minutes, Seconds, Milliseconds, Microseconds, Nanoseconds.

Map and Slice Operations

FunctionDescriptionExample
Keys(map)Returns all keysKeys(attributes)
Values(map)Returns all valuesValues(attributes)
Len(value)Length of string, map, or sliceLen(attributes) > 50
Index(slice, value)Find position in slice
Sort(slice)Returns sorted copySort(attributes["tags"])
SliceToMap(slice)Converts key-value pairs to map
ContainsValue(map, value)Checks if map contains valueUsed in where clauses
ToKeyValueString(map, delim, assign)Map to key=value stringToKeyValueString(attributes, " ", "=")

Identity

FunctionDescription
TraceID(value)Converts hex string to TraceID
SpanID(value)Converts hex string to SpanID
UUID()Generates UUID v4

Encoding

FunctionDescription
Base64Encode(value)Encodes to base64
Hex(value)Converts bytes to hex
Decode(value, encoding)Decodes text from encoding

Network

FunctionDescription
IsInCIDR(ip, cidr)Checks IP against CIDR range
CommunityID(...)Generates network flow community ID
IsValidLuhn(value)Validates Luhn checksum (credit cards)

Debugging

FunctionDescription
Log(message)Outputs a debug message to Collector logs

OTTL Function Examples

Redact PII from Spans

Remove sensitive attributes and mask patterns in URLs:

processors:
transform/redact:
trace_statements:
- context: span
statements:
- delete_key(attributes, "user.email")
- delete_key(attributes, "user.phone")
- delete_matching_keys(attributes, "credit_card.*")
- replace_pattern(attributes["http.url"], "(token=)[^&]*", "$1***")
- set(attributes["http.request.header.authorization"], "REDACTED")
where attributes["http.request.header.authorization"] != nil

Normalize Span Names

Replace dynamic path segments with placeholders for better grouping. See Transforming Spans Using OTTL for more span examples.

processors:
transform/normalize:
trace_statements:
- context: span
statements:
- replace_pattern(name, "/users/[0-9a-f-]+", "/users/{id}")
- replace_pattern(name, "/orders/[0-9]+", "/orders/{id}")
- set(name, Concat([attributes["http.method"], " ", attributes["http.route"]], ""))
where attributes["http.route"] != nil

Parse JSON Log Bodies

Extract structured fields from JSON-formatted log bodies. For a deeper walkthrough of ExtractPatterns, see Extract Fields from Log Body.

processors:
transform/parse_json:
log_statements:
- context: log
statements:
- set(severity_text, ParseJSON(body)["level"])
where IsString(body)
- set(attributes["request.method"], ParseJSON(body)["method"])
where IsString(body)
- set(attributes["request.path"], ParseJSON(body)["path"])
where IsString(body)
- set(attributes["request.duration_ms"], ParseJSON(body)["duration"])
where IsString(body)

Drop Noisy Telemetry

Filter out health checks, internal traffic, and low-value spans. For regex-based log filtering, see Filter Logs with Regex and JSON.

processors:
transform/drop_noise:
trace_statements:
- context: span
statements:
- delete() where name == "healthcheck"
- delete() where attributes["http.target"] == "/ready"
- delete() where attributes["http.target"] == "/metrics"
- delete() where IsMatch(name, "internal.*")
log_statements:
- context: log
statements:
- delete() where IsMatch(body, ".*healthcheck.*")
- delete() where severity_number < 9

Enrich Metrics with Resource Attributes

Copy resource-level metadata into datapoint attributes for querying:

processors:
transform/enrich_metrics:
metric_statements:
- context: datapoint
statements:
- set(attributes["service.name"], resource.attributes["service.name"])
- set(attributes["k8s.namespace"], resource.attributes["k8s.namespace.name"])
- set(attributes["deployment"], resource.attributes["k8s.deployment.name"])

Hash Identifiers for Privacy

Replace user-identifiable values with hashes:

processors:
transform/hash_pii:
trace_statements:
- context: span
statements:
- set(attributes["user.id"], SHA256(attributes["user.id"]))
where attributes["user.id"] != nil
- set(attributes["session.id"], SHA256(attributes["session.id"]))
where attributes["session.id"] != nil

Extract Log Fields with Regex

Pull structured data from unstructured log lines:

processors:
transform/extract:
log_statements:
- context: log
statements:
- set(attributes["status"], ExtractPatterns(body, "status=(?P<status>\\d+)")["status"])
- set(attributes["method"], ExtractPatterns(body, "method=(?P<method>[A-Z]+)")["method"])
- set(attributes["duration"], ExtractPatterns(body, "duration=(?P<duration>[0-9.]+)")["duration"])

OTTL Where Clauses and Conditions

Every OTTL statement supports an optional where clause. The condition must evaluate to a boolean.

statements:
# String comparison
- set(name, "auth-check") where attributes["http.route"] == "/auth"

# Numeric comparison
- delete() where severity_number < 9

# Nil check
- set(attributes["http.method"], "UNKNOWN") where attributes["http.method"] == nil

# Pattern match
- delete() where IsMatch(name, "internal.*")

# Type check
- set(attributes["parsed"], ParseJSON(body)) where IsString(body)

# Combined conditions (AND)
- delete() where attributes["http.target"] == "/health" and kind.string == "Server"

# Combined conditions (OR)
- set(attributes["tier"], "critical")
where attributes["service.name"] == "payments" or attributes["service.name"] == "auth"

OTTL Error Handling

Set error_mode to control what happens when a statement fails:

ModeBehavior
propagateFail the entire pipeline (default)
ignoreSkip the failed statement, continue processing
silentLike ignore, but suppresses error logs
processors:
transform/safe:
error_mode: ignore
log_statements:
- context: log
statements:
# Won't crash if body isn't valid JSON
- set(attributes["level"], ParseJSON(body)["level"])

Use ignore when processing mixed-format data where some records won't match your statements.

OTTL Playground

The OTTL Playground lets you test OTTL functions interactively before deploying to production. Paste sample telemetry data (spans, logs, or metrics in JSON format), write your OTTL statements, and see the transformed output immediately. The playground supports all editor and converter functions listed on this page. Use it to validate regex patterns in replace_pattern, test ParseJSON against real log bodies, or experiment with where clause conditions before editing your Collector config.

OTTL Best Practices

  • Test OTTL functions locally first. Use error_mode: ignore during development, then switch to propagate once statements are validated.
  • Order matters. Statements execute sequentially. A delete_key before a set referencing that key will cause the set to fail.
  • Watch cardinality. Functions like flatten can explode attribute counts. Use limit or keep_keys to control map sizes.
  • Use specific contexts. A resource statement runs once per batch; a span statement runs once per span. Put shared logic at the highest context level for better performance.
  • Monitor Collector resources. Complex OTTL pipelines (regex, JSON parsing) add CPU and memory overhead. Profile with pprof under production load.
Was this page helpful?