From 026fad16d73816efc9b2eb064140959459531b55 Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Thu, 17 Jul 2025 23:34:06 +0200 Subject: [PATCH 01/67] Add empty value to attribute --- specification/common/README.md | 12 +++++------- specification/common/attribute-type-mapping.md | 6 ++++++ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/specification/common/README.md b/specification/common/README.md index 4b95d8b8508..1724db3cfcd 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -8,7 +8,7 @@ path_base_for_github_subdir: # Common specification concepts -**Status**: [Stable](../document-status.md) +**Status**: [Stable](../document-status.md), except where otherwise specified
Table of Contents @@ -38,15 +38,13 @@ 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. - An array of primitive type values. The array MUST be homogeneous, i.e., it MUST NOT contain values of different types. + - **Status**: [Stable](../document-status.md) - An empty value (e.g. `null`). 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 `[]`. -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. - -Attribute values of `null` are not valid and attempting to set a `null` value is -undefined behavior. +Attribute values 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 diff --git a/specification/common/attribute-type-mapping.md b/specification/common/attribute-type-mapping.md index e936eb1695c..56251663268 100644 --- a/specification/common/attribute-type-mapping.md +++ b/specification/common/attribute-type-mapping.md @@ -54,6 +54,12 @@ follow the rules described below. ### Primitive Values +#### Empty Value + +Empty values SHOULD be converted to AnyValue with no +[value](https://github.com/open-telemetry/opentelemetry-proto/blob/38b5b9b6e5257c6500a843f7fdacf89dd95833e8/opentelemetry/proto/common/v1/common.proto#L28-L30) +field being set. + #### Integer Values Integer values which are within the range of 64 bit signed numbers From 18311641df520e578137ef9ca11fc6766825595a Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Thu, 17 Jul 2025 23:35:32 +0200 Subject: [PATCH 02/67] Update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23a27cd2a00..139c4fadc81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,6 +57,9 @@ release. ### Common +- Add empty value to attribute. + ([#4595](https://github.com/open-telemetry/opentelemetry-specification/pull/4595)) + ### Supplementary Guidelines ### OTEPs From 82e8913989e8d3250fb546ea7398efe6b0f8f5d0 Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Thu, 17 Jul 2025 23:44:16 +0200 Subject: [PATCH 03/67] toc --- specification/common/attribute-type-mapping.md | 1 + 1 file changed, 1 insertion(+) diff --git a/specification/common/attribute-type-mapping.md b/specification/common/attribute-type-mapping.md index 56251663268..015847c8aeb 100644 --- a/specification/common/attribute-type-mapping.md +++ b/specification/common/attribute-type-mapping.md @@ -13,6 +13,7 @@ linkTitle: Mapping to AnyValue - [Converting to AnyValue](#converting-to-anyvalue) * [Primitive Values](#primitive-values) + + [Empty Value](#empty-value) + [Integer Values](#integer-values) + [Enumerations](#enumerations) + [Floating Point Values](#floating-point-values) From 9cab0c47c347298743bb795ac327d80187052b70 Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Thu, 17 Jul 2025 23:47:49 +0200 Subject: [PATCH 04/67] fix status --- specification/common/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/common/README.md b/specification/common/README.md index 1724db3cfcd..06806a5bc2b 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -38,7 +38,7 @@ 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. - An array of primitive type values. The array MUST be homogeneous, i.e., it MUST NOT contain values of different types. - - **Status**: [Stable](../document-status.md) - An empty value (e.g. `null`). + - **Status**: [Development](../document-status.md) - An empty value (e.g. `null`). 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 `[]`. From 85db60a47e8dfc50e793059dd229fcc60fccb22b Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Thu, 17 Jul 2025 23:58:27 +0200 Subject: [PATCH 05/67] Remove the note that extending attributes is a breaking change --- specification/common/README.md | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/specification/common/README.md b/specification/common/README.md index 06806a5bc2b..95ad05fbd08 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -81,21 +81,6 @@ 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. -Note: Extending the set of standard attribute value types is a breaking change. -This was decided after extensive debate, with arguments as follows: - -* Limiting the types of attribute values to a set which has proved sufficient - during several years of OpenTelemetry's development is a useful guardrail for - design. In taking additional value types off the table, we narrow the solution - space and have more productive design conversations. -* Upon proposing to extend support for complex value types, we received significant - pushback. Limiting attribute value types to primitives and arrays of primitives - simplifies data consumers' efforts to create search indexes and perform statistical - analysis. -* To address concerns over restricting standard attributes to primitive types, it was - called out that complex types can be encoded as existing primitive types, such as - representing datetime as a string or 64 bit integer. - ### Attribute Limits Execution of erroneous code can result in unintended attributes. If there are no From eaea1ea7dbe664bad1f6ae2b9cace004bb19d951 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Fri, 18 Jul 2025 00:24:52 +0200 Subject: [PATCH 06/67] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 139c4fadc81..f36b92b717b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,7 +57,7 @@ release. ### Common -- Add empty value to attribute. +- Add empty value attribute. ([#4595](https://github.com/open-telemetry/opentelemetry-specification/pull/4595)) ### Supplementary Guidelines From 25c2c257e4975284bf76b3fe3b70d12b4c71f0e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Fri, 18 Jul 2025 04:03:32 +0200 Subject: [PATCH 07/67] Update specification/common/attribute-type-mapping.md Co-authored-by: Tyler Yahn --- specification/common/attribute-type-mapping.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/common/attribute-type-mapping.md b/specification/common/attribute-type-mapping.md index 015847c8aeb..d41ebc82979 100644 --- a/specification/common/attribute-type-mapping.md +++ b/specification/common/attribute-type-mapping.md @@ -57,7 +57,7 @@ follow the rules described below. #### Empty Value -Empty values SHOULD be converted to AnyValue with no +Empty values MUST be converted to AnyValue with no [value](https://github.com/open-telemetry/opentelemetry-proto/blob/38b5b9b6e5257c6500a843f7fdacf89dd95833e8/opentelemetry/proto/common/v1/common.proto#L28-L30) field being set. From c5400989f60bb90e4e47407ec1c3b3c45322d61d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Tue, 22 Jul 2025 17:46:08 +0200 Subject: [PATCH 08/67] revert breaking change note --- specification/common/README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/specification/common/README.md b/specification/common/README.md index 95ad05fbd08..06806a5bc2b 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -81,6 +81,21 @@ 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. +Note: Extending the set of standard attribute value types is a breaking change. +This was decided after extensive debate, with arguments as follows: + +* Limiting the types of attribute values to a set which has proved sufficient + during several years of OpenTelemetry's development is a useful guardrail for + design. In taking additional value types off the table, we narrow the solution + space and have more productive design conversations. +* Upon proposing to extend support for complex value types, we received significant + pushback. Limiting attribute value types to primitives and arrays of primitives + simplifies data consumers' efforts to create search indexes and perform statistical + analysis. +* To address concerns over restricting standard attributes to primitive types, it was + called out that complex types can be encoded as existing primitive types, such as + representing datetime as a string or 64 bit integer. + ### Attribute Limits Execution of erroneous code can result in unintended attributes. If there are no From aa3c41ced17343159958d71b317c2b3b85da969c Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Tue, 26 Aug 2025 15:51:27 +0200 Subject: [PATCH 09/67] remove changelog entry --- CHANGELOG.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3ffc2288cb..71ec5ceaeb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,8 +33,6 @@ release. - ⚠️ **IMPORTANT**: Extending the set of standard attribute value types is no longer a breaking change. ([#4614](https://github.com/open-telemetry/opentelemetry-specification/pull/4614)) -- Add empty value attribute. - ([#4595](https://github.com/open-telemetry/opentelemetry-specification/pull/4595)) ### Supplementary Guidelines From 20043e347776af83df01e68fef233d5bf33822df Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Tue, 26 Aug 2025 16:10:46 +0200 Subject: [PATCH 10/67] remove "standard attribute" term --- ...nding-attributes-to-support-complex-values.md | 2 +- spec-compliance-matrix.md | 1 - specification/common/README.md | 16 ---------------- specification/entities/data-model.md | 4 ++-- specification/logs/api.md | 8 -------- specification/logs/data-model.md | 3 --- specification/resource/data-model.md | 6 +++--- specification/resource/sdk.md | 3 ++- 8 files changed, 8 insertions(+), 35 deletions(-) diff --git a/oteps/4485-extending-attributes-to-support-complex-values.md b/oteps/4485-extending-attributes-to-support-complex-values.md index 737c03732d4..8a3cbfe81d0 100644 --- a/oteps/4485-extending-attributes-to-support-complex-values.md +++ b/oteps/4485-extending-attributes-to-support-complex-values.md @@ -94,7 +94,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](/specification/common/README.md#attribute). We believe that removing this clause and extending standard attributes can be done gracefully across the OpenTelemetry ecosystem diff --git a/spec-compliance-matrix.md b/spec-compliance-matrix.md index 336058fd51d..eb9e585df41 100644 --- a/spec-compliance-matrix.md +++ b/spec-compliance-matrix.md @@ -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 | | | + | | + | | | + | | + | | | diff --git a/specification/common/README.md b/specification/common/README.md index 95ad05fbd08..ad4b94cacd3 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -16,7 +16,6 @@ path_base_for_github_subdir: - [Attribute](#attribute) - * [Standard Attribute](#standard-attribute) * [Attribute Limits](#attribute-limits) + [Configurable Parameters](#configurable-parameters) + [Exempt Entities](#exempt-entities) @@ -66,21 +65,6 @@ 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 diff --git a/specification/entities/data-model.md b/specification/entities/data-model.md index 22c277edd82..4c7c088657c 100644 --- a/specification/entities/data-model.md +++ b/specification/entities/data-model.md @@ -48,8 +48,8 @@ physical format and encoding of how entity data is recorded). | Field | Type | Description | |--------------|----------------------------------------|-----------------| | Type | string | Defines the type of the entity. MUST not change during the lifetime of the entity. For example: "service" or "host". This field is required and MUST not be empty for valid entities. | -| Id | map | Attributes that identify the entity.

MUST not change during the lifetime of the entity. The Id must contain at least one attribute.

Follows OpenTelemetry [Standard attribute definition](../common/README.md#standard-attribute). SHOULD follow OpenTelemetry [semantic conventions](https://github.com/open-telemetry/semantic-conventions) for attributes. | -| Description | map | Descriptive (non-identifying) attributes of the entity.

MAY change over the lifetime of the entity. MAY be empty. These attributes are not part of entity's identity.

Follows [any](../logs/data-model.md#type-any) value definition in the OpenTelemetry spec. Arbitrary deep nesting of values for arrays and maps is allowed.

SHOULD follow OpenTelemetry [semantic conventions](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/README.md) for attributes. | +| Id | map | Attributes that identify the entity.

MUST not change during the lifetime of the entity. The Id must contain at least one attribute.

Follows OpenTelemetry [attribute definition](../common/README.md#attribute). SHOULD follow OpenTelemetry [semantic conventions](https://github.com/open-telemetry/semantic-conventions) for attributes. | +| Description | map | Descriptive (non-identifying) attributes of the entity.

MAY change over the lifetime of the entity. MAY be empty. These attributes are not part of entity's identity.

Follows OpenTelemetry [attribute definition](../common/README.md#attribute). SHOULD follow OpenTelemetry [semantic conventions](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/README.md) for attributes. | ## Minimally Sufficient Identity diff --git a/specification/logs/api.md b/specification/logs/api.md index 977770be6fb..a0f11ce49fc 100644 --- a/specification/logs/api.md +++ b/specification/logs/api.md @@ -124,14 +124,6 @@ The API MUST accept the following parameters: - [Attributes](./data-model.md#field-attributes) (optional) - [Event Name](./data-model.md#field-eventname) (optional) -**Status**: [Development](../document-status.md) - -The API SHOULD provide functionality for users to convert -[Standard Attributes](../common/README.md#standard-attribute) -so they can be used, or directly accept them, in the log signal. -This allows the reuse of [Standard Attributes](../common/README.md#standard-attribute) -across signals. - ### Enabled To help users avoid performing computationally expensive operations when diff --git a/specification/logs/data-model.md b/specification/logs/data-model.md index 807e5899aa1..b8ba6c428e4 100644 --- a/specification/logs/data-model.md +++ b/specification/logs/data-model.md @@ -470,9 +470,6 @@ Description: Additional information about the specific event occurrence. Unlike the `Resource` field, which is fixed for a particular source, `Attributes` can vary for each occurrence of the event coming from the same source. Can contain information about the request context (other than [Trace Context Fields](#trace-context-fields)). -The log attribute model MUST support [`any` type](#type-any), -a superset of [standard Attribute](../common/README.md#attribute), -to preserve the semantics of structured attributes emitted by the applications. This field is optional. #### Errors and Exceptions diff --git a/specification/resource/data-model.md b/specification/resource/data-model.md index 60b924ddebb..6a9d579dc07 100644 --- a/specification/resource/data-model.md +++ b/specification/resource/data-model.md @@ -24,8 +24,8 @@ running in a container on Kubernetes, which is associated to a Pod running on a Node that is a VM but also is in a namespace and possibly is part of a Deployment. Resource could have attributes to denote information about the Container, the Pod, the Node, the VM or the Deployment. All of these help -identify what produced the telemetry. Note that there are certain "standard -attributes" that have prescribed meanings. +identify what produced the telemetry. Note that there are certain attributes +that have prescribed meanings. A resource is composed of 0 or more [`Entities`](../entities/README.md) and 0 or more attributes not associated with any entity. @@ -35,7 +35,7 @@ The data model below defines a logical model for an Resource (irrespective of th | Field | Type | Description | |------------|----------|-----------------| | Entities | set\ | Defines the set of Entities associated with this resource.

[Entity is defined here](../entities/data-model.md) | -| Attributes | map\ | Additional Attributes that identify the resource.

MUST not change during the lifetime of the resource.

Follows OpenTelemetry [Standard attribute definition](../common/README.md#standard-attribute). | +| Attributes | map\ | Additional Attributes that identify the resource.

MUST not change during the lifetime of the resource.

Follows OpenTelemetry [attribute definition](../common/README.md#attribute). | ## Identity diff --git a/specification/resource/sdk.md b/specification/resource/sdk.md index b7cb8cfa976..8a9a08b4cb0 100644 --- a/specification/resource/sdk.md +++ b/specification/resource/sdk.md @@ -13,7 +13,8 @@ For example, a process producing telemetry that is running in a container on Kubernetes has a Pod name, it is in a namespace and possibly is part of a Deployment which also has a name. All three of these attributes can be included in the `Resource`. Note that there are certain -["standard attributes"](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/resource/README.md) that have prescribed meanings. +[attributes](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/resource/README.md) +that have prescribed meanings. The primary purpose of resources as a first-class concept in the SDK is decoupling of discovery of resource information from exporters. This allows for From bfaf650c3c8541b24d22be4e055a9872c261e6a1 Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Tue, 26 Aug 2025 16:45:03 +0200 Subject: [PATCH 11/67] merge log attributes and standard attribute types --- specification/common/README.md | 60 +++++++++++++------- specification/logs/data-model.md | 94 ++------------------------------ 2 files changed, 46 insertions(+), 108 deletions(-) diff --git a/specification/common/README.md b/specification/common/README.md index ad4b94cacd3..74f066a4c82 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -8,7 +8,7 @@ path_base_for_github_subdir: # Common specification concepts -**Status**: [Stable](../document-status.md), except where otherwise specified +**Status**: [Stable](../document-status.md)

Table of Contents @@ -33,11 +33,28 @@ 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 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. - - **Status**: [Development](../document-status.md) - An empty value (e.g. `null`). +- The attribute value MUST be one of types defined in [Attribute Value](#attribute-value). + +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. + +See [Requirement Level](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/general/attribute-requirement-level.md) for requirement levels guidelines. + +See [this document](attribute-type-mapping.md) to find out how to map values obtained +outside OpenTelemetry into OpenTelemetry attribute values. + +### Attribute Value + +The attribute value is either: + + - a primitive type: string, boolean, double precision floating point (IEEE 754-1985), or signed 64 bit integer, + - an homogeneous array of primitive type values. An homogeneous array MUST NOT contain values of different types. + - a byte array. + - an heteregonous array of [Attribute Value](#attribute-value), + - an [Attribute Collection](#attribute-collections), + - an empty value (e.g. `null`). + 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 `[]`. @@ -45,10 +62,10 @@ Attribute values 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 +`null` values SHOULD NOT be allowed in homogeneous arrays. +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 homogeneous arrays MUST be preserved as-is (i.e., passed on to span 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 @@ -56,14 +73,8 @@ indices that are kept in sync (e.g., two attributes `header_keys` and `header_va both containing an array of strings to represent a mapping `header_keys[i] -> header_values[i]`). -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. - -See [Requirement Level](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/general/attribute-requirement-level.md) for requirement levels guidelines. - -See [this document](attribute-type-mapping.md) to find out how to map values obtained -outside OpenTelemetry into OpenTelemetry attribute values. +Arbitrary deep nesting of values for heteregonous arrays and attribute collections +is allowed (essentially allows to represent an equivalent of a JSON object). ### Attribute Limits @@ -130,9 +141,12 @@ 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), +and even [Attribute Value](#attribute-value) itself +may 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. @@ -155,6 +169,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). diff --git a/specification/logs/data-model.md b/specification/logs/data-model.md index b8ba6c428e4..67ac031b55d 100644 --- a/specification/logs/data-model.md +++ b/specification/logs/data-model.md @@ -15,10 +15,6 @@ weight: 2 - [Design Notes](#design-notes) * [Requirements](#requirements) * [Events](#events) - * [Definitions Used in this Document](#definitions-used-in-this-document) - + [Type `any`](#type-any) - + [Type `map`](#type-mapstring-any) - * [Field Kinds](#field-kinds) - [Log and Event Record Definition](#log-and-event-record-definition) * [Field: `Timestamp`](#field-timestamp) * [Field: `ObservedTimestamp`](#field-observedtimestamp) @@ -112,85 +108,6 @@ conventions defined for logs SHOULD be formatted as Events. Requirements and det Events are intended to be used by OpenTelemetry instrumentation. It is not a requirement that all LogRecords are formatted as Events. -### Definitions Used in this Document - -In this document we refer to types `any` and `map`, defined as -follows. - -#### Type `any` - -Value of type `any` can be one of the following: - -- A scalar value: string, boolean, signed 64 bit integer, or double precision floating point (IEEE 754-1985) - -- A byte array, - -- An array (a list) of `any` values, - -- A `map`, - -- [since 1.31.0] An empty value (e.g. `null`). - -#### Type `map` - -Value of type `map` is a map of string keys to `any` values. The -keys in the map are unique (duplicate keys are not allowed). - -Arbitrary deep nesting of values for arrays and maps is allowed (essentially -allows to represent an equivalent of a JSON object). - -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. - -### Field Kinds - -This Data Model defines a logical model for a log record (irrespective of the -physical format and encoding of the record). Each record contains 2 kinds of -fields: - -- Named top-level fields of specific type and meaning. - -- Fields stored as `map`, which can contain arbitrary values of - different types. The keys and values for well-known fields follow semantic - conventions for key names and possible values that allow all parties that work - with the field to have the same interpretation of the data. See references to - semantic conventions for `Resource` and `Attributes` fields and examples in - [Appendix A](./data-model-appendix.md#appendix-a-example-mappings). - -The reasons for having these 2 kinds of fields are: - -- Ability to efficiently represent named top-level fields, which are almost - always present (e.g. when using encodings like Protocol Buffers where fields - are enumerated but not named on the wire). - -- Ability to enforce types of named fields, which is very useful for compiled - languages with type checks. - -- Flexibility to represent less frequent data as `map`. This - includes well-known data that has standardized semantics as well as arbitrary - custom data that the application may want to include in the logs. - -When designing this data model we followed the following reasoning to make a -decision about when to use a top-level named field: - -- The field needs to be either mandatory for all records or be frequently - present in well-known log and event formats (such as `Timestamp`) or is - expected to be often present in log records in upcoming logging systems (such - as `TraceId`). - -- The field’s semantics must be the same for all known log and event formats and - can be mapped directly and unambiguously to this data model. - -Both of the above conditions were required to give the field a place in the -top-level structure of the record. - ## Log and Event Record Definition [Appendix A](./data-model-appendix.md#appendix-a-example-mappings) contains many examples that show how @@ -430,14 +347,15 @@ when it is used to represent an unspecified severity. ### Field: `Body` -Type: [`any`](#type-any). +Type: [Attribute Value](../common/README.md#attribute-value). Description: A value containing the body of the log record. Can be for example a human-readable string message (including multi-line) describing the event in a free form or it can be a structured data composed of arrays and maps of other -values. Body MUST support [`any` type](#type-any) to preserve the semantics of -structured logs emitted by the applications. Can vary for each occurrence of the -event coming from the same source. This field is optional. +values. Body MUST support [Attribute Value](../common/README.md#attribute-value) +types to preserve the semantics of structured logs emitted by the applications. +Can vary for each occurrence of the event coming from the same source. +This field is optional. ### Field: `Resource` @@ -464,7 +382,7 @@ they all have the same value of `InstrumentationScope`. This field is optional. ### Field: `Attributes` -Type: [`map`](#type-mapstring-any). +Type: [Attribute Collection](../common/README.md#attribute-collections). Description: Additional information about the specific event occurrence. Unlike the `Resource` field, which is fixed for a particular source, `Attributes` can From c17aec624a0c00f64b3e5347a44c1b30a6e59024 Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Tue, 26 Aug 2025 16:50:21 +0200 Subject: [PATCH 12/67] rename "Attribute Value" to "AnyValue" --- specification/common/README.md | 13 +++++++------ specification/logs/data-model.md | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/specification/common/README.md b/specification/common/README.md index 74f066a4c82..14bfa164581 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -16,6 +16,7 @@ path_base_for_github_subdir: - [Attribute](#attribute) + * [AnyValue](#anyvalue) * [Attribute Limits](#attribute-limits) + [Configurable Parameters](#configurable-parameters) + [Exempt Entities](#exempt-entities) @@ -33,7 +34,7 @@ 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 [Attribute Value](#attribute-value). +- The attribute value MUST be one of types defined in [AnyValue](#anyvalue). Attributes are equal when their keys and values are equal. @@ -44,21 +45,21 @@ 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. -### Attribute Value +### AnyValue -The attribute value is either: +`AnyValue` is either: - a primitive type: string, boolean, double precision floating point (IEEE 754-1985), or signed 64 bit integer, - an homogeneous array of primitive type values. An homogeneous array MUST NOT contain values of different types. - a byte array. - - an heteregonous array of [Attribute Value](#attribute-value), + - an heteregonous array of [AnyValue](#anyvalue), - an [Attribute Collection](#attribute-collections), - an empty value (e.g. `null`). 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 `[]`. -Attribute values expressing an empty value, a numerical value of zero, +`AnyValue` 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. @@ -142,7 +143,7 @@ at this time, as discussed in [Events](../trace/api.md#add-events), Span [Links](../trace/api.md#link) and [Log Records](../logs/data-model.md), -and even [Attribute Value](#attribute-value) itself +and even [AnyValue](#anyvalue) may contain a collection of attributes. Implementation MUST by default ensure that the exported attribute collections diff --git a/specification/logs/data-model.md b/specification/logs/data-model.md index 67ac031b55d..3faf5f9224f 100644 --- a/specification/logs/data-model.md +++ b/specification/logs/data-model.md @@ -347,7 +347,7 @@ when it is used to represent an unspecified severity. ### Field: `Body` -Type: [Attribute Value](../common/README.md#attribute-value). +Type: [AnyValue](../common/README.md#anyvalue). Description: A value containing the body of the log record. Can be for example a human-readable string message (including multi-line) describing the event in From 95b049ba1c24f6327d9e5641429790cfb9d31a90 Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Tue, 26 Aug 2025 16:54:32 +0200 Subject: [PATCH 13/67] mdlint --- specification/common/README.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/specification/common/README.md b/specification/common/README.md index 14bfa164581..fa1d5e7b0dd 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -49,13 +49,12 @@ outside OpenTelemetry into OpenTelemetry attribute values. `AnyValue` is either: - - a primitive type: string, boolean, double precision floating point (IEEE 754-1985), or signed 64 bit integer, - - an homogeneous array of primitive type values. An homogeneous array MUST NOT contain values of different types. - - a byte array. - - an heteregonous array of [AnyValue](#anyvalue), - - an [Attribute Collection](#attribute-collections), - - an empty value (e.g. `null`). - +- a primitive type: string, boolean, double precision floating point (IEEE 754-1985), or signed 64 bit integer, +- an homogeneous array of primitive type values. An homogeneous array MUST NOT contain values of different types. +- a byte array. +- an heteregonous array of [AnyValue](#anyvalue), +- an [Attribute Collection](#attribute-collections), +- an empty value (e.g. `null`). 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 `[]`. From b98d714abf2f695859a21eb8e423c238907639ce Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Tue, 26 Aug 2025 16:56:38 +0200 Subject: [PATCH 14/67] fix links --- oteps/entities/0256-entities-data-model.md | 4 ++-- specification/logs/data-model.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/oteps/entities/0256-entities-data-model.md b/oteps/entities/0256-entities-data-model.md index 51d5a00faae..70d0fde0b5f 100644 --- a/oteps/entities/0256-entities-data-model.md +++ b/oteps/entities/0256-entities-data-model.md @@ -139,7 +139,7 @@ MAY change over the lifetime of the entity. MAY be empty. These attributes are not part of entity's identity.

Follows any +href="https://github.com/open-telemetry/opentelemetry-specification/blob/v1.44.0/specification/logs/data-model.md#type-any">any 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. @@ -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. diff --git a/specification/logs/data-model.md b/specification/logs/data-model.md index 3faf5f9224f..ea95cb3d6e5 100644 --- a/specification/logs/data-model.md +++ b/specification/logs/data-model.md @@ -352,8 +352,8 @@ Type: [AnyValue](../common/README.md#anyvalue). Description: A value containing the body of the log record. Can be for example a human-readable string message (including multi-line) describing the event in a free form or it can be a structured data composed of arrays and maps of other -values. Body MUST support [Attribute Value](../common/README.md#attribute-value) -types to preserve the semantics of structured logs emitted by the applications. +values. Body MUST support [AnyValue](../common/README.md#anyvalue) to preserve +the semantics of structured logs emitted by the applications. Can vary for each occurrence of the event coming from the same source. This field is optional. From e55416d5e74a9ba71b562482de5e87b6f3cd9a2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Tue, 26 Aug 2025 18:15:10 +0200 Subject: [PATCH 15/67] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- specification/common/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specification/common/README.md b/specification/common/README.md index fa1d5e7b0dd..f7bd073e56e 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -50,9 +50,9 @@ outside OpenTelemetry into OpenTelemetry attribute values. `AnyValue` is either: - a primitive type: string, boolean, double precision floating point (IEEE 754-1985), or signed 64 bit integer, -- an homogeneous array of primitive type values. An homogeneous array MUST NOT contain values of different types. +- a homogeneous array of primitive type values. A homogeneous array MUST NOT contain values of different types. - a byte array. -- an heteregonous array of [AnyValue](#anyvalue), +- a heterogeneous array of [AnyValue](#anyvalue), - an [Attribute Collection](#attribute-collections), - an empty value (e.g. `null`). @@ -73,7 +73,7 @@ indices that are kept in sync (e.g., two attributes `header_keys` and `header_va both containing an array of strings to represent a mapping `header_keys[i] -> header_values[i]`). -Arbitrary deep nesting of values for heteregonous arrays and attribute collections +Arbitrary deep nesting of values for heterogeneous arrays and attribute collections is allowed (essentially allows to represent an equivalent of a JSON object). ### Attribute Limits From 49b41b4f37086e37f4c1073ac8d50ea896fa7ac5 Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Tue, 26 Aug 2025 19:42:07 +0200 Subject: [PATCH 16/67] Revert "rename "Attribute Value" to "AnyValue"" This reverts commit c17aec624a0c00f64b3e5347a44c1b30a6e59024. --- specification/common/README.md | 13 ++++++------- specification/logs/data-model.md | 6 +++--- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/specification/common/README.md b/specification/common/README.md index f7bd073e56e..7143a9203be 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -16,7 +16,6 @@ path_base_for_github_subdir: - [Attribute](#attribute) - * [AnyValue](#anyvalue) * [Attribute Limits](#attribute-limits) + [Configurable Parameters](#configurable-parameters) + [Exempt Entities](#exempt-entities) @@ -34,7 +33,7 @@ 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). +- The attribute value MUST be one of types defined in [Attribute Value](#attribute-value). Attributes are equal when their keys and values are equal. @@ -45,20 +44,20 @@ 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. -### AnyValue +### Attribute Value -`AnyValue` is either: +The attribute value is either: - 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. - a byte array. -- a heterogeneous array of [AnyValue](#anyvalue), +- a heterogeneous array of [Attribute Values](#attribute-value), - an [Attribute Collection](#attribute-collections), - an empty value (e.g. `null`). 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 `[]`. -`AnyValue` expressing an empty value, a numerical value of zero, +Attribute values 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. @@ -142,7 +141,7 @@ at this time, as discussed in [Events](../trace/api.md#add-events), Span [Links](../trace/api.md#link) and [Log Records](../logs/data-model.md), -and even [AnyValue](#anyvalue) +and even [Attribute Value](#attribute-value) itself may contain a collection of attributes. Implementation MUST by default ensure that the exported attribute collections diff --git a/specification/logs/data-model.md b/specification/logs/data-model.md index ea95cb3d6e5..5ba29aec4e6 100644 --- a/specification/logs/data-model.md +++ b/specification/logs/data-model.md @@ -347,13 +347,13 @@ when it is used to represent an unspecified severity. ### Field: `Body` -Type: [AnyValue](../common/README.md#anyvalue). +Type: [Attribute Value](../common/README.md#attribute-value). Description: A value containing the body of the log record. Can be for example a human-readable string message (including multi-line) describing the event in a free form or it can be a structured data composed of arrays and maps of other -values. Body MUST support [AnyValue](../common/README.md#anyvalue) to preserve -the semantics of structured logs emitted by the applications. +values. Body MUST support [Attribute Value](../common/README.md#attribute-value) +to preserve the semantics of structured logs emitted by the applications. Can vary for each occurrence of the event coming from the same source. This field is optional. From db81d62d2c36d6eadc51e960c436404fde582c30 Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Tue, 26 Aug 2025 19:43:50 +0200 Subject: [PATCH 17/67] toc --- specification/common/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/specification/common/README.md b/specification/common/README.md index 7143a9203be..9a88d8b464f 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -16,6 +16,7 @@ path_base_for_github_subdir: - [Attribute](#attribute) + * [Attribute Value](#attribute-value) * [Attribute Limits](#attribute-limits) + [Configurable Parameters](#configurable-parameters) + [Exempt Entities](#exempt-entities) From ad107698d73b2556cfbd01235d972241efee367e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Tue, 26 Aug 2025 19:45:23 +0200 Subject: [PATCH 18/67] Update specification/common/README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- specification/common/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/common/README.md b/specification/common/README.md index 9a88d8b464f..a41a5cf6984 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -54,7 +54,7 @@ The attribute value is either: - a byte array. - a heterogeneous array of [Attribute Values](#attribute-value), - an [Attribute Collection](#attribute-collections), -- an empty value (e.g. `null`). +- an empty value (e.g. `null`, `undefined` in JavaScript/TypeScript, `None` in Python, `nil` in Go/Ruby, etc.). 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 `[]`. From cc41e2f727b71b22b2b938aaa027d2a7e869e357 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Tue, 26 Aug 2025 19:45:40 +0200 Subject: [PATCH 19/67] Update specification/common/README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- specification/common/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/common/README.md b/specification/common/README.md index a41a5cf6984..36f256fdc46 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -62,7 +62,7 @@ Attribute values 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 homogeneous arrays. +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 homogeneous arrays MUST be preserved as-is (i.e., passed on to span From 8b029c8cd913713fad95103dc38c91e78abb2b27 Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Thu, 28 Aug 2025 10:40:03 +0200 Subject: [PATCH 20/67] propose Attribute Limits changes --- specification/common/README.md | 132 ++++++++++++++++++--------------- 1 file changed, 71 insertions(+), 61 deletions(-) diff --git a/specification/common/README.md b/specification/common/README.md index 36f256fdc46..e9e418e2507 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -17,10 +17,10 @@ path_base_for_github_subdir: - [Attribute](#attribute) * [Attribute Value](#attribute-value) - * [Attribute Limits](#attribute-limits) - + [Configurable Parameters](#configurable-parameters) - + [Exempt Entities](#exempt-entities) -- [Attribute Collections](#attribute-collections) + * [Attribute Collections](#attribute-collections) +- [Attribute Limits](#attribute-limits) + * [Configurable Parameters](#configurable-parameters) + * [Exempt Entities](#exempt-entities) @@ -49,14 +49,19 @@ outside OpenTelemetry into OpenTelemetry attribute values. The attribute value is either: -- 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. +- 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. - a byte array. - a heterogeneous array of [Attribute Values](#attribute-value), - an [Attribute Collection](#attribute-collections), - an empty value (e.g. `null`, `undefined` in JavaScript/TypeScript, `None` in Python, `nil` in Go/Ruby, etc.). -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 `[]`. +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 `[]`. Attribute values expressing an empty value, a numerical value of zero, an empty string, or an empty array are considered meaningful and MUST be stored @@ -76,7 +81,53 @@ both containing an array of strings to represent a mapping Arbitrary deep nesting of values for heterogeneous arrays and attribute collections is allowed (essentially allows to represent an equivalent of a JSON object). -### Attribute Limits +### Attribute Collections + +[Resources](../resource/sdk.md), +[Instrumentation Scopes](instrumentation-scope.md), +[Metric points](../metrics/data-model.md#metric-points), +[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), +and even [Attribute Value](#attribute-value) itself +may 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. + +Normally for the telemetry generated using OpenTelemetry SDKs the attribute +key-value pairs are set via an API that either accepts a single key-value pair +or a collection of key-value pairs. Setting an attribute with the same key as an +existing attribute SHOULD overwrite the existing attribute's value. See for +example Span's [SetAttribute](../trace/api.md#set-attributes) API. + +A typical implementation of [SetAttribute](../trace/api.md#set-attributes) API +will enforce the uniqueness by overwriting any existing attribute values pending +to be exported, so that when the Span is eventually exported the exporters see +only unique attributes. The OTLP format in particular requires that exported +Resources, Spans, Metric data points and Log Records contain only unique +attributes. + +Some other implementations may use a streaming approach where every +[SetAttribute](../trace/api.md#set-attributes) API call immediately results in +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). + +## 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 @@ -90,14 +141,18 @@ If an SDK provides a way to: - set an attribute value length limit such that for each attribute value: - 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 + 1), SDK 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, + - if it is an array or attributes collection, then apply the above rule to + each of its string values separately, - 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 an attribute addition into an attribute collection would result + in exceeding the limit (counting any attribute in it as 1 and nested + collections do contribute to the count of their parent), + SDK MUST discard that attribute, so that the total number of attributes in + an attribute collection is at most equal to the limit; + - 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 @@ -114,12 +169,12 @@ 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. -#### Configurable Parameters +### Configurable Parameters * `AttributeCountLimit` (Default=128) - Maximum allowed attribute count per record; * `AttributeValueLengthLimit` (Default=Infinity) - Maximum allowed attribute value length; -#### Exempt Entities +### Exempt Entities Resource attributes SHOULD be exempt from the limits described above as resources are not susceptible to the scenarios (auto-instrumentation) that result in @@ -133,48 +188,3 @@ Attributes, which belong to Metrics, are exempt from the limits described above at this time, as discussed in [Metrics Attribute Limits](../metrics/sdk.md#attribute-limits). -## Attribute Collections - -[Resources](../resource/sdk.md), -[Instrumentation Scopes](instrumentation-scope.md), -[Metric points](../metrics/data-model.md#metric-points), -[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), -and even [Attribute Value](#attribute-value) itself -may 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. - -Normally for the telemetry generated using OpenTelemetry SDKs the attribute -key-value pairs are set via an API that either accepts a single key-value pair -or a collection of key-value pairs. Setting an attribute with the same key as an -existing attribute SHOULD overwrite the existing attribute's value. See for -example Span's [SetAttribute](../trace/api.md#set-attributes) API. - -A typical implementation of [SetAttribute](../trace/api.md#set-attributes) API -will enforce the uniqueness by overwriting any existing attribute values pending -to be exported, so that when the Span is eventually exported the exporters see -only unique attributes. The OTLP format in particular requires that exported -Resources, Spans, Metric data points and Log Records contain only unique -attributes. - -Some other implementations may use a streaming approach where every -[SetAttribute](../trace/api.md#set-attributes) API call immediately results in -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). From a5851af0c21d67384b077b4d79062e1a5f069876 Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Thu, 28 Aug 2025 10:41:24 +0200 Subject: [PATCH 21/67] format --- specification/common/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/specification/common/README.md b/specification/common/README.md index e9e418e2507..b8d937c3e4c 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -56,7 +56,8 @@ The attribute value is either: - a byte array. - a heterogeneous array of [Attribute Values](#attribute-value), - an [Attribute Collection](#attribute-collections), -- an empty value (e.g. `null`, `undefined` in JavaScript/TypeScript, `None` in Python, `nil` in Go/Ruby, etc.). +- an empty value (e.g. `null`, `undefined` in JavaScript/TypeScript, + `None` in Python, `nil` in Go/Ruby, etc.). For protocols that do not natively support non-string values, non-string values SHOULD be represented as JSON-encoded strings. For example, the expression @@ -67,7 +68,8 @@ Attribute values 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. -While `null` is a valid attribute value, its use within homogeneous arrays SHOULD generally be avoided unless language constraints make this impossible. +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 homogeneous arrays MUST be preserved as-is (i.e., passed on to span From 52ccb34e4689f9d222ebd8af8dd22589a956465c Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Thu, 28 Aug 2025 11:01:36 +0200 Subject: [PATCH 22/67] remove EOL --- specification/common/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/specification/common/README.md b/specification/common/README.md index b8d937c3e4c..e5474027fdc 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -189,4 +189,3 @@ attribute limits for Resources. Attributes, which belong to Metrics, are exempt from the limits described above at this time, as discussed in [Metrics Attribute Limits](../metrics/sdk.md#attribute-limits). - From ecebf40fc8f79180f3db89d6fbfb78d868250afa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Thu, 28 Aug 2025 11:20:41 +0200 Subject: [PATCH 23/67] Update specification/common/README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- specification/common/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/common/README.md b/specification/common/README.md index e5474027fdc..b6ebaf25120 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -145,7 +145,7 @@ If an SDK provides a way to: - if it is a string, if it exceeds that limit (counting any character in it as 1), SDK MUST truncate that value, so that its length is at most equal to the limit, - - if it is an array or attributes collection, then apply the above rule to + - if it is an array or an attributes collection, then apply the above rule to each of its string values separately, - otherwise a value MUST NOT be truncated; - set an attribute count limit such that: From abfd0634885e99d82e07f53375c40496a85cb5a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Thu, 28 Aug 2025 11:20:48 +0200 Subject: [PATCH 24/67] Update specification/common/README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- specification/common/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/common/README.md b/specification/common/README.md index b6ebaf25120..8f3fa4a298a 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -143,7 +143,7 @@ If an SDK provides a way to: - set an attribute value length limit such that for each attribute value: - if it is a string, if it exceeds that limit (counting any character in it as - 1), SDK MUST truncate that value, so that its length is at most equal + 1), SDKs MUST truncate that value, so that its length is at most equal to the limit, - if it is an array or an attributes collection, then apply the above rule to each of its string values separately, From cbe15f58170a33825fcad9dc126ea773cd23a5a5 Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Thu, 28 Aug 2025 11:22:22 +0200 Subject: [PATCH 25/67] Apply code review suggestion --- specification/common/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/common/README.md b/specification/common/README.md index 8f3fa4a298a..c939c74049d 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -72,7 +72,7 @@ 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 homogeneous arrays MUST be preserved as-is (i.e., passed on to span +`null` values within homogeneous 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 From 7a3c387fbbcc3c7d68467a61324611f66446331b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Thu, 28 Aug 2025 11:39:46 +0200 Subject: [PATCH 26/67] Update specification/common/README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- specification/common/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/specification/common/README.md b/specification/common/README.md index c939c74049d..e1953aa0152 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -150,8 +150,7 @@ If an SDK provides a way to: - otherwise a value MUST NOT be truncated; - set an attribute count limit such that: - if an attribute addition into an attribute collection would result - in exceeding the limit (counting any attribute in it as 1 and nested - collections do contribute to the count of their parent), + in exceeding the limit (counting each attribute in the collection as 1; if an attribute is itself a collection, each key-value pair within the nested collection is also counted as a separate attribute of the parent), SDK MUST discard that attribute, so that the total number of attributes in an attribute collection is at most equal to the limit; - otherwise an attribute MUST NOT be discarded. From f2a508be995b057f94868b81f1eaa30d889332ee Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Thu, 28 Aug 2025 11:42:21 +0200 Subject: [PATCH 27/67] format --- specification/common/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/specification/common/README.md b/specification/common/README.md index e1953aa0152..923e362918b 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -150,7 +150,9 @@ If an SDK provides a way to: - otherwise a value MUST NOT be truncated; - set an attribute count limit such that: - if an attribute addition into an attribute collection would result - in exceeding the limit (counting each attribute in the collection as 1; if an attribute is itself a collection, each key-value pair within the nested collection is also counted as a separate attribute of the parent), + in exceeding the limit (counting each attribute in the collection as 1; + if an attribute is itself a collection, each key-value pair within + the nested collection is also counted as a separate attribute of the parent), SDK MUST discard that attribute, so that the total number of attributes in an attribute collection is at most equal to the limit; - otherwise an attribute MUST NOT be discarded. From ee4d8ba583465511f23cfc6f67d93f423d0f12a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Thu, 28 Aug 2025 11:43:30 +0200 Subject: [PATCH 28/67] Update specification/common/README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- specification/common/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/common/README.md b/specification/common/README.md index 923e362918b..4678fc9f124 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -145,7 +145,7 @@ 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 or an attributes collection, then apply the above rule to + - if it is an array or an attribute collection, then apply the above rule to each of its string values separately, - otherwise a value MUST NOT be truncated; - set an attribute count limit such that: From 10400ef53285cf11ad86c25b16ddd7b076e4a58b Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Thu, 28 Aug 2025 12:16:46 +0200 Subject: [PATCH 29/67] add attribute count example --- specification/common/README.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/specification/common/README.md b/specification/common/README.md index 4678fc9f124..118cc32aa18 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -151,12 +151,25 @@ If an SDK provides a way to: - set an attribute count limit such that: - if an attribute addition into an attribute collection would result in exceeding the limit (counting each attribute in the collection as 1; - if an attribute is itself a collection, each key-value pair within - the nested collection is also counted as a separate attribute of the parent), + if an attribute is itself a collection, each attribute within the nested + collection is also counted as a separate attribute of the parent), SDK MUST discard that attribute, so that the total number of attributes in an attribute collection is at most equal to the limit; - otherwise an attribute MUST NOT be discarded. +**Attribute count example:** +Consider an attribute collection with two attributes: + +- `a: 1` +- `b: { x: "foo", y: "bar", z: "baz" }` + +Here, `a` is a primitive attribute, and `b` is itself a collection with 3 attributes. +The total attribute count is calculated as follows: +- `a` counts as 1 +- Each attribute in `b` (`x`, `y`, `z`) counts as 1 each (total 3) +- `b` itself counts as 1 (the parent attribute) +- **Total attribute count = 1 (a) + 1 (b) + 3 (x, y, z) = 5**; + 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 emitted more than once per record on which an attribute is set. From f8236e7674c3a85de1baea70d8fd57dfdf8f736c Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Thu, 28 Aug 2025 12:21:19 +0200 Subject: [PATCH 30/67] format --- specification/common/README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/specification/common/README.md b/specification/common/README.md index 118cc32aa18..0d93b2dc1be 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -165,10 +165,12 @@ Consider an attribute collection with two attributes: Here, `a` is a primitive attribute, and `b` is itself a collection with 3 attributes. The total attribute count is calculated as follows: -- `a` counts as 1 -- Each attribute in `b` (`x`, `y`, `z`) counts as 1 each (total 3) -- `b` itself counts as 1 (the parent attribute) -- **Total attribute count = 1 (a) + 1 (b) + 3 (x, y, z) = 5**; + +- `a` counts as 1, +- each attribute in `b` (`x`, `y`, `z`) counts as 1 each (total 3), +- `b` itself counts as 1 (the parent attribute). + +Total attribute count = 1 (`a`) + 1 (`b`) + 3 (`x`, `y`, `z`) = 5 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 From 5b46a71a85205d267ab69e690adc9fd21493130f Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Wed, 3 Sep 2025 09:33:27 +0200 Subject: [PATCH 31/67] add AnyValue and map --- specification/common/README.md | 77 +++++++++++++++++++------------- specification/logs/data-model.md | 4 +- 2 files changed, 48 insertions(+), 33 deletions(-) diff --git a/specification/common/README.md b/specification/common/README.md index 0d93b2dc1be..1a8e5d7ecfb 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -15,8 +15,9 @@ path_base_for_github_subdir: +- [AnyValue](#anyvalue) +- [map](#mapstring-anyvalue) - [Attribute](#attribute) - * [Attribute Value](#attribute-value) * [Attribute Collections](#attribute-collections) - [Attribute Limits](#attribute-limits) * [Configurable Parameters](#configurable-parameters) @@ -26,36 +27,17 @@ path_base_for_github_subdir:

-## Attribute - - - -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 [Attribute Value](#attribute-value). - -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. - -See [Requirement Level](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/general/attribute-requirement-level.md) for requirement levels guidelines. - -See [this document](attribute-type-mapping.md) to find out how to map values obtained -outside OpenTelemetry into OpenTelemetry attribute values. +## AnyValue -### Attribute Value - -The attribute value is either: +`AnyValue` is either: - 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. - a byte array. -- a heterogeneous array of [Attribute Values](#attribute-value), -- an [Attribute Collection](#attribute-collections), +- a heterogeneous array of `AnyValue`, +- a [`map`](#mapstring-anyvalue), - an empty value (e.g. `null`, `undefined` in JavaScript/TypeScript, `None` in Python, `nil` in Go/Ruby, etc.). @@ -64,9 +46,9 @@ 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 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. +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. While `null` is a valid attribute value, its use within homogeneous arrays SHOULD generally be avoided unless language constraints make this impossible. @@ -80,8 +62,42 @@ indices that are kept in sync (e.g., two attributes `header_keys` and `header_va both containing an array of strings to represent a mapping `header_keys[i] -> header_values[i]`). -Arbitrary deep nesting of values for heterogeneous arrays and attribute collections -is allowed (essentially allows to represent an equivalent of a JSON object). +## map + +`map` is a map of string keys to `AnyValue` values. +The keys in the map are unique (duplicate keys are not allowed). + +Arbitrary deep nesting of values for arrays and maps is allowed (essentially +allows to represent an equivalent of a JSON object). + +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. + +## Attribute + + + +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. + +See [Requirement Level](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/general/attribute-requirement-level.md) for requirement levels guidelines. + +See [this document](attribute-type-mapping.md) to find out how to map values obtained +outside OpenTelemetry into OpenTelemetry attribute values. ### Attribute Collections @@ -92,8 +108,7 @@ is allowed (essentially allows to represent an equivalent of a JSON object). [Events](../trace/api.md#add-events), Span [Links](../trace/api.md#link) and [Log Records](../logs/data-model.md), -and even [Attribute Value](#attribute-value) itself -may contain a collection of attributes. +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 diff --git a/specification/logs/data-model.md b/specification/logs/data-model.md index 5ba29aec4e6..260d77187ea 100644 --- a/specification/logs/data-model.md +++ b/specification/logs/data-model.md @@ -347,12 +347,12 @@ when it is used to represent an unspecified severity. ### Field: `Body` -Type: [Attribute Value](../common/README.md#attribute-value). +Type: [AnyValue](../common/README.md#anyvalue). Description: A value containing the body of the log record. Can be for example a human-readable string message (including multi-line) describing the event in a free form or it can be a structured data composed of arrays and maps of other -values. Body MUST support [Attribute Value](../common/README.md#attribute-value) +values. Body MUST support [AnyValue](../common/README.md#anyvalue) to preserve the semantics of structured logs emitted by the applications. Can vary for each occurrence of the event coming from the same source. This field is optional. From 4a15e7cd5666fae9d038a9eb87d4c1158501ddca Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Wed, 3 Sep 2025 09:44:45 +0200 Subject: [PATCH 32/67] update Attribute Limits --- specification/common/README.md | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/specification/common/README.md b/specification/common/README.md index 1a8e5d7ecfb..5c95baf1acf 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -160,33 +160,20 @@ 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 or an attribute collection, then apply the above rule to - each of its string values separately, + - if it is a byte array, if it 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 [AnyValue](#anyvalue), then apply the limit to + each value within the array recursively, + - if it is a [`map`](#mapstring-anyvalue), then apply the + limit to each value within the map recursively, - otherwise a value MUST NOT be truncated; - set an attribute count limit such that: - if an attribute addition into an attribute collection would result - in exceeding the limit (counting each attribute in the collection as 1; - if an attribute is itself a collection, each attribute within the nested - collection is also counted as a separate attribute of the parent), + in exceeding the limit (counting each attribute in the collection as 1), SDK MUST discard that attribute, so that the total number of attributes in an attribute collection is at most equal to the limit; - otherwise an attribute MUST NOT be discarded. -**Attribute count example:** -Consider an attribute collection with two attributes: - -- `a: 1` -- `b: { x: "foo", y: "bar", z: "baz" }` - -Here, `a` is a primitive attribute, and `b` is itself a collection with 3 attributes. -The total attribute count is calculated as follows: - -- `a` counts as 1, -- each attribute in `b` (`x`, `y`, `z`) counts as 1 each (total 3), -- `b` itself counts as 1 (the parent attribute). - -Total attribute count = 1 (`a`) + 1 (`b`) + 3 (`x`, `y`, `z`) = 5 - 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 emitted more than once per record on which an attribute is set. @@ -205,7 +192,7 @@ model-specific limit default value, followed by the global limit default value. ### 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 From 552e997efb6904f5d103db6cfac86b17d0c01e91 Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Wed, 3 Sep 2025 09:51:36 +0200 Subject: [PATCH 33/67] fix toc --- specification/common/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specification/common/README.md b/specification/common/README.md index 5c95baf1acf..92480f71777 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -16,7 +16,7 @@ path_base_for_github_subdir: - [AnyValue](#anyvalue) -- [map](#mapstring-anyvalue) +- [map](#mapstring-anyvalue) - [Attribute](#attribute) * [Attribute Collections](#attribute-collections) - [Attribute Limits](#attribute-limits) @@ -164,7 +164,7 @@ If an SDK provides a way to: SDKs MUST truncate that value, so that its length is at most equal to the limit, - if it is an array of [AnyValue](#anyvalue), then apply the limit to each value within the array recursively, - - if it is a [`map`](#mapstring-anyvalue), then apply the + - if it is a [map](#mapstring-anyvalue), then apply the limit to each value within the map recursively, - otherwise a value MUST NOT be truncated; - set an attribute count limit such that: From b224937382f23d38faff661c2009722f8c60de86 Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Wed, 3 Sep 2025 09:54:29 +0200 Subject: [PATCH 34/67] fix limit rules --- specification/common/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/specification/common/README.md b/specification/common/README.md index 92480f71777..c8b68026e37 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -162,10 +162,12 @@ If an SDK provides a way to: to the limit, - if it is a byte array, if it 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 string, then apply the limit to + each value within the array separately, - if it is an array of [AnyValue](#anyvalue), then apply the limit to - each value within the array recursively, + each value within the array separately, - if it is a [map](#mapstring-anyvalue), then apply the - limit to each value within the map recursively, + limit to each value within the map separately, - otherwise a value MUST NOT be truncated; - set an attribute count limit such that: - if an attribute addition into an attribute collection would result From 9f04b588d267f6a00bf5ce0029210df15ddb8244 Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Mon, 8 Sep 2025 13:02:51 +0200 Subject: [PATCH 35/67] make it development --- specification/common/README.md | 18 ++++--- specification/logs/data-model.md | 87 +++++++++++++++++++++++++++++++- 2 files changed, 95 insertions(+), 10 deletions(-) diff --git a/specification/common/README.md b/specification/common/README.md index c8b68026e37..94af196b3c5 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -8,7 +8,7 @@ path_base_for_github_subdir: # Common specification concepts -**Status**: [Stable](../document-status.md) +**Status**: [Stable](../document-status.md), except where otherwise specified
Table of Contents @@ -35,10 +35,10 @@ path_base_for_github_subdir: (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. -- a byte array. -- a heterogeneous array of `AnyValue`, -- a [`map`](#mapstring-anyvalue), -- an empty value (e.g. `null`, `undefined` in JavaScript/TypeScript, +- **Status**: [Development](../document-status.md) - a byte array. +- **Status**: [Development](../document-status.md) - a heterogeneous array of `AnyValue`, +- **Status**: [Development](../document-status.md) - a [`map`](#mapstring-anyvalue), +- **Status**: [Development](../document-status.md) - an empty value (e.g. `null`, `undefined` in JavaScript/TypeScript, `None` in Python, `nil` in Go/Ruby, etc.). For protocols that do not natively support non-string values, non-string values @@ -64,6 +64,8 @@ both containing an array of strings to represent a mapping ## map +**Status**: [Development](../document-status.md) + `map` is a map of string keys to `AnyValue` values. The keys in the map are unique (duplicate keys are not allowed). @@ -160,13 +162,13 @@ 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 a byte array, if it exceeds that limit (counting each byte as 1), + - **Status**: [Development](../document-status.md) - if it is a byte array, if it 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 string, then apply the limit to each value within the array separately, - - if it is an array of [AnyValue](#anyvalue), then apply the limit to + - **Status**: [Development](../document-status.md) - if it is an array of [AnyValue](#anyvalue), then apply the limit to each value within the array separately, - - if it is a [map](#mapstring-anyvalue), then apply the + - **Status**: [Development](../document-status.md) - if it is a [map](#mapstring-anyvalue), then apply the limit to each value within the map separately, - otherwise a value MUST NOT be truncated; - set an attribute count limit such that: diff --git a/specification/logs/data-model.md b/specification/logs/data-model.md index 260d77187ea..6893df5c1cb 100644 --- a/specification/logs/data-model.md +++ b/specification/logs/data-model.md @@ -15,6 +15,10 @@ weight: 2 - [Design Notes](#design-notes) * [Requirements](#requirements) * [Events](#events) + * [Definitions Used in this Document](#definitions-used-in-this-document) + + [Type `any`](#type-any) + + [Type `map`](#type-mapstring-any) + * [Field Kinds](#field-kinds) - [Log and Event Record Definition](#log-and-event-record-definition) * [Field: `Timestamp`](#field-timestamp) * [Field: `ObservedTimestamp`](#field-observedtimestamp) @@ -108,6 +112,85 @@ conventions defined for logs SHOULD be formatted as Events. Requirements and det Events are intended to be used by OpenTelemetry instrumentation. It is not a requirement that all LogRecords are formatted as Events. +### Definitions Used in this Document + +In this document we refer to types `any` and `map`, defined as +follows. + +#### Type `any` + +Value of type `any` can be one of the following: + +- A scalar value: string, boolean, signed 64 bit integer, or double precision floating point (IEEE 754-1985) + +- A byte array, + +- An array (a list) of `any` values, + +- A `map`, + +- [since 1.31.0] An empty value (e.g. `null`). + +#### Type `map` + +Value of type `map` is a map of string keys to `any` values. The +keys in the map are unique (duplicate keys are not allowed). + +Arbitrary deep nesting of values for arrays and maps is allowed (essentially +allows to represent an equivalent of a JSON object). + +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. + +### Field Kinds + +This Data Model defines a logical model for a log record (irrespective of the +physical format and encoding of the record). Each record contains 2 kinds of +fields: + +- Named top-level fields of specific type and meaning. + +- Fields stored as `map`, which can contain arbitrary values of + different types. The keys and values for well-known fields follow semantic + conventions for key names and possible values that allow all parties that work + with the field to have the same interpretation of the data. See references to + semantic conventions for `Resource` and `Attributes` fields and examples in + [Appendix A](./data-model-appendix.md#appendix-a-example-mappings). + +The reasons for having these 2 kinds of fields are: + +- Ability to efficiently represent named top-level fields, which are almost + always present (e.g. when using encodings like Protocol Buffers where fields + are enumerated but not named on the wire). + +- Ability to enforce types of named fields, which is very useful for compiled + languages with type checks. + +- Flexibility to represent less frequent data as `map`. This + includes well-known data that has standardized semantics as well as arbitrary + custom data that the application may want to include in the logs. + +When designing this data model we followed the following reasoning to make a +decision about when to use a top-level named field: + +- The field needs to be either mandatory for all records or be frequently + present in well-known log and event formats (such as `Timestamp`) or is + expected to be often present in log records in upcoming logging systems (such + as `TraceId`). + +- The field’s semantics must be the same for all known log and event formats and + can be mapped directly and unambiguously to this data model. + +Both of the above conditions were required to give the field a place in the +top-level structure of the record. + ## Log and Event Record Definition [Appendix A](./data-model-appendix.md#appendix-a-example-mappings) contains many examples that show how @@ -347,7 +430,7 @@ when it is used to represent an unspecified severity. ### Field: `Body` -Type: [AnyValue](../common/README.md#anyvalue). +Type: [`any`](#type-any) or [AnyValue](../common/README.md#anyvalue). Description: A value containing the body of the log record. Can be for example a human-readable string message (including multi-line) describing the event in @@ -382,7 +465,7 @@ they all have the same value of `InstrumentationScope`. This field is optional. ### Field: `Attributes` -Type: [Attribute Collection](../common/README.md#attribute-collections). +Type: [`map`](#type-mapstring-any) or [Attribute Collection](../common/README.md#attribute-collections). Description: Additional information about the specific event occurrence. Unlike the `Resource` field, which is fixed for a particular source, `Attributes` can From 61a9a1bd21a97bd5182a69075aa26426b62f8e15 Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Mon, 8 Sep 2025 13:07:23 +0200 Subject: [PATCH 36/67] fix OTEP hyperlink --- oteps/4485-extending-attributes-to-support-complex-values.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oteps/4485-extending-attributes-to-support-complex-values.md b/oteps/4485-extending-attributes-to-support-complex-values.md index 8a3cbfe81d0..95f1a0c6423 100644 --- a/oteps/4485-extending-attributes-to-support-complex-values.md +++ b/oteps/4485-extending-attributes-to-support-complex-values.md @@ -94,7 +94,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#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 From 98fb4ae9f58e42cab61babbb922f870a50659d53 Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Mon, 8 Sep 2025 13:08:53 +0200 Subject: [PATCH 37/67] fix logs API status --- specification/logs/api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/logs/api.md b/specification/logs/api.md index a0f11ce49fc..66eb9c6b995 100644 --- a/specification/logs/api.md +++ b/specification/logs/api.md @@ -6,7 +6,7 @@ aliases: [bridge-api] # Logs API -**Status**: [Stable](../document-status.md), except where otherwise specified +**Status**: [Stable](../document-status.md)
Table of Contents From 253949fb3f6641d29ec333e10f151b1d1f96a510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Mon, 8 Sep 2025 13:11:30 +0200 Subject: [PATCH 38/67] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- specification/common/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specification/common/README.md b/specification/common/README.md index 94af196b3c5..b695c94978f 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -164,7 +164,7 @@ If an SDK provides a way to: to the limit, - **Status**: [Development](../document-status.md) - if it is a byte array, if it 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 string, then apply the limit to + - 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 value within the array separately, @@ -172,9 +172,9 @@ If an SDK provides a way to: limit to each value within the map separately, - otherwise a value MUST NOT be truncated; - set an attribute count limit such that: - - if an attribute addition into an attribute collection would result + - if adding an attribute to an attribute collection would result in exceeding the limit (counting each attribute in the collection as 1), - SDK MUST discard that attribute, so that the total number of attributes in + the SDK MUST discard that attribute, so that the total number of attributes in an attribute collection is at most equal to the limit; - otherwise an attribute MUST NOT be discarded. From d246e636488fe12da401f863ab01fbab83b03b55 Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Mon, 8 Sep 2025 13:19:19 +0200 Subject: [PATCH 39/67] Add changelog entry --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 893218373ad..4d2faf6020e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,14 @@ release. ([#4560](https://github.com/open-telemetry/opentelemetry-specification/pull/4560)) - ⚠️ **IMPORTANT**: Extending the set of standard attribute value types is no longer a breaking change. ([#4614](https://github.com/open-telemetry/opentelemetry-specification/pull/4614)) +- Extend the set of attribute value types to support more complex data structures. + ([#4651](https://github.com/open-telemetry/opentelemetry-specification/pull/4651)) + - Introduce of `AnyValue` type supporting complex data structures (empty value, + byte arrays, heterogeneous arrays and maps). + - Consolidate of attribute definitions across signals to use the unified + `AnyValue` type. + - Update attribute limits to accommodate new value types. + - Remove "standard attribute" terminology in favor of general "attribute". ### Supplementary Guidelines From 9e47faa0077cc3c72d94a2528a4d8d71567d8e8b Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Mon, 8 Sep 2025 13:20:42 +0200 Subject: [PATCH 40/67] mdlint --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d2faf6020e..e9f3ed3cd56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,7 +39,7 @@ release. ([#4651](https://github.com/open-telemetry/opentelemetry-specification/pull/4651)) - Introduce of `AnyValue` type supporting complex data structures (empty value, byte arrays, heterogeneous arrays and maps). - - Consolidate of attribute definitions across signals to use the unified + - Consolidate of attribute definitions across signals to use the unified `AnyValue` type. - Update attribute limits to accommodate new value types. - Remove "standard attribute" terminology in favor of general "attribute". From 1ac516ada133a1d802091d29c0921dbcefae45ec Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Mon, 8 Sep 2025 13:33:59 +0200 Subject: [PATCH 41/67] Remove "Reuse Standard Attribute" from spec compliance --- spec-compliance-matrix.md | 1 - spec-compliance-matrix/cpp.yaml | 2 -- spec-compliance-matrix/dotnet.yaml | 2 -- spec-compliance-matrix/erlang.yaml | 2 -- spec-compliance-matrix/go.yaml | 2 -- spec-compliance-matrix/java.yaml | 2 -- spec-compliance-matrix/js.yaml | 2 -- spec-compliance-matrix/php.yaml | 2 -- spec-compliance-matrix/python.yaml | 2 -- spec-compliance-matrix/ruby.yaml | 2 -- spec-compliance-matrix/rust.yaml | 2 -- spec-compliance-matrix/swift.yaml | 2 -- spec-compliance-matrix/template.yaml | 2 -- 13 files changed, 25 deletions(-) diff --git a/spec-compliance-matrix.md b/spec-compliance-matrix.md index 982dda53db9..2563fca6c97 100644 --- a/spec-compliance-matrix.md +++ b/spec-compliance-matrix.md @@ -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 | | | + | | + | | | + | | + | | | diff --git a/spec-compliance-matrix/cpp.yaml b/spec-compliance-matrix/cpp.yaml index 14e20252911..bbb91260975 100644 --- a/spec-compliance-matrix/cpp.yaml +++ b/spec-compliance-matrix/cpp.yaml @@ -357,8 +357,6 @@ sections: status: '+' - name: Logger.Emit(LogRecord) status: '+' - - name: Reuse Standard Attributes - status: '?' - name: LogRecord.Set EventName status: '+' - name: Logger.Enabled diff --git a/spec-compliance-matrix/dotnet.yaml b/spec-compliance-matrix/dotnet.yaml index 7e5004b911a..c250553d05b 100644 --- a/spec-compliance-matrix/dotnet.yaml +++ b/spec-compliance-matrix/dotnet.yaml @@ -357,8 +357,6 @@ sections: status: '-' - name: Logger.Emit(LogRecord) status: '-' - - name: Reuse Standard Attributes - status: '?' - name: LogRecord.Set EventName status: '?' - name: Logger.Enabled diff --git a/spec-compliance-matrix/erlang.yaml b/spec-compliance-matrix/erlang.yaml index 2ff35d5dc18..483278379cc 100644 --- a/spec-compliance-matrix/erlang.yaml +++ b/spec-compliance-matrix/erlang.yaml @@ -357,8 +357,6 @@ sections: status: '?' - name: Logger.Emit(LogRecord) status: '?' - - name: Reuse Standard Attributes - status: '?' - name: LogRecord.Set EventName status: '?' - name: Logger.Enabled diff --git a/spec-compliance-matrix/go.yaml b/spec-compliance-matrix/go.yaml index afe6052aec3..49d16998f93 100644 --- a/spec-compliance-matrix/go.yaml +++ b/spec-compliance-matrix/go.yaml @@ -357,8 +357,6 @@ sections: status: '?' - name: Logger.Emit(LogRecord) status: '?' - - name: Reuse Standard Attributes - status: '+' - name: LogRecord.Set EventName status: '+' - name: Logger.Enabled diff --git a/spec-compliance-matrix/java.yaml b/spec-compliance-matrix/java.yaml index a7cd7414f6d..bd3b8a2ef73 100644 --- a/spec-compliance-matrix/java.yaml +++ b/spec-compliance-matrix/java.yaml @@ -357,8 +357,6 @@ sections: status: '+' - name: Logger.Emit(LogRecord) status: '+' - - name: Reuse Standard Attributes - status: '?' - name: LogRecord.Set EventName status: '?' - name: Logger.Enabled diff --git a/spec-compliance-matrix/js.yaml b/spec-compliance-matrix/js.yaml index d85c0db6335..92d818aa3b1 100644 --- a/spec-compliance-matrix/js.yaml +++ b/spec-compliance-matrix/js.yaml @@ -357,8 +357,6 @@ sections: status: '?' - name: Logger.Emit(LogRecord) status: '?' - - name: Reuse Standard Attributes - status: '?' - name: LogRecord.Set EventName status: '?' - name: Logger.Enabled diff --git a/spec-compliance-matrix/php.yaml b/spec-compliance-matrix/php.yaml index c79d8e3a48b..2472e82ceeb 100644 --- a/spec-compliance-matrix/php.yaml +++ b/spec-compliance-matrix/php.yaml @@ -357,8 +357,6 @@ sections: status: '+' - name: Logger.Emit(LogRecord) status: '+' - - name: Reuse Standard Attributes - status: '?' - name: LogRecord.Set EventName status: '?' - name: Logger.Enabled diff --git a/spec-compliance-matrix/python.yaml b/spec-compliance-matrix/python.yaml index 11a70239ed0..4c26ef34258 100644 --- a/spec-compliance-matrix/python.yaml +++ b/spec-compliance-matrix/python.yaml @@ -357,8 +357,6 @@ sections: status: '+' - name: Logger.Emit(LogRecord) status: '+' - - name: Reuse Standard Attributes - status: '?' - name: LogRecord.Set EventName status: '?' - name: Logger.Enabled diff --git a/spec-compliance-matrix/ruby.yaml b/spec-compliance-matrix/ruby.yaml index d005ba9a0b5..6ac3532d193 100644 --- a/spec-compliance-matrix/ruby.yaml +++ b/spec-compliance-matrix/ruby.yaml @@ -357,8 +357,6 @@ sections: status: '?' - name: Logger.Emit(LogRecord) status: '?' - - name: Reuse Standard Attributes - status: '?' - name: LogRecord.Set EventName status: '?' - name: Logger.Enabled diff --git a/spec-compliance-matrix/rust.yaml b/spec-compliance-matrix/rust.yaml index 41ed148b9d7..7c2203ab5af 100644 --- a/spec-compliance-matrix/rust.yaml +++ b/spec-compliance-matrix/rust.yaml @@ -357,8 +357,6 @@ sections: status: '?' - name: Logger.Emit(LogRecord) status: '?' - - name: Reuse Standard Attributes - status: '?' - name: LogRecord.Set EventName status: '+' - name: Logger.Enabled diff --git a/spec-compliance-matrix/swift.yaml b/spec-compliance-matrix/swift.yaml index 73e78097f45..9bca50a7242 100644 --- a/spec-compliance-matrix/swift.yaml +++ b/spec-compliance-matrix/swift.yaml @@ -357,8 +357,6 @@ sections: status: '?' - name: Logger.Emit(LogRecord) status: '?' - - name: Reuse Standard Attributes - status: '?' - name: LogRecord.Set EventName status: '?' - name: Logger.Enabled diff --git a/spec-compliance-matrix/template.yaml b/spec-compliance-matrix/template.yaml index 26240de7d26..6b1a464dee4 100644 --- a/spec-compliance-matrix/template.yaml +++ b/spec-compliance-matrix/template.yaml @@ -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 From 2dd712dfd9a6b56a924cc592aa80380a1a6133a1 Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Mon, 8 Sep 2025 13:35:18 +0200 Subject: [PATCH 42/67] fmt --- specification/common/README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/specification/common/README.md b/specification/common/README.md index b695c94978f..fe697b0ca1a 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -162,14 +162,15 @@ 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, - - **Status**: [Development](../document-status.md) - if it is a byte array, if it exceeds that limit (counting each byte as 1), + - **Status**: [Development](../document-status.md) - if it is a byte array, + if it 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 value within the array separately, - - **Status**: [Development](../document-status.md) - if it is a [map](#mapstring-anyvalue), then apply the - limit to each value within the map separately, + - **Status**: [Development](../document-status.md) - if it is an array of [AnyValue](#anyvalue), + then apply the limit to each value within the array separately, + - **Status**: [Development](../document-status.md) - if it is a [map](#mapstring-anyvalue), + then apply the limit to each value within the map separately, - otherwise a value MUST NOT be truncated; - set an attribute count limit such that: - if adding an attribute to an attribute collection would result From a9b711d281fe38b93e46e45adc6b9fc9545c130b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Tue, 9 Sep 2025 15:53:09 +0200 Subject: [PATCH 43/67] Update specification/common/README.md Co-authored-by: Liudmila Molkova --- specification/common/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/common/README.md b/specification/common/README.md index fe697b0ca1a..d8efdad5a28 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -41,7 +41,7 @@ path_base_for_github_subdir: - **Status**: [Development](../document-status.md) - an empty value (e.g. `null`, `undefined` in JavaScript/TypeScript, `None` in Python, `nil` in Go/Ruby, etc.). -For protocols that do not natively support non-string values, non-string values +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 `[]`. From a1493d40e15be7a23fb13eb4607729f747019cba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Tue, 9 Sep 2025 15:54:40 +0200 Subject: [PATCH 44/67] Update specification/common/README.md Co-authored-by: Liudmila Molkova --- specification/common/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/common/README.md b/specification/common/README.md index d8efdad5a28..0811a8732ba 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -163,7 +163,7 @@ If an SDK provides a way to: 1), SDKs MUST truncate that value, so that its length is at most equal to the limit, - **Status**: [Development](../document-status.md) - if it is a byte array, - if it exceeds that limit (counting each byte as 1), + 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, From df857007171ca1843f32fb1b1725b3c26938c8bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Tue, 9 Sep 2025 15:55:06 +0200 Subject: [PATCH 45/67] Update specification/common/README.md Co-authored-by: Liudmila Molkova --- specification/common/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/common/README.md b/specification/common/README.md index 0811a8732ba..6996638210e 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -168,7 +168,7 @@ If an SDK provides a way to: - 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 value within the array separately, + 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, - otherwise a value MUST NOT be truncated; From 708686ecd34c7ab260b1af8e1c3f642218a42f67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Tue, 9 Sep 2025 15:55:18 +0200 Subject: [PATCH 46/67] Update specification/common/README.md Co-authored-by: Liudmila Molkova --- specification/common/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/common/README.md b/specification/common/README.md index 6996638210e..a1ec753adda 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -170,7 +170,7 @@ If an SDK provides a way to: - **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, + then apply the limit to each value within the map separately (and recursively), - otherwise a value MUST NOT be truncated; - set an attribute count limit such that: - if adding an attribute to an attribute collection would result From af80d42c8b44247bcbee97fe09afc4dcd9c75081 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Tue, 9 Sep 2025 16:07:58 +0200 Subject: [PATCH 47/67] Update specification/common/README.md Co-authored-by: Liudmila Molkova --- specification/common/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/common/README.md b/specification/common/README.md index a1ec753adda..73ebba98b14 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -62,7 +62,7 @@ indices that are kept in sync (e.g., two attributes `header_keys` and `header_va both containing an array of strings to represent a mapping `header_keys[i] -> header_values[i]`). -## map +### map **Status**: [Development](../document-status.md) From dca8512823e61cf7991eb0d134678acf43605a9c Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Tue, 9 Sep 2025 16:08:19 +0200 Subject: [PATCH 48/67] toc --- specification/common/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/common/README.md b/specification/common/README.md index 73ebba98b14..eafd0c58e75 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -16,7 +16,7 @@ path_base_for_github_subdir: - [AnyValue](#anyvalue) -- [map](#mapstring-anyvalue) + * [map](#mapstring-anyvalue) - [Attribute](#attribute) * [Attribute Collections](#attribute-collections) - [Attribute Limits](#attribute-limits) From ec94759b73bf92973b029df1595a86ad52e1d4c1 Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Tue, 9 Sep 2025 16:09:30 +0200 Subject: [PATCH 49/67] move note about deep nesting --- specification/common/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specification/common/README.md b/specification/common/README.md index eafd0c58e75..028428fad26 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -41,6 +41,9 @@ path_base_for_github_subdir: - **Status**: [Development](../document-status.md) - an empty value (e.g. `null`, `undefined` in JavaScript/TypeScript, `None` in Python, `nil` in Go/Ruby, etc.). +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 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`, @@ -69,9 +72,6 @@ both containing an array of strings to represent a mapping `map` is a map of string keys to `AnyValue` values. The keys in the map are unique (duplicate keys are not allowed). -Arbitrary deep nesting of values for arrays and maps is allowed (essentially -allows to represent an equivalent of a JSON object). - The representation of the map is language-dependent. The implementation MUST by default ensure that the exported maps contain only unique keys. From d4240f2ae75d4fde59c4683dc230e3ebf4cd10e6 Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Tue, 9 Sep 2025 18:25:48 +0200 Subject: [PATCH 50/67] make compliance-matrix --- spec-compliance-matrix.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/spec-compliance-matrix.md b/spec-compliance-matrix.md index 60fd8d020ad..ce4484cb868 100644 --- a/spec-compliance-matrix.md +++ b/spec-compliance-matrix.md @@ -196,9 +196,6 @@ Disclaimer: this list of features is still a work in progress, please refer to t | ------- | -------- | -- | ---- | -- | ------ | ---- | ------ | --- | ---- | --- | ---- | ----- | | LoggerProvider.Get Logger | | | + | | + | + | | + | | + | - | | | LoggerProvider.Get Logger accepts attributes | | | | | + | | | + | | + | | | -| LoggerProvider.Shutdown | | | + | | + | | | + | | + | - | | -| LoggerProvider.ForceFlush | | | + | | + | | | + | | + | - | | -| Logger.Emit(LogRecord) | | | + | | + | | | + | | + | - | | | LoggerProvider.Shutdown | | | + | | + | + | | + | | + | - | | | LoggerProvider.ForceFlush | | | + | | + | + | | + | | + | - | | | Logger.Emit(LogRecord) | | | + | | + | + | | + | | + | - | | From 9b210cae72e8bae21686bb203e5821cf0a5fe43b Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Tue, 9 Sep 2025 20:40:56 +0200 Subject: [PATCH 51/67] note that array and map values carry performance overhead --- specification/common/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/specification/common/README.md b/specification/common/README.md index 028428fad26..cf25d15bbf8 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -44,6 +44,9 @@ path_base_for_github_subdir: Arbitrary deep nesting of values for arrays and maps is allowed (essentially allows to represent an equivalent of a JSON object). +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. + 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`, From 851f4263f91428845d80a4727a1e8e4627705e9a Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Tue, 9 Sep 2025 20:45:36 +0200 Subject: [PATCH 52/67] update OTEP per feedback --- ...ding-attributes-to-support-complex-values.md | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/oteps/4485-extending-attributes-to-support-complex-values.md b/oteps/4485-extending-attributes-to-support-complex-values.md index 95f1a0c6423..23083ede638 100644 --- a/oteps/4485-extending-attributes-to-support-complex-values.md +++ b/oteps/4485-extending-attributes-to-support-complex-values.md @@ -125,22 +125,7 @@ simple attribute value for type checking, ergonomics, and performance reasons. Exposing multiple types of attribute sets is NOT RECOMMENDED, such as having "ExtendedAttributes" in addition to "Attributes". -OTel API MUST support setting complex attributes on spans, logs, profiles, -span links, and as descriptive entity attributes. - -OTel API MAY support setting complex attributes on metrics, resources, -instrumentation scope, span events, and as identifying entity attributes. - -> [!NOTE] -> "MAY" is used here instead of "MUST" to give flexibility to dynamically -> typed language APIs since there are no concrete use cases at this time -> requiring complex attributes in these areas. -> -> Most likely statically typed languages will choose to support -> setting complex attributes uniformly everywhere. -> -> This requirement level could change from "MAY" to "MUST" in the future -> if we uncover use cases for complex attributes in these areas. +OTel API MUST support setting complex attributes. API documentation and spec language around complex attributes SHOULD include language similar to this: From a5178c60278841b6044a713e319326f637e94ee7 Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Wed, 10 Sep 2025 14:19:05 +0200 Subject: [PATCH 53/67] remove redundant section --- specification/common/attribute-type-mapping.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/specification/common/attribute-type-mapping.md b/specification/common/attribute-type-mapping.md index d41ebc82979..e936eb1695c 100644 --- a/specification/common/attribute-type-mapping.md +++ b/specification/common/attribute-type-mapping.md @@ -13,7 +13,6 @@ linkTitle: Mapping to AnyValue - [Converting to AnyValue](#converting-to-anyvalue) * [Primitive Values](#primitive-values) - + [Empty Value](#empty-value) + [Integer Values](#integer-values) + [Enumerations](#enumerations) + [Floating Point Values](#floating-point-values) @@ -55,12 +54,6 @@ follow the rules described below. ### Primitive Values -#### Empty Value - -Empty values MUST be converted to AnyValue with no -[value](https://github.com/open-telemetry/opentelemetry-proto/blob/38b5b9b6e5257c6500a843f7fdacf89dd95833e8/opentelemetry/proto/common/v1/common.proto#L28-L30) -field being set. - #### Integer Values Integer values which are within the range of 64 bit signed numbers From 4f92d3dce6224797045da43e680a1a3dcebeac89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Wed, 10 Sep 2025 14:25:29 +0200 Subject: [PATCH 54/67] Update 4485-extending-attributes-to-support-complex-values.md --- ...ding-attributes-to-support-complex-values.md | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/oteps/4485-extending-attributes-to-support-complex-values.md b/oteps/4485-extending-attributes-to-support-complex-values.md index 23083ede638..d0914ad5f5d 100644 --- a/oteps/4485-extending-attributes-to-support-complex-values.md +++ b/oteps/4485-extending-attributes-to-support-complex-values.md @@ -137,22 +137,7 @@ language similar to this: ### SDK -OTel SDK MUST support setting complex attributes on spans, logs, profiles, -span links, and as descriptive entity attributes. - -OTel SDK MAY support setting complex attributes on metrics, exemplars, resources, -instrumentation scope, span events, and as identifying entity attributes. - -> [!NOTE] -> "MAY" is used here instead of "MUST" to give flexibility to dynamically -> typed language SDKs since there are no concrete use cases at this time -> requiring complex attributes in these areas. -> -> Most likely statically typed languages will choose to support -> setting complex attributes uniformly everywhere. -> -> This requirement level could change from "MAY" to "MUST" in the future -> if we uncover use cases for complex attributes in these areas. +OTel SDK MUST support setting complex attributes. The SDK MUST support reading and modifying complex attributes during processing whenever they are allowed on the API surface. From e3a1a65448190f9fbdee8bc01855fed3bb04f371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Thu, 18 Sep 2025 16:55:00 +0200 Subject: [PATCH 55/67] Update specification/common/README.md --- specification/common/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/common/README.md b/specification/common/README.md index cf25d15bbf8..de3d4f9546a 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -60,7 +60,7 @@ 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 homogeneous arrays MUST be preserved as-is (i.e., passed on to +`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 From d7d4eaa5ad690b0580d607b91672ba49f23f0ccd Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Tue, 23 Sep 2025 15:09:38 +0200 Subject: [PATCH 56/67] Clarify that for attribute count limit only the top-level attributes are counted --- specification/common/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/specification/common/README.md b/specification/common/README.md index de3d4f9546a..2ca1e3c168f 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -180,6 +180,8 @@ If an SDK provides a way to: 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; + - 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 From 4d7c1da31f33580c91ae0eb905cb8a8119e2836a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Tue, 23 Sep 2025 17:26:41 +0200 Subject: [PATCH 57/67] Update oteps/4485-extending-attributes-to-support-complex-values.md --- oteps/4485-extending-attributes-to-support-complex-values.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/oteps/4485-extending-attributes-to-support-complex-values.md b/oteps/4485-extending-attributes-to-support-complex-values.md index d0914ad5f5d..d19b94a5f4e 100644 --- a/oteps/4485-extending-attributes-to-support-complex-values.md +++ b/oteps/4485-extending-attributes-to-support-complex-values.md @@ -123,8 +123,6 @@ Existing APIs that create or add attributes will be extended to support It's RECOMMENDED to expose an `AnyValue` type - the API representing complex or simple attribute value for type checking, ergonomics, and performance reasons. -Exposing multiple types of attribute sets is NOT RECOMMENDED, such as having "ExtendedAttributes" in addition to "Attributes". - OTel API MUST support setting complex attributes. API documentation and spec language around complex attributes SHOULD include From d756e956843f106c8a8b9bd21d8bfc0f264bd73d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Tue, 23 Sep 2025 17:57:47 +0200 Subject: [PATCH 58/67] Update specification/common/README.md --- specification/common/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/common/README.md b/specification/common/README.md index 2ca1e3c168f..c3f815234d4 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -36,7 +36,7 @@ path_base_for_github_subdir: - 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) - a heterogeneous array of `AnyValue`, +- **Status**: [Development](../document-status.md) - an array of `AnyValue`, - **Status**: [Development](../document-status.md) - a [`map`](#mapstring-anyvalue), - **Status**: [Development](../document-status.md) - an empty value (e.g. `null`, `undefined` in JavaScript/TypeScript, `None` in Python, `nil` in Go/Ruby, etc.). From 815cf8baf98a5647971ab2f7c3f40540f8224ae1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Tue, 23 Sep 2025 18:01:08 +0200 Subject: [PATCH 59/67] Update CHANGELOG.md --- CHANGELOG.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22fbe7151e6..33b88c03a12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,12 +50,6 @@ release. ([#4614](https://github.com/open-telemetry/opentelemetry-specification/pull/4614)) - Extend the set of attribute value types to support more complex data structures. ([#4651](https://github.com/open-telemetry/opentelemetry-specification/pull/4651)) - - Introduce of `AnyValue` type supporting complex data structures (empty value, - byte arrays, heterogeneous arrays and maps). - - Consolidate of attribute definitions across signals to use the unified - `AnyValue` type. - - Update attribute limits to accommodate new value types. - - Remove "standard attribute" terminology in favor of general "attribute". ### OTEPs From e1386caceb6f5edb3f72b8111bcfac509126b991 Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Wed, 24 Sep 2025 13:42:35 +0200 Subject: [PATCH 60/67] Define equality of map --- specification/common/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/specification/common/README.md b/specification/common/README.md index c3f815234d4..d55f865e3e7 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -85,6 +85,10 @@ 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 From 703745c5970cf17eef9963191242ed17e32507aa Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Wed, 24 Sep 2025 13:48:35 +0200 Subject: [PATCH 61/67] Note that the limits apply only to attributes collections --- specification/common/README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/specification/common/README.md b/specification/common/README.md index d55f865e3e7..ae163da1a5b 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -156,8 +156,8 @@ irrespective of the order in which those elements appear ## 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. @@ -203,6 +203,10 @@ 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; From 6c8418eb9edd9c3b3b053a6eb0fbb143c3a93229 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Mon, 6 Oct 2025 20:24:55 +0200 Subject: [PATCH 62/67] Update specification/common/README.md --- specification/common/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specification/common/README.md b/specification/common/README.md index ae163da1a5b..b92155f552a 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -38,8 +38,8 @@ path_base_for_github_subdir: - **Status**: [Development](../document-status.md) - a byte array. - **Status**: [Development](../document-status.md) - an array of `AnyValue`, - **Status**: [Development](../document-status.md) - a [`map`](#mapstring-anyvalue), -- **Status**: [Development](../document-status.md) - an empty value (e.g. `null`, `undefined` in JavaScript/TypeScript, - `None` in Python, `nil` in Go/Ruby, etc.). +- **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.) Arbitrary deep nesting of values for arrays and maps is allowed (essentially allows to represent an equivalent of a JSON object). From 4a4af916a1eadf459044d1303ab9d2af27d383bc Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Tue, 14 Oct 2025 17:13:21 +0200 Subject: [PATCH 63/67] Move changlog entry to unreleased --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c80e520476..2506f5d2acd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 @@ -62,8 +65,6 @@ release. ([#4560](https://github.com/open-telemetry/opentelemetry-specification/pull/4560)) - ⚠️ **IMPORTANT**: Extending the set of standard attribute value types is no longer a breaking change. ([#4614](https://github.com/open-telemetry/opentelemetry-specification/pull/4614)) -- Extend the set of attribute value types to support more complex data structures. - ([#4651](https://github.com/open-telemetry/opentelemetry-specification/pull/4651)) ### OTEPs From 2884f43c47faba1ee46e118b047d85780c772280 Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Tue, 14 Oct 2025 17:24:07 +0200 Subject: [PATCH 64/67] Add appendix instead of changes in OTEP content --- ...ng-attributes-to-support-complex-values.md | 43 ++++++++++++++++++- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/oteps/4485-extending-attributes-to-support-complex-values.md b/oteps/4485-extending-attributes-to-support-complex-values.md index d19b94a5f4e..dc361744792 100644 --- a/oteps/4485-extending-attributes-to-support-complex-values.md +++ b/oteps/4485-extending-attributes-to-support-complex-values.md @@ -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) @@ -123,7 +124,24 @@ Existing APIs that create or add attributes will be extended to support It's RECOMMENDED to expose an `AnyValue` type - the API representing complex or simple attribute value for type checking, ergonomics, and performance reasons. -OTel API MUST support setting complex attributes. +Exposing multiple types of attribute sets is NOT RECOMMENDED, such as having "ExtendedAttributes" in addition to "Attributes". + +OTel API MUST support setting complex attributes on spans, logs, profiles, +span links, and as descriptive entity attributes. + +OTel API MAY support setting complex attributes on metrics, resources, +instrumentation scope, span events, and as identifying entity attributes. + +> [!NOTE] +> "MAY" is used here instead of "MUST" to give flexibility to dynamically +> typed language APIs since there are no concrete use cases at this time +> requiring complex attributes in these areas. +> +> Most likely statically typed languages will choose to support +> setting complex attributes uniformly everywhere. +> +> This requirement level could change from "MAY" to "MUST" in the future +> if we uncover use cases for complex attributes in these areas. API documentation and spec language around complex attributes SHOULD include language similar to this: @@ -135,7 +153,22 @@ language similar to this: ### SDK -OTel SDK MUST support setting complex attributes. +OTel SDK MUST support setting complex attributes on spans, logs, profiles, +span links, and as descriptive entity attributes. + +OTel SDK MAY support setting complex attributes on metrics, exemplars, resources, +instrumentation scope, span events, and as identifying entity attributes. + +> [!NOTE] +> "MAY" is used here instead of "MUST" to give flexibility to dynamically +> typed language SDKs since there are no concrete use cases at this time +> requiring complex attributes in these areas. +> +> Most likely statically typed languages will choose to support +> setting complex attributes uniformly everywhere. +> +> This requirement level could change from "MAY" to "MUST" in the future +> if we uncover use cases for complex attributes in these areas. The SDK MUST support reading and modifying complex attributes during processing whenever they are allowed on the API surface. @@ -277,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. From ab65c41b5028a74779f7a2e2480f88179349ee92 Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Thu, 16 Oct 2025 20:36:22 +0200 Subject: [PATCH 65/67] key case sensitivity in map --- specification/common/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/specification/common/README.md b/specification/common/README.md index b92155f552a..132a1007e29 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -75,6 +75,9 @@ both containing an array of strings to represent a mapping `map` 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. From 8fbd4fce21ea1d0b4177c952f24165dc94687b03 Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Thu, 16 Oct 2025 20:41:05 +0200 Subject: [PATCH 66/67] revert sections order --- specification/common/README.md | 104 ++++++++++++++++----------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/specification/common/README.md b/specification/common/README.md index 132a1007e29..a656ada68a9 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -18,10 +18,10 @@ path_base_for_github_subdir: - [AnyValue](#anyvalue) * [map](#mapstring-anyvalue) - [Attribute](#attribute) - * [Attribute Collections](#attribute-collections) -- [Attribute Limits](#attribute-limits) - * [Configurable Parameters](#configurable-parameters) - * [Exempt Entities](#exempt-entities) + * [Attribute Limits](#attribute-limits) + + [Configurable Parameters](#configurable-parameters) + + [Exempt Entities](#exempt-entities) +- [Attribute Collections](#attribute-collections) @@ -111,52 +111,7 @@ 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. -### Attribute Collections - -[Resources](../resource/sdk.md), -[Instrumentation Scopes](instrumentation-scope.md), -[Metric points](../metrics/data-model.md#metric-points), -[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), -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. - -Normally for the telemetry generated using OpenTelemetry SDKs the attribute -key-value pairs are set via an API that either accepts a single key-value pair -or a collection of key-value pairs. Setting an attribute with the same key as an -existing attribute SHOULD overwrite the existing attribute's value. See for -example Span's [SetAttribute](../trace/api.md#set-attributes) API. - -A typical implementation of [SetAttribute](../trace/api.md#set-attributes) API -will enforce the uniqueness by overwriting any existing attribute values pending -to be exported, so that when the Span is eventually exported the exporters see -only unique attributes. The OTLP format in particular requires that exported -Resources, Spans, Metric data points and Log Records contain only unique -attributes. - -Some other implementations may use a streaming approach where every -[SetAttribute](../trace/api.md#set-attributes) API call immediately results in -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). - -## Attribute Limits +### Attribute Limits Execution of erroneous code can result in unintended attributes. If there are no limits placed on attribute collections, they can quickly exhaust available memory, @@ -210,12 +165,12 @@ 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 +#### Configurable Parameters * `AttributeCountLimit` (Default=128) - Maximum allowed attribute count per record; * `AttributeValueLengthLimit` (Default=Infinity) - Maximum allowed attribute value length (applies to string values and byte arrays); -### Exempt Entities +#### Exempt Entities Resource attributes SHOULD be exempt from the limits described above as resources are not susceptible to the scenarios (auto-instrumentation) that result in @@ -228,3 +183,48 @@ attribute limits for Resources. Attributes, which belong to Metrics, are exempt from the limits described above at this time, as discussed in [Metrics Attribute Limits](../metrics/sdk.md#attribute-limits). + +## Attribute Collections + +[Resources](../resource/sdk.md), +[Instrumentation Scopes](instrumentation-scope.md), +[Metric points](../metrics/data-model.md#metric-points), +[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), +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. + +Normally for the telemetry generated using OpenTelemetry SDKs the attribute +key-value pairs are set via an API that either accepts a single key-value pair +or a collection of key-value pairs. Setting an attribute with the same key as an +existing attribute SHOULD overwrite the existing attribute's value. See for +example Span's [SetAttribute](../trace/api.md#set-attributes) API. + +A typical implementation of [SetAttribute](../trace/api.md#set-attributes) API +will enforce the uniqueness by overwriting any existing attribute values pending +to be exported, so that when the Span is eventually exported the exporters see +only unique attributes. The OTLP format in particular requires that exported +Resources, Spans, Metric data points and Log Records contain only unique +attributes. + +Some other implementations may use a streaming approach where every +[SetAttribute](../trace/api.md#set-attributes) API call immediately results in +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). From 35e2fd44174264899fe1ba95ec8e50e5eddcd0ef Mon Sep 17 00:00:00 2001 From: Robert Pajak Date: Thu, 16 Oct 2025 20:50:20 +0200 Subject: [PATCH 67/67] add status to attr count limit in maps --- specification/common/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/common/README.md b/specification/common/README.md index a656ada68a9..78b7dea9dae 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -142,7 +142,7 @@ If an SDK provides a way to: 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; - - the count limit applies only to top-level attributes, not to nested key-value + - **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.