diff --git a/CHANGELOG.md b/CHANGELOG.md index b3bf96db340..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 diff --git a/oteps/4485-extending-attributes-to-support-complex-values.md b/oteps/4485-extending-attributes-to-support-complex-values.md index 737c03732d4..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) @@ -94,7 +95,7 @@ extending the standard attributes provides a more seamless and user-friendly API Currently, the SDK specification has a clause that says extending the set of standard attribute would be -[considered a breaking change](/specification/common/README.md#standard-attribute). +[considered a breaking change](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.44.0/specification/common/README.md#standard-attribute). We believe that removing this clause and extending standard attributes can be done gracefully across the OpenTelemetry ecosystem @@ -309,3 +310,9 @@ for additional details. > [!NOTE] > This list only reflects the behavior at the time of writing and may change in the future. + +## Appendix + +The [Extend the set of attribute value types #4651](https://github.com/open-telemetry/opentelemetry-specification/pull/4651) PR implements part of this OTEP by requiring that both the OTel API and SDK MUST support complex attributes. +Some languages aim to support complex attributes for all kinds of telemetry. +To maintain consistency across languages, we agreed that all languages should provide the same level of support for complex attributes. 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/spec-compliance-matrix.md b/spec-compliance-matrix.md index 4afb3f68fe9..1a98a55d299 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 0f5e4ac5bac..822b5c76939 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 ccbf4bdb0c4..be292770c18 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 b5ee63fe9ea..a511671fe8c 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 0d012d6d184..3e95ec07f9c 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 6a5d80c2114..9f0bbe5ed94 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 c9b612f87d1..801a40128c0 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 1ce9890a2a2..6cfa96fdb52 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 3a6cecd32a1..d38947bf448 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 89a407985f7..5087a89b4e5 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 db4430f71c3..f9c42583095 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 9a8b194f38c..76d9ef90a39 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 60d2b2e5b68..d3eb46a334b 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 diff --git a/specification/common/README.md b/specification/common/README.md index 82f634d5dc9..78b7dea9dae 100644 --- a/specification/common/README.md +++ b/specification/common/README.md @@ -8,15 +8,16 @@ path_base_for_github_subdir: # Common specification concepts -**Status**: [Stable](../document-status.md) +**Status**: [Stable](../document-status.md), except where otherwise specified

Table of Contents +- [AnyValue](#anyvalue) + * [map](#mapstring-anyvalue) - [Attribute](#attribute) - * [Standard Attribute](#standard-attribute) * [Attribute Limits](#attribute-limits) + [Configurable Parameters](#configurable-parameters) + [Exempt Entities](#exempt-entities) @@ -26,32 +27,40 @@ path_base_for_github_subdir:
-## Attribute +## AnyValue - +`AnyValue` is either: -An `Attribute` is a key-value pair, which MUST have the following properties: +- a primitive type: string, boolean, double precision floating point + (IEEE 754-1985), or signed 64 bit integer, +- a homogeneous array of primitive type values. A homogeneous array MUST NOT + contain values of different types. +- **Status**: [Development](../document-status.md) - a byte array. +- **Status**: [Development](../document-status.md) - an array of `AnyValue`, +- **Status**: [Development](../document-status.md) - a [`map`](#mapstring-anyvalue), +- **Status**: [Development](../document-status.md) - an empty value if supported by the language, + (e.g. `null`, `undefined` in JavaScript/TypeScript, `None` in Python, `nil` in Go/Ruby, not supported in Erlang, etc.) -- The attribute key MUST be a non-`null` and non-empty string. - - Case sensitivity of keys is preserved. Keys that differ in casing are treated as distinct keys. -- The attribute value is either: - - A primitive type: string, boolean, double precision floating point (IEEE 754-1985) or signed 64 bit integer. - - An array of primitive type values. The array MUST be homogeneous, - i.e., it MUST NOT contain values of different types. +Arbitrary deep nesting of values for arrays and maps is allowed (essentially +allows to represent an equivalent of a JSON object). -For protocols that do not natively support non-string values, non-string values SHOULD be represented as JSON-encoded strings. For example, the expression `int64(100)` will be encoded as `100`, `float64(1.5)` will be encoded as `1.5`, and an empty array of any type will be encoded as `[]`. +APIs SHOULD be documented in a way to communicate to users that using array and +map values may carry higher performance overhead compared to primitive values. -Attribute values expressing a numerical value of zero, an empty string, or an -empty array are considered meaningful and MUST be stored and passed on to -processors / exporters. +For protocols that do not natively support some of the value types, corresponding values +SHOULD be represented as JSON-encoded strings. For example, the expression +`int64(100)` will be encoded as `100`, `float64(1.5)` will be encoded as `1.5`, +and an empty array of any type will be encoded as `[]`. -Attribute values of `null` are not valid and attempting to set a `null` value is -undefined behavior. +AnyValues expressing an empty value, a numerical value of zero, an empty string, +or an empty array are considered meaningful and MUST be stored and passed on to +processors / exporters. -`null` values SHOULD NOT be allowed in arrays. However, if it is impossible to -make sure that no `null` values are accepted +While `null` is a valid attribute value, its use within homogeneous arrays +SHOULD generally be avoided unless language constraints make this impossible. +However, if it is impossible to make sure that no `null` values are accepted (e.g. in languages that do not have appropriate compile-time type checking), -`null` values within arrays MUST be preserved as-is (i.e., passed on to span +`null` values within arrays MUST be preserved as-is (i.e., passed on to processors / exporters as `null`). If exporters do not support exporting `null` values, they MAY replace those values by 0, `false`, or empty strings. This is required for map/dictionary structures represented as two arrays with @@ -59,6 +68,40 @@ 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 + +**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). + +Case sensitivity of keys MUST be preserved. +Keys that differ in casing are treated as distinct keys. + +The representation of the map is language-dependent. + +The implementation MUST by default ensure that the exported maps contain only unique keys. + +The implementation MAY have an option to allow exporting maps with duplicate keys +(e.g. for better performance). +If such option is provided, it MUST be documented that for many receivers, +handling of maps with duplicate keys is unpredictable and it is the users' +responsibility to ensure keys are not duplicate. + +Maps are equal when they contain the same key-value pairs, +irrespective of the order in which those elements appear +(unordered collection equality). + +## Attribute + + + +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. @@ -68,26 +111,11 @@ See [Requirement Level](https://github.com/open-telemetry/semantic-conventions/b See [this document](attribute-type-mapping.md) to find out how to map values obtained outside OpenTelemetry into OpenTelemetry attribute values. -### Standard Attribute - -Attributes are used in various places throughout the OpenTelemetry data model. -We designate the [previous attribute section](#attribute) as the standard -attribute definition, in order to facilitate more intuitive and consistent API / -SDK design. - -The standard attribute definition SHOULD be used to represent attributes in data -modeling unless there is a strong justification to diverge. For example, the Log -Data Model has an extended [attributes](../logs/data-model.md#field-attributes) -definition allowing values of [type `Any`](../logs/data-model.md#type-any). This -reflects that LogRecord attributes are expected to model data produced from -external log APIs, which do not necessarily have the same value type -restrictions as the standard attribute definition. - ### Attribute Limits Execution of erroneous code can result in unintended attributes. If there are no -limits placed on attributes, they can quickly exhaust available memory, resulting -in crashes that are difficult to recover from safely. +limits placed on attribute collections, they can quickly exhaust available memory, +resulting in crashes that are difficult to recover from safely. By default an SDK SHOULD apply truncation as per the list of [configurable parameters](#configurable-parameters) below. @@ -99,12 +127,24 @@ If an SDK provides a way to: - if it is a string, if it exceeds that limit (counting any character in it as 1), SDKs MUST truncate that value, so that its length is at most equal to the limit, - - if it is an array of strings, then apply the above rule to each of the - values separately, + - **Status**: [Development](../document-status.md) - if it is a byte array, + if its length exceeds that limit (counting each byte as 1), + SDKs MUST truncate that value, so that its length is at most equal to the limit, + - if it is an array of strings, then apply the limit to + each value within the array separately, + - **Status**: [Development](../document-status.md) - if it is an array of [AnyValue](#anyvalue), + then apply the limit to each element of the array separately (and recursively), + - **Status**: [Development](../document-status.md) - if it is a [map](#mapstring-anyvalue), + then apply the limit to each value within the map separately (and recursively), - otherwise a value MUST NOT be truncated; -- set a limit of unique attribute keys such that: - - for each unique attribute key, addition of which would result in exceeding - the limit, SDK MUST discard that key/value pair. +- set an attribute count limit such that: + - if adding an attribute to an attribute collection would result + in exceeding the limit (counting each attribute in the collection as 1), + the SDK MUST discard that attribute, so that the total number of attributes in + an attribute collection is at most equal to the limit; + - **Status**: [Development](../document-status.md) - the count limit applies only to top-level attributes, not to nested key-value + pairs within [maps](#mapstring-anyvalue); + - otherwise an attribute MUST NOT be discarded. There MAY be a log emitted to indicate to the user that an attribute was truncated or discarded. To prevent excessive logging, the log MUST NOT be @@ -121,10 +161,14 @@ use the model-specific limit, if it isn't set, then the SDK MUST attempt to use the general limit. If neither are defined, then the SDK MUST try to use the model-specific limit default value, followed by the global limit default value. +Note that the limits apply only to attributes collections. +Therefore, they do not apply to values within other data structures such as +[`LogRecord.Body`](../logs/data-model.md#field-body). + #### Configurable Parameters * `AttributeCountLimit` (Default=128) - Maximum allowed attribute count per record; -* `AttributeValueLengthLimit` (Default=Infinity) - Maximum allowed attribute value length; +* `AttributeValueLengthLimit` (Default=Infinity) - Maximum allowed attribute value length (applies to string values and byte arrays); #### Exempt Entities @@ -148,9 +192,11 @@ at this time, as discussed in [Spans](../trace/api.md#set-attributes), Span [Events](../trace/api.md#add-events), Span [Links](../trace/api.md#link) and -[Log Records](../logs/data-model.md) may contain a collection of attributes. The -keys in each such collection are unique, i.e. there MUST NOT exist more than one -key-value pair with the same key. The enforcement of uniqueness may be performed +[Log Records](../logs/data-model.md), +contain a collection of attributes. + +Implementation MUST by default ensure that the exported attribute collections +contain only unique keys. The enforcement of uniqueness may be performed in a variety of ways as it best fits the limitations of the particular implementation. @@ -173,6 +219,12 @@ that individual attribute value being exported using a streaming wire protocol. In such cases the enforcement of uniqueness will likely be the responsibility of the recipient of this data. +Implementations MAY have an option to allow exporting attribute collections +with duplicate keys (e.g. for better performance). +If such option is provided, it MUST be documented that for many receivers, +handling of maps with duplicate keys is unpredictable and it is the users' +responsibility to ensure keys are not duplicate. + Collection of attributes are equal when they contain the same attributes, irrespective of the order in which those elements appear (unordered collection equality). 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..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 @@ -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..6893df5c1cb 100644 --- a/specification/logs/data-model.md +++ b/specification/logs/data-model.md @@ -430,14 +430,15 @@ when it is used to represent an unspecified severity. ### Field: `Body` -Type: [`any`](#type-any). +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 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 [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. ### Field: `Resource` @@ -464,15 +465,12 @@ they all have the same value of `InstrumentationScope`. This field is optional. ### Field: `Attributes` -Type: [`map`](#type-mapstring-any). +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 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