Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
026fad1
Add empty value to attribute
pellared Jul 17, 2025
1831164
Update changelog
pellared Jul 17, 2025
82e8913
toc
pellared Jul 17, 2025
9cab0c4
fix status
pellared Jul 17, 2025
85db60a
Remove the note that extending attributes is a breaking change
pellared Jul 17, 2025
eaea1ea
Update CHANGELOG.md
pellared Jul 17, 2025
25c2c25
Update specification/common/attribute-type-mapping.md
pellared Jul 18, 2025
d9ac9f7
Merge branch 'main' into empty-attr
pellared Jul 21, 2025
75b22ad
Merge branch 'main' into empty-attr
pellared Jul 21, 2025
c540098
revert breaking change note
pellared Jul 22, 2025
05fa307
Merge branch 'main' into empty-attr
pellared Aug 26, 2025
aa3c41c
remove changelog entry
pellared Aug 26, 2025
20043e3
remove "standard attribute" term
pellared Aug 26, 2025
bfaf650
merge log attributes and standard attribute types
pellared Aug 26, 2025
c17aec6
rename "Attribute Value" to "AnyValue"
pellared Aug 26, 2025
95b049b
mdlint
pellared Aug 26, 2025
b98d714
fix links
pellared Aug 26, 2025
e55416d
Apply suggestions from code review
pellared Aug 26, 2025
49b41b4
Revert "rename "Attribute Value" to "AnyValue""
pellared Aug 26, 2025
db81d62
toc
pellared Aug 26, 2025
ad10769
Update specification/common/README.md
pellared Aug 26, 2025
cc41e2f
Update specification/common/README.md
pellared Aug 26, 2025
8b029c8
propose Attribute Limits changes
pellared Aug 28, 2025
a5851af
format
pellared Aug 28, 2025
52ccb34
remove EOL
pellared Aug 28, 2025
9bd7de9
Merge branch 'main' into extend-attrs
pellared Aug 28, 2025
ecebf40
Update specification/common/README.md
pellared Aug 28, 2025
abfd063
Update specification/common/README.md
pellared Aug 28, 2025
cbe15f5
Apply code review suggestion
pellared Aug 28, 2025
7a3c387
Update specification/common/README.md
pellared Aug 28, 2025
f2a508b
format
pellared Aug 28, 2025
ee4d8ba
Update specification/common/README.md
pellared Aug 28, 2025
10400ef
add attribute count example
pellared Aug 28, 2025
f8236e7
format
pellared Aug 28, 2025
d7de5d0
Merge branch 'main' into extend-attrs
pellared Sep 3, 2025
5b46a71
add AnyValue and map<string, AnyValue>
pellared Sep 3, 2025
4a15e7c
update Attribute Limits
pellared Sep 3, 2025
552e997
fix toc
pellared Sep 3, 2025
b224937
fix limit rules
pellared Sep 3, 2025
9f04b58
make it development
pellared Sep 8, 2025
61a9a1b
fix OTEP hyperlink
pellared Sep 8, 2025
98fb4ae
fix logs API status
pellared Sep 8, 2025
f343e4e
Merge branch 'main' into extend-attrs-dev
pellared Sep 8, 2025
253949f
Apply suggestions from code review
pellared Sep 8, 2025
d246e63
Add changelog entry
pellared Sep 8, 2025
9e47faa
mdlint
pellared Sep 8, 2025
1ac516a
Remove "Reuse Standard Attribute" from spec compliance
pellared Sep 8, 2025
2dd712d
fmt
pellared Sep 8, 2025
0230f74
Merge branch 'main' into extend-attrs-dev
pellared Sep 8, 2025
a9b711d
Update specification/common/README.md
pellared Sep 9, 2025
a1493d4
Update specification/common/README.md
pellared Sep 9, 2025
df85700
Update specification/common/README.md
pellared Sep 9, 2025
708686e
Update specification/common/README.md
pellared Sep 9, 2025
af80d42
Update specification/common/README.md
pellared Sep 9, 2025
dca8512
toc
pellared Sep 9, 2025
ec94759
move note about deep nesting
pellared Sep 9, 2025
eee4182
Merge branch 'main' into extend-attrs-dev
pellared Sep 9, 2025
d4240f2
make compliance-matrix
pellared Sep 9, 2025
9b210ca
note that array and map values carry performance overhead
pellared Sep 9, 2025
851f426
update OTEP per feedback
pellared Sep 9, 2025
a5178c6
remove redundant section
pellared Sep 10, 2025
4f92d3d
Update 4485-extending-attributes-to-support-complex-values.md
pellared Sep 10, 2025
e3a1a65
Update specification/common/README.md
pellared Sep 18, 2025
bf19f4d
Merge branch 'main' into extend-attrs-dev
pellared Sep 23, 2025
d7d4eaa
Clarify that for attribute count limit only the top-level attributes …
pellared Sep 23, 2025
4d7c1da
Update oteps/4485-extending-attributes-to-support-complex-values.md
pellared Sep 23, 2025
4b69f1f
Merge branch 'main' into extend-attrs-dev
pellared Sep 23, 2025
d756e95
Update specification/common/README.md
pellared Sep 23, 2025
815cf8b
Update CHANGELOG.md
pellared Sep 23, 2025
1174a4a
Merge branch 'main' into extend-attrs-dev
pellared Sep 24, 2025
e1386ca
Define equality of map<string, AnyValue>
pellared Sep 24, 2025
703745c
Note that the limits apply only to attributes collections
pellared Sep 24, 2025
9c2136f
Merge branch 'main' into extend-attrs-dev
pellared Sep 25, 2025
0baa88c
Merge branch 'main' into extend-attrs-dev
pellared Oct 1, 2025
42bc422
Merge branch 'main' into extend-attrs-dev
pellared Oct 6, 2025
e11dd54
Merge branch 'main' into extend-attrs-dev
pellared Oct 6, 2025
6c8418e
Update specification/common/README.md
pellared Oct 6, 2025
6169089
Merge branch 'main' into extend-attrs-dev
pellared Oct 8, 2025
4817bca
Merge branch 'main' into extend-attrs-dev
pellared Oct 13, 2025
23b00af
Merge branch 'main' into extend-attrs-dev
pellared Oct 14, 2025
4a4af91
Move changlog entry to unreleased
pellared Oct 14, 2025
2884f43
Add appendix instead of changes in OTEP content
pellared Oct 14, 2025
7c1896d
Merge branch 'main' into extend-attrs-dev
pellared Oct 16, 2025
ab65c41
key case sensitivity in map
pellared Oct 16, 2025
8fbd4fc
revert sections order
pellared Oct 16, 2025
35e2fd4
add status to attr count limit in maps
pellared Oct 16, 2025
3bfd222
Merge branch 'main' into extend-attrs-dev
pellared Oct 16, 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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ release.

### Common

- Extend the set of attribute value types to support more complex data structures.
([#4651](https://github.com/open-telemetry/opentelemetry-specification/pull/4651))

### Supplementary Guidelines

### OTEPs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
* [Configurable OTLP exporter behavior (both SDK and Collector)](#configurable-otlp-exporter-behavior-both-sdk-and-collector)
* [Record pointer to repetitive data](#record-pointer-to-repetitive-data)
- [Backend research](#backend-research)
- [Appendix](#appendix)

<!-- tocstop -->

Expand Down Expand Up @@ -94,7 +95,7 @@ extending the standard attributes provides a more seamless and user-friendly API

Currently, the SDK specification has a clause that says extending
the set of standard attribute would be
[considered a breaking change](/specification/common/README.md#standard-attribute).
[considered a breaking change](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.44.0/specification/common/README.md#standard-attribute).

We believe that removing this clause and extending standard
attributes can be done gracefully across the OpenTelemetry ecosystem
Expand Down Expand Up @@ -309,3 +310,9 @@ for additional details.

> [!NOTE]
> This list only reflects the behavior at the time of writing and may change in the future.

## Appendix

The [Extend the set of attribute value types #4651](https://github.com/open-telemetry/opentelemetry-specification/pull/4651) PR implements part of this OTEP by requiring that both the OTel API and SDK MUST support complex attributes.
Some languages aim to support complex attributes for all kinds of telemetry.
To maintain consistency across languages, we agreed that all languages should provide the same level of support for complex attributes.
4 changes: 2 additions & 2 deletions oteps/entities/0256-entities-data-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ MAY change over the lifetime of the entity. MAY be empty. These
attributes are not part of entity's identity.
<p>
Follows <a
href="../../specification/logs/data-model.md#type-any">any</a>
href="https://github.com/open-telemetry/opentelemetry-specification/blob/v1.44.0/specification/logs/data-model.md#type-any">any</a>
value definition in the OpenTelemetry spec - it can be a scalar value,
byte array, an array or map of values. Arbitrary deep nesting of values
for arrays and maps is allowed.
Expand Down Expand Up @@ -682,7 +682,7 @@ There are a couple of reasons:
### Attribute Data Type

The data model requires the Attributes field to use the extended
[any](../../specification/logs/data-model.md#type-any)
[any](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.44.0/specification/logs/data-model.md#type-any)
attribute values, that allows more complex data types. This is different from the data
type used by the Id field, which is more restricted in the shape.

Expand Down
1 change: 0 additions & 1 deletion spec-compliance-matrix.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,6 @@ Disclaimer: this list of features is still a work in progress, please refer to t
| LoggerProvider.Shutdown | | | + | | + | + | | + | | + | - | |
| LoggerProvider.ForceFlush | | | + | | + | + | | + | | + | - | |
| Logger.Emit(LogRecord) | | | + | | + | + | | + | | + | - | |
| Reuse Standard Attributes | X | + | | | | | | | | | | |
| LogRecord.Set EventName | | + | | | | | | | + | + | | |
| Logger.Enabled | X | + | | | | | | + | + | + | | |
| SimpleLogRecordProcessor | | | + | | + | + | | + | | + | | |
Expand Down
2 changes: 0 additions & 2 deletions spec-compliance-matrix/cpp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -357,8 +357,6 @@ sections:
status: '+'
- name: Logger.Emit(LogRecord)
status: '+'
- name: Reuse Standard Attributes
status: '?'
- name: LogRecord.Set EventName
status: '+'
- name: Logger.Enabled
Expand Down
2 changes: 0 additions & 2 deletions spec-compliance-matrix/dotnet.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -357,8 +357,6 @@ sections:
status: '-'
- name: Logger.Emit(LogRecord)
status: '-'
- name: Reuse Standard Attributes
status: '?'
- name: LogRecord.Set EventName
status: '?'
- name: Logger.Enabled
Expand Down
2 changes: 0 additions & 2 deletions spec-compliance-matrix/erlang.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -357,8 +357,6 @@ sections:
status: '?'
- name: Logger.Emit(LogRecord)
status: '?'
- name: Reuse Standard Attributes
status: '?'
- name: LogRecord.Set EventName
status: '?'
- name: Logger.Enabled
Expand Down
2 changes: 0 additions & 2 deletions spec-compliance-matrix/go.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -357,8 +357,6 @@ sections:
status: '?'
- name: Logger.Emit(LogRecord)
status: '?'
- name: Reuse Standard Attributes
status: '+'
- name: LogRecord.Set EventName
status: '+'
- name: Logger.Enabled
Expand Down
2 changes: 0 additions & 2 deletions spec-compliance-matrix/java.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -357,8 +357,6 @@ sections:
status: '+'
- name: Logger.Emit(LogRecord)
status: '+'
- name: Reuse Standard Attributes
status: '?'
- name: LogRecord.Set EventName
status: '?'
- name: Logger.Enabled
Expand Down
2 changes: 0 additions & 2 deletions spec-compliance-matrix/js.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -357,8 +357,6 @@ sections:
status: '?'
- name: Logger.Emit(LogRecord)
status: '?'
- name: Reuse Standard Attributes
status: '?'
- name: LogRecord.Set EventName
status: '?'
- name: Logger.Enabled
Expand Down
2 changes: 0 additions & 2 deletions spec-compliance-matrix/php.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -357,8 +357,6 @@ sections:
status: '+'
- name: Logger.Emit(LogRecord)
status: '+'
- name: Reuse Standard Attributes
status: '?'
- name: LogRecord.Set EventName
status: '?'
- name: Logger.Enabled
Expand Down
2 changes: 0 additions & 2 deletions spec-compliance-matrix/python.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -357,8 +357,6 @@ sections:
status: '+'
- name: Logger.Emit(LogRecord)
status: '+'
- name: Reuse Standard Attributes
status: '?'
- name: LogRecord.Set EventName
status: '?'
- name: Logger.Enabled
Expand Down
2 changes: 0 additions & 2 deletions spec-compliance-matrix/ruby.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -357,8 +357,6 @@ sections:
status: '+'
- name: Logger.Emit(LogRecord)
status: '+'
- name: Reuse Standard Attributes
status: '?'
- name: LogRecord.Set EventName
status: '?'
- name: Logger.Enabled
Expand Down
2 changes: 0 additions & 2 deletions spec-compliance-matrix/rust.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -357,8 +357,6 @@ sections:
status: '?'
- name: Logger.Emit(LogRecord)
status: '?'
- name: Reuse Standard Attributes
status: '?'
- name: LogRecord.Set EventName
status: '+'
- name: Logger.Enabled
Expand Down
2 changes: 0 additions & 2 deletions spec-compliance-matrix/swift.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -357,8 +357,6 @@ sections:
status: '?'
- name: Logger.Emit(LogRecord)
status: '?'
- name: Reuse Standard Attributes
status: '?'
- name: LogRecord.Set EventName
status: '?'
- name: Logger.Enabled
Expand Down
2 changes: 0 additions & 2 deletions spec-compliance-matrix/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,6 @@ sections:
- name: LoggerProvider.Shutdown
- name: LoggerProvider.ForceFlush
- name: Logger.Emit(LogRecord)
- name: Reuse Standard Attributes
optional: true
- name: LogRecord.Set EventName
- name: Logger.Enabled
optional: true
Expand Down
144 changes: 98 additions & 46 deletions specification/common/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@ path_base_for_github_subdir:

# Common specification concepts

**Status**: [Stable](../document-status.md)
**Status**: [Stable](../document-status.md), except where otherwise specified

<details>
<summary>Table of Contents</summary>

<!-- toc -->

- [AnyValue](#anyvalue)
* [map](#mapstring-anyvalue)
- [Attribute](#attribute)
* [Standard Attribute](#standard-attribute)
* [Attribute Limits](#attribute-limits)
+ [Configurable Parameters](#configurable-parameters)
+ [Exempt Entities](#exempt-entities)
Expand All @@ -26,39 +27,81 @@ path_base_for_github_subdir:

</details>

## Attribute
## AnyValue

<a id="attributes"></a>
`AnyValue` is either:

An `Attribute` is a key-value pair, which MUST have the following properties:
- a primitive type: string, boolean, double precision floating point
(IEEE 754-1985), or signed 64 bit integer,
- a homogeneous array of primitive type values. A homogeneous array MUST NOT
contain values of different types.
- **Status**: [Development](../document-status.md) - a byte array.
- **Status**: [Development](../document-status.md) - an array of `AnyValue`,
- **Status**: [Development](../document-status.md) - a [`map<string, AnyValue>`](#mapstring-anyvalue),
- **Status**: [Development](../document-status.md) - an empty value if supported by the language,
(e.g. `null`, `undefined` in JavaScript/TypeScript, `None` in Python, `nil` in Go/Ruby, not supported in Erlang, etc.)

- The attribute key MUST be a non-`null` and non-empty string.
- Case sensitivity of keys is preserved. Keys that differ in casing are treated as distinct keys.
- The attribute value is either:
- A primitive type: string, boolean, double precision floating point (IEEE 754-1985) or signed 64 bit integer.
- An array of primitive type values. The array MUST be homogeneous,
i.e., it MUST NOT contain values of different types.
Arbitrary deep nesting of values for arrays and maps is allowed (essentially
allows to represent an equivalent of a JSON object).

For protocols that do not natively support non-string values, non-string values SHOULD be represented as JSON-encoded strings. For example, the expression `int64(100)` will be encoded as `100`, `float64(1.5)` will be encoded as `1.5`, and an empty array of any type will be encoded as `[]`.
APIs SHOULD be documented in a way to communicate to users that using array and
map values may carry higher performance overhead compared to primitive values.

Attribute values expressing a numerical value of zero, an empty string, or an
empty array are considered meaningful and MUST be stored and passed on to
processors / exporters.
For protocols that do not natively support some of the value types, corresponding values
SHOULD be represented as JSON-encoded strings. For example, the expression
`int64(100)` will be encoded as `100`, `float64(1.5)` will be encoded as `1.5`,
and an empty array of any type will be encoded as `[]`.

Attribute values of `null` are not valid and attempting to set a `null` value is
undefined behavior.
AnyValues expressing an empty value, a numerical value of zero, an empty string,
or an empty array are considered meaningful and MUST be stored and passed on to
processors / exporters.

`null` values SHOULD NOT be allowed in arrays. However, if it is impossible to
make sure that no `null` values are accepted
While `null` is a valid attribute value, its use within homogeneous arrays
SHOULD generally be avoided unless language constraints make this impossible.
However, if it is impossible to make sure that no `null` values are accepted
(e.g. in languages that do not have appropriate compile-time type checking),
`null` values within arrays MUST be preserved as-is (i.e., passed on to span
`null` values within arrays MUST be preserved as-is (i.e., passed on to
processors / exporters as `null`). If exporters do not support exporting `null`
values, they MAY replace those values by 0, `false`, or empty strings.
This is required for map/dictionary structures represented as two arrays with
indices that are kept in sync (e.g., two attributes `header_keys` and `header_values`,
both containing an array of strings to represent a mapping
`header_keys[i] -> header_values[i]`).

### map<string, AnyValue>

**Status**: [Development](../document-status.md)

`map<string, AnyValue>` is a map of string keys to `AnyValue` values.
The keys in the map are unique (duplicate keys are not allowed).

Case sensitivity of keys MUST be preserved.
Keys that differ in casing are treated as distinct keys.

The representation of the map is language-dependent.

The implementation MUST by default ensure that the exported maps contain only unique keys.

The implementation MAY have an option to allow exporting maps with duplicate keys
(e.g. for better performance).
If such option is provided, it MUST be documented that for many receivers,
handling of maps with duplicate keys is unpredictable and it is the users'
responsibility to ensure keys are not duplicate.

Maps are equal when they contain the same key-value pairs,
irrespective of the order in which those elements appear
(unordered collection equality).

## Attribute

<a id="attributes"></a>

An `Attribute` is a key-value pair, which MUST have the following properties:

- The attribute key MUST be a non-`null` and non-empty string.
- Case sensitivity of keys is preserved. Keys that differ in casing are treated as distinct keys.
- The attribute value MUST be one of types defined in [AnyValue](#anyvalue).

Attributes are equal when their keys and values are equal.

See [Attribute Naming](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/general/naming.md#attributes) for naming guidelines.
Expand All @@ -68,26 +111,11 @@ See [Requirement Level](https://github.com/open-telemetry/semantic-conventions/b
See [this document](attribute-type-mapping.md) to find out how to map values obtained
outside OpenTelemetry into OpenTelemetry attribute values.

### Standard Attribute

Attributes are used in various places throughout the OpenTelemetry data model.
We designate the [previous attribute section](#attribute) as the standard
attribute definition, in order to facilitate more intuitive and consistent API /
SDK design.

The standard attribute definition SHOULD be used to represent attributes in data
modeling unless there is a strong justification to diverge. For example, the Log
Data Model has an extended [attributes](../logs/data-model.md#field-attributes)
definition allowing values of [type `Any`](../logs/data-model.md#type-any). This
reflects that LogRecord attributes are expected to model data produced from
external log APIs, which do not necessarily have the same value type
restrictions as the standard attribute definition.

### Attribute Limits

Execution of erroneous code can result in unintended attributes. If there are no
limits placed on attributes, they can quickly exhaust available memory, resulting
in crashes that are difficult to recover from safely.
limits placed on attribute collections, they can quickly exhaust available memory,
resulting in crashes that are difficult to recover from safely.

By default an SDK SHOULD apply truncation as per the list of
[configurable parameters](#configurable-parameters) below.
Expand All @@ -99,12 +127,24 @@ If an SDK provides a way to:
- if it is a string, if it exceeds that limit (counting any character in it as
1), SDKs MUST truncate that value, so that its length is at most equal
to the limit,
- if it is an array of strings, then apply the above rule to each of the
values separately,
- **Status**: [Development](../document-status.md) - if it is a byte array,
if its length exceeds that limit (counting each byte as 1),
SDKs MUST truncate that value, so that its length is at most equal to the limit,
- if it is an array of strings, then apply the limit to
each value within the array separately,
- **Status**: [Development](../document-status.md) - if it is an array of [AnyValue](#anyvalue),
then apply the limit to each element of the array separately (and recursively),
- **Status**: [Development](../document-status.md) - if it is a [map](#mapstring-anyvalue),
then apply the limit to each value within the map separately (and recursively),
- otherwise a value MUST NOT be truncated;
- set a limit of unique attribute keys such that:
- for each unique attribute key, addition of which would result in exceeding
the limit, SDK MUST discard that key/value pair.
- set an attribute count limit such that:
- if adding an attribute to an attribute collection would result
in exceeding the limit (counting each attribute in the collection as 1),
the SDK MUST discard that attribute, so that the total number of attributes in
an attribute collection is at most equal to the limit;
- **Status**: [Development](../document-status.md) - the count limit applies only to top-level attributes, not to nested key-value
pairs within [maps](#mapstring-anyvalue);
- otherwise an attribute MUST NOT be discarded.

There MAY be a log emitted to indicate to the user that an attribute was
truncated or discarded. To prevent excessive logging, the log MUST NOT be
Expand All @@ -121,10 +161,14 @@ use the model-specific limit, if it isn't set, then the SDK MUST attempt to use
the general limit. If neither are defined, then the SDK MUST try to use the
model-specific limit default value, followed by the global limit default value.

Note that the limits apply only to attributes collections.
Therefore, they do not apply to values within other data structures such as
[`LogRecord.Body`](../logs/data-model.md#field-body).

#### Configurable Parameters

* `AttributeCountLimit` (Default=128) - Maximum allowed attribute count per record;
* `AttributeValueLengthLimit` (Default=Infinity) - Maximum allowed attribute value length;
* `AttributeValueLengthLimit` (Default=Infinity) - Maximum allowed attribute value length (applies to string values and byte arrays);

#### Exempt Entities

Expand All @@ -148,9 +192,11 @@ at this time, as discussed in
[Spans](../trace/api.md#set-attributes), Span
[Events](../trace/api.md#add-events), Span
[Links](../trace/api.md#link) and
[Log Records](../logs/data-model.md) may contain a collection of attributes. The
keys in each such collection are unique, i.e. there MUST NOT exist more than one
key-value pair with the same key. The enforcement of uniqueness may be performed
[Log Records](../logs/data-model.md),
contain a collection of attributes.

Implementation MUST by default ensure that the exported attribute collections
contain only unique keys. The enforcement of uniqueness may be performed
in a variety of ways as it best fits the limitations of the particular
implementation.

Expand All @@ -173,6 +219,12 @@ that individual attribute value being exported using a streaming wire protocol.
In such cases the enforcement of uniqueness will likely be the responsibility of
the recipient of this data.

Implementations MAY have an option to allow exporting attribute collections
with duplicate keys (e.g. for better performance).
If such option is provided, it MUST be documented that for many receivers,
handling of maps with duplicate keys is unpredictable and it is the users'
responsibility to ensure keys are not duplicate.

Collection of attributes are equal when they contain the same attributes,
irrespective of the order in which those elements appear
(unordered collection equality).
Loading
Loading