Skip to content
Merged
Changes from 6 commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
1f538b0
Complex attributes OTEP (draft)
Apr 20, 2025
e0cf307
why
trask Apr 21, 2025
3209dd7
first round
Apr 21, 2025
21558e0
Merge pull request #2 from lmolkova/complex-attributes
trask Apr 22, 2025
de20078
clarify metrics
Apr 22, 2025
7f27984
Merge pull request #3 from lmolkova/complex-attributes
trask Apr 22, 2025
cad874e
more about why not a breaking change
trask Apr 22, 2025
f7626c1
newline
trask Apr 22, 2025
6da42db
simplify, move options to the future, add glossary
Apr 22, 2025
ffbacf0
Merge pull request #4 from lmolkova/complex-attributes-2
Apr 22, 2025
163cfba
rename file
Apr 22, 2025
22fb140
clarify
trask Apr 23, 2025
9a14f95
simplify
trask Apr 23, 2025
8a21990
Update oteps/4485-extending-attributes-to-support-complex-values.md
Apr 23, 2025
33ed4c2
exporters, null value, prometheus
Apr 23, 2025
6ca73a1
comment with link on limits
Apr 24, 2025
a883928
toc
Apr 24, 2025
017b9fd
another round of feedback
Apr 24, 2025
cd58951
Update oteps/4485-extending-attributes-to-support-complex-values.md
Apr 25, 2025
b63ad0f
wording
trask Apr 28, 2025
1acc53d
another example
trask Apr 28, 2025
0b43566
refine reasons why non-breaking
trask Apr 29, 2025
95f2bb6
add json serialization stability
Apr 29, 2025
bf44dbf
Update oteps/4485-extending-attributes-to-support-complex-values.md
Apr 29, 2025
2c04f16
remove note on metrics, added backend research table
May 12, 2025
5856172
lint
May 12, 2025
04d148e
Update time table
trask May 13, 2025
fae4007
SDK requirement matching API requirement. also exemplars
trask May 20, 2025
81d0b55
feedback
trask May 20, 2025
e3d6b89
feedback
trask May 20, 2025
8ba65ac
span links
trask May 20, 2025
10ad24c
add prototypes and clarify limit
May 27, 2025
06332e7
remove 'should not provide convenience'
May 27, 2025
f60117f
Update oteps/4485-extending-attributes-to-support-complex-values.md
trask Jun 3, 2025
1807c5b
Update oteps/4485-extending-attributes-to-support-complex-values.md
trask Jun 3, 2025
d535198
Update oteps/4485-extending-attributes-to-support-complex-values.md
trask Jun 3, 2025
89cff55
Update oteps/4485-extending-attributes-to-support-complex-values.md
trask Jun 10, 2025
ad41831
update NR behavior
trask Jun 12, 2025
fe2d853
Update oteps/4485-extending-attributes-to-support-complex-values.md
trask Jun 17, 2025
03bd028
Update oteps/4485-extending-attributes-to-support-complex-values.md
trask Jun 17, 2025
b019ddf
Update oteps/4485-extending-attributes-to-support-complex-values.md
trask Jun 17, 2025
09c6b56
Update oteps/4485-extending-attributes-to-support-complex-values.md
trask Jun 17, 2025
6abe3a4
Update oteps/4485-extending-attributes-to-support-complex-values.md
trask Jun 17, 2025
907386c
add note about backend research
trask Jun 17, 2025
b639028
sdk and collector
trask Jun 17, 2025
cf9af50
Update oteps/4485-extending-attributes-to-support-complex-values.md
trask Jun 17, 2025
7f0dd09
Update oteps/4485-extending-attributes-to-support-complex-values.md
trask Jun 17, 2025
7af24d3
Update oteps/4485-extending-attributes-to-support-complex-values.md
trask Jun 17, 2025
9d3629f
feedback
trask Jun 18, 2025
85dd9b7
clarification
trask Jun 18, 2025
9eb9601
fix toc
trask Jun 18, 2025
6582fd6
Update oteps/4485-extending-attributes-to-support-complex-values.md
trask Jun 19, 2025
69fe9d0
exemplar attributes are from metrics
trask Jun 19, 2025
1b3b5ba
explain why MUST/MAY support for different areas
trask Jun 19, 2025
c1d9a5a
remove attribute limits from the OTEP - it's tracked in #4487
Jul 7, 2025
5e3e53f
replace Oct 1 with 6 months from merge
Jul 7, 2025
d7565e6
address some of the anyvalue comments
Jul 7, 2025
1f93651
remove confusing statement on AnyValue enforcement
Jul 7, 2025
7125cd0
equality notes
Jul 7, 2025
3235744
Add AnyValue definition and clean up some usages
Jul 7, 2025
5f35562
lint
Jul 7, 2025
45a82c0
add pointer/ref as a future possibility, limit deep equailty requirem…
Jul 8, 2025
e0d8748
toc
Jul 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
220 changes: 220 additions & 0 deletions oteps/XXXX-extending-attributes-to-support-complex-values.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
# Extending attributes to support complex values

* [Why?](#why)
* [Why do we want complex attributes on spans?](#why-do-we-want-complex-attributes-on-spans)
* [Why do we want to extend standard attributes?](#why-do-we-want-to-extend-standard-attributes)
* [Why isn't it a breaking change?](#why-isnt-it-a-breaking-change)
* [How](#how)
* [API](#api)
* [SDK](#sdk)
* [Signals that support complex attributes](#signals-that-support-complex-attributes)
* [Signals that don't support complex attributes](#signals-that-dont-support-complex-attributes)
* [Handling complex attributes](#handling-complex-attributes)
* [Semantic conventions](#semantic-conventions)
* [Trade-offs and mitigations](#trade-offs-and-mitigations)
* [Prior art and alternatives](#prior-art-and-alternatives)
* [Open questions](#open-questions)
* [Future possibilities](#future-possibilities)

## Why?

### Why do we want complex attributes on spans?

There are a number of reasons why we want to allow complex attributes on spans:

- Emerging semantic conventions, such as Generative AI,
demonstrate the usefulness of including complex attributes on spans.
- Many users already add complex attributes to spans by JSON-encoding them.
Supporting complex attributes natively enables future possibilities like
collector transformations, better attribute truncation, and native
storage of complex attributes in backends.
- During the span event deprecation process, we found that some people
use span events to represent complex data on spans.
Providing support for complex attributes on spans would offer a more natural
way to store this data.
- During the event stabilization process, it became clear that
[spans and events are often thought of as being conceptual
twins.](https://opentelemetry.io/blog/2025/opentelemetry-logging-and-you/#how-is-this-different-from-other-signals),
and the choice between modeling something as a span or an event should not
be influenced by whether complex attributes are needed.

### Why do we want to extend standard attributes?

Instead of introducing a second set of "extended" attributes that can be used on
spans and events, we propose to extend the standard attributes.

Having multiple attribute sets across the API
[creates ergonomic challenges](https://github.com/open-telemetry/opentelemetry-specification/issues/4201).
While there are some mitigations ([as demonstrated in
Java](https://github.com/open-telemetry/opentelemetry-java/pull/7123)),
extending the standard attributes provides a more seamless and user-friendly API experience.

### Why isn't it a breaking change?

Currently, the SDK specification states that extending the set of standard
attribute types to the full set of attribute types supported by OTLP would be
[considered a breaking change](../specification/common/README.md#standard-attribute).

We propose revisiting this and allowing extending the set of standard attribute
types to the full set of attribute types supported by OTLP, without treating it as
a breaking change, for the following reasons:

- Language SDKs can implement this without breaking their backwards
compatibility guarantees (e.g., [Java's](https://github.com/open-telemetry/opentelemetry-java/blob/main/VERSIONING.md)).
- While backends will need to add support for complex attributes, this is
consistent with the introduction of other new features that enable
new capabilities.
A reasonably straightforward implementation option for backends is to JSON serialize
complex attribute values and store them as strings.

## How

### API

Existing APIs that create or add attributes will be extended to support value with type `AnyValue`.

It's up to the language to expose an `AnyValue` API for type checking, ergonomics, or performance.
Alternatively, it may use a base object or another standard library type.

Exposing multiple `Attributes` types is NOT RECOMMENDED if conversion between them
is non-trivial in terms of usability or performance.

The SDK is responsible for handling attribute types depending on the signal.

> [!NOTE]
>
> While OTel metrics are designed for aggregation, future SDK implementations
> may choose to record measurements as individual events. This would make complex
> values acceptable in metrics.
>
> Ultimately, it’s up to the SDK implementation to decide whether to support complex
> values for a given signal. Guidance for OTel-hosted SDKs is provided in the next section.
>
> The API, however, is less opinionated. It should not offer conveniences for recording
> complex attributes on metrics (resources, etc), but it does not have to make it impossible.

### SDK

#### Signals that support complex attributes

**The OTel SDK MUST support complex attributes on spans, logs, profiles, and descriptive
entity attributes.**

Any future OTel signals SHOULD support complex attributes unless there is a
reason not to, which MUST be documented in the specification.

By default, the OTel SDK SHOULD pass complex attributes to the processing pipeline.
The SDK MUST support reading and modifying complex attributes during processing.

If `AnyValue` is not defined at the API level, the OTel SDK SHOULD provide it as
a contract for processors and exporters. The SDK MUST document the contract and
SHOULD convert non-primitive input values to this common type. If conversion is
not possible - e.g., when a non-serializable or unknown object is passed - the SDK
SHOULD record string representation of the provided object.

See the [Configuring complex attribute handling](#configuring-complex-attribute-handling)
section for customization options.

#### Signals that don't support complex attributes

**The OTel SDK SHOULD serialize complex attributes to JSON string if they are added
to metrics, resources, instrumentation scope, or used as identifying attributes on entities.**

The SDK MAY allow customizing this behavior, see [Configuring
complex attribute handling](#allow-recording-structured-attributes) section.

> [!Note]
>
> Complex attributes are not intended to be used on metrics and other
> signals in this category. Their usage is discouraged and expected to be accidental.
>
> JSON serialization overhead is limited to specific applications and is used as a
> fallback (better than dropping).

#### Handling complex attributes

The SDK SHOULD allow per-signal configuration of [attribute limits](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/common/README.md#attribute-limits).

**Attribute value length limit** SHOULD be applied to all leaf string nodes in `AnyValue`.
String values SHOULD be truncated to the configured limit.

Leaf nodes of an `AnyValue` attribute SHOULD count toward the **attribute count limit**.
If the limit is reached, the SDK MUST drop the entire `AnyValue` attribute;
partial exports are not allowed.

A **new attribute limit** property will be introduced to control how and if complex
attributes are handled, with the following options:

- **pass as is**
- Default for spans, logs, profiles, and descriptive entity attributes.
- The SDK MAY support this option for all signals.

- **serialize to JSON string**
- Default for metrics, resources, instrumentation scopes, and identifying entity attributes.
- The SDK MUST support this option for all signals and SHOULD provide per-signal configuration.

- **drop**
- The SDK MAY support this option

### Semantic conventions

Semantic conventions will be updated with the following guidance

- Standard attributes SHOULD be used whenever possible. Semantic conventions SHOULD
assume that backends do not index individual properties of complex attributes,
that querying or aggregating on such properties is inefficient and complicated,
and that reporting complex attributes carries higher performance overhead.

- Complex attributes that are likely to be large (when serialized to a string) SHOULD
be added as *opt-in* attributes. *Large* will be defined based on common backend
attribute limits, typically around 4–16 KB.

- Complex attributes MUST NOT be used on metrics, resources, instrumentation scopes,
or as identifying attributes on entities.

## Trade-offs and mitigations

1. Allowing arbitrary objects as attributes is convenient but increases the risk of
including large, sensitive, mutable, non-serializable, or otherwise problematic
data in telemetry.

It is RECOMMENDED to enforce `AnyValue` compatibility at the API level.
Users and instrumentations SHOULD define custom `AnyValue`-compatible models
to minimize misuse and reduce performance overhead.

OTel SDKs MAY provide convenience methods to convert arbitrary objects to `AnyValue`.
If such convenience is provided, it is RECOMMENDED to limit supported types
to primitives, arrays, standard library collections, named tuples, JSON objects, and
similar structures.

If the object has any property with an unrecognized type, it is RECOMMENDED
to fall back to recording a string representation of the whole object to minimize
the risk of unintentional use of complex attributes.

2. While it should be possible to record complex data in telemetry, many backends do not
support it well - or at all - which can result in individual complex attributes
or entire spans being dropped or rejected.

In the future, support for complex attributes may be negotiated via OpAMP,
allowing this behavior to be configured based on backend capabilities without
requiring user intervention.

In the meantime, we plan to mitigate this through:

- Requiring an SDK mode that serializes complex attributes to JSON
- A collector transformation processor that already can drop, flatten, serialize, or
truncate complex attributes using OTTL
- Semantic conventions guidance that discourages their use

## Prior art and alternatives

TODO

## Open questions

TODO

## Future possibilities

We can consider a separate set of attribute limits specifically for complex values,
including a total size limit and ability to estimate `AnyValue` object size.
Loading