From d8b9bb3c3b1266b21164c5acc92fd2a17ba759e1 Mon Sep 17 00:00:00 2001 From: cijothomas Date: Thu, 14 May 2026 22:30:36 -0700 Subject: [PATCH 01/24] Add otel.sdk.component.shutdown self-observability event (#3718) --- .chloggen/sdk-component-shutdown-event.yaml | 9 ++ docs/otel/README.md | 1 + docs/otel/sdk-events.md | 133 ++++++++++++++++++++ docs/registry/attributes/otel.md | 28 ++++- model/otel/events.yaml | 40 ++++++ model/otel/registry.yaml | 32 +++++ 6 files changed, 237 insertions(+), 6 deletions(-) create mode 100644 .chloggen/sdk-component-shutdown-event.yaml create mode 100644 docs/otel/sdk-events.md create mode 100644 model/otel/events.yaml diff --git a/.chloggen/sdk-component-shutdown-event.yaml b/.chloggen/sdk-component-shutdown-event.yaml new file mode 100644 index 0000000000..691b2f5f5e --- /dev/null +++ b/.chloggen/sdk-component-shutdown-event.yaml @@ -0,0 +1,9 @@ +change_type: enhancement + +component: otel + +note: Add `otel.sdk.component.shutdown` self-observability event and supporting attributes (`otel.component.shutdown.outcome`, `otel.component.dropped_count`). + +issues: [3718] + +subtext: diff --git a/docs/otel/README.md b/docs/otel/README.md index 209b40aebf..cfce5ee4bc 100644 --- a/docs/otel/README.md +++ b/docs/otel/README.md @@ -10,6 +10,7 @@ This document defines semantic conventions for telemetry emitted by the OpenTele Semantic conventions are defined for the following signals: +* [Events](sdk-events.md) * [Metrics](sdk-metrics.md) [DocumentStatus]: https://opentelemetry.io/docs/specs/otel/document-status diff --git a/docs/otel/sdk-events.md b/docs/otel/sdk-events.md new file mode 100644 index 0000000000..99d04f19a7 --- /dev/null +++ b/docs/otel/sdk-events.md @@ -0,0 +1,133 @@ + + +# Semantic conventions for OpenTelemetry SDK events + +**Status**: [Development][DocumentStatus] + +This document describes events emitted by the OpenTelemetry SDK components themselves about their own lifecycle. + +These events are intended for SDK self-observability and answer questions +that metrics cannot easily answer on their own, such as +"did my pipeline drain cleanly when the application was shutting down?". + +> [!NOTE] +> Events are in-development and not yet available in some languages. Check the [spec-compliance matrix](https://github.com/open-telemetry/opentelemetry-specification/blob/main/spec-compliance-matrix.md#logs) to see the implementation status in the corresponding language. + + + +- [Component lifecycle events](#component-lifecycle-events) + - [Event: `otel.sdk.component.shutdown`](#event-otelsdkcomponentshutdown) + + + +## Component lifecycle events + +### Event: `otel.sdk.component.shutdown` + + + + + + +**Status:** ![Development](https://img.shields.io/badge/-development-blue) + +The event name MUST be `otel.sdk.component.shutdown`. + +Indicates that an OpenTelemetry SDK component (e.g. a span processor or exporter) has finished shutting down. + +The OpenTelemetry SDK SHOULD emit an `otel.sdk.component.shutdown` event from each long-lived +SDK component (e.g. the Batching Span Processor) when its `Shutdown` operation has completed, +either successfully, with errors, or after a timeout. + +The event is intended for SDK self-observability and answers the question +"did my pipeline drain cleanly when the application was shutting down?". +It is emitted exactly once per component instance per shutdown. + +The severity of the emitted log record SHOULD be: + +- `WARN` when `otel.component.shutdown.outcome` is not `success`, + or when `otel.component.dropped_count` is greater than `0`. +- `INFO` otherwise. + +Implementations MUST take care that emitting this event does not itself depend on the +component (or pipeline) that is being shut down. For example, the SDK SHOULD NOT route an +`otel.sdk.component.shutdown` event for a log processor through the same `LoggerProvider` +that owns the processor being shut down. + +The event body is not used (per the [event guidelines](/docs/general/events.md)). + +**Attributes:** + +| Key | Stability | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Value Type | Description | Example Values | +| --- | --- | --- | --- | --- | --- | +| [`otel.component.name`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | A name uniquely identifying the instance of the OpenTelemetry component within its containing SDK instance. [1] | `otlp_grpc_span_exporter/0`; `custom-name` | +| [`otel.component.shutdown.outcome`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | The outcome of an OpenTelemetry SDK component shutdown. | `success`; `failed`; `timed_out` | +| [`otel.component.type`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | A name identifying the type of the OpenTelemetry component. [2] | `batching_span_processor`; `com.example.MySpanExporter` | +| [`otel.component.dropped_count`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Recommended` If the component tracks a lifetime dropped count. | int | The total number of items the component dropped over its lifetime, up to and including the shutdown. [3] | `0`; `42` | + +**[1] `otel.component.name`:** Implementations SHOULD ensure a low cardinality for this attribute, even across application or SDK restarts. +E.g. implementations MUST NOT use UUIDs as values for this attribute. + +Implementations MAY achieve these goals by following a `/` pattern, e.g. `batching_span_processor/0`. +Hereby `otel.component.type` refers to the corresponding attribute value of the component. + +The value of `instance-counter` MAY be automatically assigned by the component and uniqueness within the enclosing SDK instance MUST be guaranteed. +For example, `` MAY be implemented by using a monotonically increasing counter (starting with `0`), which is incremented every time an +instance of the given component type is started. + +With this implementation, for example the first Batching Span Processor would have `batching_span_processor/0` +as `otel.component.name`, the second one `batching_span_processor/1` and so on. +These values will therefore be reused in the case of an application restart. + +**[2] `otel.component.type`:** If none of the standardized values apply, implementations SHOULD use the language-defined name of the type. +E.g. for Java the fully qualified classname SHOULD be used in this case. + +**[3] `otel.component.dropped_count`:** Counts items dropped for any reason, e.g. queue overflow or export failures that exhausted retries. +The value is the cumulative count from the time the component was started until the moment the +enclosing event (e.g. `otel.sdk.component.shutdown`) is emitted. + +--- + +`otel.component.shutdown.outcome` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. + +| Value | Description | Stability | +| --- | --- | --- | +| `failed` | The component shut down with one or more failures other than a timeout (e.g. an exporter rejected the final batch). | ![Development](https://img.shields.io/badge/-development-blue) | +| `success` | The component shut down cleanly and drained any pending work. | ![Development](https://img.shields.io/badge/-development-blue) | +| `timed_out` | The component did not finish shutting down within the configured shutdown timeout. | ![Development](https://img.shields.io/badge/-development-blue) | + +--- + +`otel.component.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. + +| Value | Description | Stability | +| --- | --- | --- | +| `batching_log_processor` | The builtin SDK batching log record processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `batching_span_processor` | The builtin SDK batching span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `otlp_grpc_log_exporter` | OTLP log record exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | +| `otlp_grpc_metric_exporter` | OTLP metric exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | +| `otlp_grpc_span_exporter` | OTLP span exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | +| `otlp_http_json_log_exporter` | OTLP log record exporter over HTTP with JSON serialization | ![Development](https://img.shields.io/badge/-development-blue) | +| `otlp_http_json_metric_exporter` | OTLP metric exporter over HTTP with JSON serialization | ![Development](https://img.shields.io/badge/-development-blue) | +| `otlp_http_json_span_exporter` | OTLP span exporter over HTTP with JSON serialization | ![Development](https://img.shields.io/badge/-development-blue) | +| `otlp_http_log_exporter` | OTLP log record exporter over HTTP with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | +| `otlp_http_metric_exporter` | OTLP metric exporter over HTTP with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | +| `otlp_http_span_exporter` | OTLP span exporter over HTTP with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | +| `periodic_metric_reader` | The builtin SDK periodically exporting metric reader | ![Development](https://img.shields.io/badge/-development-blue) | +| `prometheus_http_text_metric_exporter` | Prometheus metric exporter over HTTP with the default text-based format | ![Development](https://img.shields.io/badge/-development-blue) | +| `simple_log_processor` | The builtin SDK simple log record processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `simple_span_processor` | The builtin SDK simple span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `zipkin_http_span_exporter` | Zipkin span exporter over HTTP | ![Development](https://img.shields.io/badge/-development-blue) | + + + + + +The component being shut down is identified by the existing +[`otel.component.*`](/docs/registry/attributes/otel.md#otel-component-attributes) attributes, +not encoded in the event name. This keeps the event name stable across all SDK component types +(span processors, log processors, metric readers, exporters, etc.). + +[DocumentStatus]: https://opentelemetry.io/docs/specs/otel/document-status diff --git a/docs/registry/attributes/otel.md b/docs/registry/attributes/otel.md index 42b3cebd6a..44ac0d01cb 100644 --- a/docs/registry/attributes/otel.md +++ b/docs/registry/attributes/otel.md @@ -59,10 +59,16 @@ Attributes used for OpenTelemetry component self-monitoring | Key | Stability | Value Type | Description | Example Values | | --- | --- | --- | --- | --- | -| `otel.component.name` | ![Development](https://img.shields.io/badge/-development-blue) | string | A name uniquely identifying the instance of the OpenTelemetry component within its containing SDK instance. [1] | `otlp_grpc_span_exporter/0`; `custom-name` | -| `otel.component.type` | ![Development](https://img.shields.io/badge/-development-blue) | string | A name identifying the type of the OpenTelemetry component. [2] | `batching_span_processor`; `com.example.MySpanExporter` | +| `otel.component.dropped_count` | ![Development](https://img.shields.io/badge/-development-blue) | int | The total number of telemetry items (spans, log records, metric data points, etc.) the OpenTelemetry SDK component dropped over its lifetime. [1] | `0`; `42` | +| `otel.component.name` | ![Development](https://img.shields.io/badge/-development-blue) | string | A name uniquely identifying the instance of the OpenTelemetry component within its containing SDK instance. [2] | `otlp_grpc_span_exporter/0`; `custom-name` | +| `otel.component.shutdown.outcome` | ![Development](https://img.shields.io/badge/-development-blue) | string | The outcome of an OpenTelemetry SDK component shutdown. | `success`; `failed`; `timed_out` | +| `otel.component.type` | ![Development](https://img.shields.io/badge/-development-blue) | string | A name identifying the type of the OpenTelemetry component. [3] | `batching_span_processor`; `com.example.MySpanExporter` | -**[1] `otel.component.name`:** Implementations SHOULD ensure a low cardinality for this attribute, even across application or SDK restarts. +**[1] `otel.component.dropped_count`:** Counts items dropped for any reason, e.g. queue overflow or export failures that exhausted retries. +The value is the cumulative count from the time the component was started until the moment the +enclosing event (e.g. `otel.sdk.component.shutdown`) is emitted. + +**[2] `otel.component.name`:** Implementations SHOULD ensure a low cardinality for this attribute, even across application or SDK restarts. E.g. implementations MUST NOT use UUIDs as values for this attribute. Implementations MAY achieve these goals by following a `/` pattern, e.g. `batching_span_processor/0`. @@ -76,11 +82,21 @@ With this implementation, for example the first Batching Span Processor would ha as `otel.component.name`, the second one `batching_span_processor/1` and so on. These values will therefore be reused in the case of an application restart. -**[2] `otel.component.type`:** If none of the standardized values apply, implementations SHOULD use the language-defined name of the type. +**[3] `otel.component.type`:** If none of the standardized values apply, implementations SHOULD use the language-defined name of the type. E.g. for Java the fully qualified classname SHOULD be used in this case. --- +`otel.component.shutdown.outcome` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. + +| Value | Description | Stability | +| --- | --- | --- | +| `failed` | The component shut down with one or more failures other than a timeout (e.g. an exporter rejected the final batch). | ![Development](https://img.shields.io/badge/-development-blue) | +| `success` | The component shut down cleanly and drained any pending work. | ![Development](https://img.shields.io/badge/-development-blue) | +| `timed_out` | The component did not finish shutting down within the configured shutdown timeout. | ![Development](https://img.shields.io/badge/-development-blue) | + +--- + `otel.component.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. | Value | Description | Stability | @@ -110,9 +126,9 @@ Attributes used by non-OTLP exporters to represent OpenTelemetry Event's concept | Key | Stability | Value Type | Description | Example Values | | --- | --- | --- | --- | --- | -| `otel.event.name` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | string | Identifies the class / type of event. [3] | `browser.mouse.click`; `device.app.lifecycle` | +| `otel.event.name` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | string | Identifies the class / type of event. [4] | `browser.mouse.click`; `device.app.lifecycle` | -**[3] `otel.event.name`:** This attribute SHOULD be used by non-OTLP exporters when destination does not support `EventName` or equivalent field. This attribute MAY be used by applications using existing logging libraries so that it can be used to set the `EventName` field by Collector or SDK components. +**[4] `otel.event.name`:** This attribute SHOULD be used by non-OTLP exporters when destination does not support `EventName` or equivalent field. This attribute MAY be used by applications using existing logging libraries so that it can be used to set the `EventName` field by Collector or SDK components. ## OTel Scope Attributes diff --git a/model/otel/events.yaml b/model/otel/events.yaml new file mode 100644 index 0000000000..fb48969d00 --- /dev/null +++ b/model/otel/events.yaml @@ -0,0 +1,40 @@ +groups: + - id: event.otel.sdk.component.shutdown + type: event + name: otel.sdk.component.shutdown + stability: development + brief: > + Indicates that an OpenTelemetry SDK component (e.g. a span processor or exporter) has finished shutting down. + note: | + The OpenTelemetry SDK SHOULD emit an `otel.sdk.component.shutdown` event from each long-lived + SDK component (e.g. the Batching Span Processor) when its `Shutdown` operation has completed, + either successfully, with errors, or after a timeout. + + The event is intended for SDK self-observability and answers the question + "did my pipeline drain cleanly when the application was shutting down?". + It is emitted exactly once per component instance per shutdown. + + The severity of the emitted log record SHOULD be: + + - `WARN` when `otel.component.shutdown.outcome` is not `success`, + or when `otel.component.dropped_count` is greater than `0`. + - `INFO` otherwise. + + Implementations MUST take care that emitting this event does not itself depend on the + component (or pipeline) that is being shut down. For example, the SDK SHOULD NOT route an + `otel.sdk.component.shutdown` event for a log processor through the same `LoggerProvider` + that owns the processor being shut down. + + The event body is not used (per the [event guidelines](/docs/general/events.md)). + attributes: + - ref: otel.component.type + requirement_level: required + - ref: otel.component.name + requirement_level: required + - ref: otel.component.shutdown.outcome + requirement_level: required + - ref: otel.component.dropped_count + requirement_level: + recommended: If the component tracks a lifetime dropped count. + brief: > + The total number of items the component dropped over its lifetime, up to and including the shutdown. diff --git a/model/otel/registry.yaml b/model/otel/registry.yaml index 35c3b465df..623497840d 100644 --- a/model/otel/registry.yaml +++ b/model/otel/registry.yaml @@ -208,3 +208,35 @@ groups: as `otel.component.name`, the second one `batching_span_processor/1` and so on. These values will therefore be reused in the case of an application restart. examples: ["otlp_grpc_span_exporter/0", "custom-name"] + - id: otel.component.shutdown.outcome + type: + members: + - id: success + value: "success" + brief: > + The component shut down cleanly and drained any pending work. + stability: development + - id: failed + value: "failed" + brief: > + The component shut down with one or more failures other than a timeout (e.g. an exporter rejected the final batch). + stability: development + - id: timed_out + value: "timed_out" + brief: > + The component did not finish shutting down within the configured shutdown timeout. + stability: development + stability: development + brief: > + The outcome of an OpenTelemetry SDK component shutdown. + examples: ["success", "failed", "timed_out"] + - id: otel.component.dropped_count + type: int + stability: development + brief: > + The total number of telemetry items (spans, log records, metric data points, etc.) the OpenTelemetry SDK component dropped over its lifetime. + note: | + Counts items dropped for any reason, e.g. queue overflow or export failures that exhausted retries. + The value is the cumulative count from the time the component was started until the moment the + enclosing event (e.g. `otel.sdk.component.shutdown`) is emitted. + examples: [0, 42] From d97755d6ac066714a5f0a958aee5e0f987f2e189 Mon Sep 17 00:00:00 2001 From: cijothomas Date: Fri, 15 May 2026 07:15:22 -0700 Subject: [PATCH 02/24] Clarify severity rule and dropped_count semantics for non-buffering components --- docs/otel/sdk-events.md | 24 ++++++++++++++++++------ docs/registry/attributes/otel.md | 5 +++++ model/otel/events.yaml | 19 ++++++++++++++----- model/otel/registry.yaml | 5 +++++ 4 files changed, 42 insertions(+), 11 deletions(-) diff --git a/docs/otel/sdk-events.md b/docs/otel/sdk-events.md index 99d04f19a7..40d1c81c1b 100644 --- a/docs/otel/sdk-events.md +++ b/docs/otel/sdk-events.md @@ -45,11 +45,16 @@ The event is intended for SDK self-observability and answers the question "did my pipeline drain cleanly when the application was shutting down?". It is emitted exactly once per component instance per shutdown. -The severity of the emitted log record SHOULD be: +The severity of the emitted log record SHOULD be `WARN` if **any** of the following hold, +and `INFO` otherwise: -- `WARN` when `otel.component.shutdown.outcome` is not `success`, - or when `otel.component.dropped_count` is greater than `0`. -- `INFO` otherwise. +- `otel.component.shutdown.outcome` is not `success`, or +- `otel.component.dropped_count` is **present** and greater than `0`. + +Components that do not track a lifetime dropped count MUST omit +`otel.component.dropped_count`. Absence of the attribute MUST NOT be treated as `0` +for the severity rule above; it means "not applicable / not tracked" and the severity +is determined solely by `otel.component.shutdown.outcome` for those components. Implementations MUST take care that emitting this event does not itself depend on the component (or pipeline) that is being shut down. For example, the SDK SHOULD NOT route an @@ -65,7 +70,7 @@ The event body is not used (per the [event guidelines](/docs/general/events.md)) | [`otel.component.name`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | A name uniquely identifying the instance of the OpenTelemetry component within its containing SDK instance. [1] | `otlp_grpc_span_exporter/0`; `custom-name` | | [`otel.component.shutdown.outcome`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | The outcome of an OpenTelemetry SDK component shutdown. | `success`; `failed`; `timed_out` | | [`otel.component.type`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | A name identifying the type of the OpenTelemetry component. [2] | `batching_span_processor`; `com.example.MySpanExporter` | -| [`otel.component.dropped_count`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Recommended` If the component tracks a lifetime dropped count. | int | The total number of items the component dropped over its lifetime, up to and including the shutdown. [3] | `0`; `42` | +| [`otel.component.dropped_count`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Recommended` [3] | int | The total number of items the component dropped over its lifetime, up to and including the shutdown. [4] | `0`; `42` | **[1] `otel.component.name`:** Implementations SHOULD ensure a low cardinality for this attribute, even across application or SDK restarts. E.g. implementations MUST NOT use UUIDs as values for this attribute. @@ -84,10 +89,17 @@ These values will therefore be reused in the case of an application restart. **[2] `otel.component.type`:** If none of the standardized values apply, implementations SHOULD use the language-defined name of the type. E.g. for Java the fully qualified classname SHOULD be used in this case. -**[3] `otel.component.dropped_count`:** Counts items dropped for any reason, e.g. queue overflow or export failures that exhausted retries. +**[3] `otel.component.dropped_count`:** If the component tracks a lifetime dropped count (e.g. queue-based processors such as the Batching Span Processor or Batching Log Record Processor). Components that do not track this MUST omit the attribute; consumers MUST treat absence as "unknown", not as `0`. + +**[4] `otel.component.dropped_count`:** Counts items dropped for any reason, e.g. queue overflow or export failures that exhausted retries. The value is the cumulative count from the time the component was started until the moment the enclosing event (e.g. `otel.sdk.component.shutdown`) is emitted. +This attribute is only applicable to components that track a lifetime dropped count, such as +queue-based processors (e.g. the Batching Span Processor or Batching Log Record Processor). +Components that do not track this MUST omit the attribute. Consumers MUST treat absence as +"unknown / not applicable", not as `0`. + --- `otel.component.shutdown.outcome` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. diff --git a/docs/registry/attributes/otel.md b/docs/registry/attributes/otel.md index 44ac0d01cb..59a76b680a 100644 --- a/docs/registry/attributes/otel.md +++ b/docs/registry/attributes/otel.md @@ -68,6 +68,11 @@ Attributes used for OpenTelemetry component self-monitoring The value is the cumulative count from the time the component was started until the moment the enclosing event (e.g. `otel.sdk.component.shutdown`) is emitted. +This attribute is only applicable to components that track a lifetime dropped count, such as +queue-based processors (e.g. the Batching Span Processor or Batching Log Record Processor). +Components that do not track this MUST omit the attribute. Consumers MUST treat absence as +"unknown / not applicable", not as `0`. + **[2] `otel.component.name`:** Implementations SHOULD ensure a low cardinality for this attribute, even across application or SDK restarts. E.g. implementations MUST NOT use UUIDs as values for this attribute. diff --git a/model/otel/events.yaml b/model/otel/events.yaml index fb48969d00..f2e95575be 100644 --- a/model/otel/events.yaml +++ b/model/otel/events.yaml @@ -14,11 +14,16 @@ groups: "did my pipeline drain cleanly when the application was shutting down?". It is emitted exactly once per component instance per shutdown. - The severity of the emitted log record SHOULD be: + The severity of the emitted log record SHOULD be `WARN` if **any** of the following hold, + and `INFO` otherwise: - - `WARN` when `otel.component.shutdown.outcome` is not `success`, - or when `otel.component.dropped_count` is greater than `0`. - - `INFO` otherwise. + - `otel.component.shutdown.outcome` is not `success`, or + - `otel.component.dropped_count` is **present** and greater than `0`. + + Components that do not track a lifetime dropped count MUST omit + `otel.component.dropped_count`. Absence of the attribute MUST NOT be treated as `0` + for the severity rule above; it means "not applicable / not tracked" and the severity + is determined solely by `otel.component.shutdown.outcome` for those components. Implementations MUST take care that emitting this event does not itself depend on the component (or pipeline) that is being shut down. For example, the SDK SHOULD NOT route an @@ -35,6 +40,10 @@ groups: requirement_level: required - ref: otel.component.dropped_count requirement_level: - recommended: If the component tracks a lifetime dropped count. + recommended: > + If the component tracks a lifetime dropped count (e.g. queue-based processors such as + the Batching Span Processor or Batching Log Record Processor). Components that do not + track this MUST omit the attribute; consumers MUST treat absence as "unknown", + not as `0`. brief: > The total number of items the component dropped over its lifetime, up to and including the shutdown. diff --git a/model/otel/registry.yaml b/model/otel/registry.yaml index 623497840d..615e383d7e 100644 --- a/model/otel/registry.yaml +++ b/model/otel/registry.yaml @@ -239,4 +239,9 @@ groups: Counts items dropped for any reason, e.g. queue overflow or export failures that exhausted retries. The value is the cumulative count from the time the component was started until the moment the enclosing event (e.g. `otel.sdk.component.shutdown`) is emitted. + + This attribute is only applicable to components that track a lifetime dropped count, such as + queue-based processors (e.g. the Batching Span Processor or Batching Log Record Processor). + Components that do not track this MUST omit the attribute. Consumers MUST treat absence as + "unknown / not applicable", not as `0`. examples: [0, 42] From 060b2ca82ce03fe269e65b6effa192d557a5cbae Mon Sep 17 00:00:00 2001 From: cijothomas Date: Fri, 5 Jun 2026 13:44:30 -0700 Subject: [PATCH 03/24] Rename otel.component.shutdown.outcome to .result per review Per #2975, the convention is attribute = '.result' (per-event value), metric = '.outcome' (aggregated count). Renames the attribute and updates the brief to use 'result' for consistency. Addresses review feedback from @thompson-tomo on #3723. --- .chloggen/sdk-component-shutdown-event.yaml | 2 +- docs/otel/sdk-events.md | 8 ++++---- docs/registry/attributes/otel.md | 4 ++-- model/otel/events.yaml | 6 +++--- model/otel/registry.yaml | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.chloggen/sdk-component-shutdown-event.yaml b/.chloggen/sdk-component-shutdown-event.yaml index 691b2f5f5e..ac2a889562 100644 --- a/.chloggen/sdk-component-shutdown-event.yaml +++ b/.chloggen/sdk-component-shutdown-event.yaml @@ -2,7 +2,7 @@ change_type: enhancement component: otel -note: Add `otel.sdk.component.shutdown` self-observability event and supporting attributes (`otel.component.shutdown.outcome`, `otel.component.dropped_count`). +note: Add `otel.sdk.component.shutdown` self-observability event and supporting attributes (`otel.component.shutdown.result`, `otel.component.dropped_count`). issues: [3718] diff --git a/docs/otel/sdk-events.md b/docs/otel/sdk-events.md index 40d1c81c1b..854ee40ab0 100644 --- a/docs/otel/sdk-events.md +++ b/docs/otel/sdk-events.md @@ -48,13 +48,13 @@ It is emitted exactly once per component instance per shutdown. The severity of the emitted log record SHOULD be `WARN` if **any** of the following hold, and `INFO` otherwise: -- `otel.component.shutdown.outcome` is not `success`, or +- `otel.component.shutdown.result` is not `success`, or - `otel.component.dropped_count` is **present** and greater than `0`. Components that do not track a lifetime dropped count MUST omit `otel.component.dropped_count`. Absence of the attribute MUST NOT be treated as `0` for the severity rule above; it means "not applicable / not tracked" and the severity -is determined solely by `otel.component.shutdown.outcome` for those components. +is determined solely by `otel.component.shutdown.result` for those components. Implementations MUST take care that emitting this event does not itself depend on the component (or pipeline) that is being shut down. For example, the SDK SHOULD NOT route an @@ -68,7 +68,7 @@ The event body is not used (per the [event guidelines](/docs/general/events.md)) | Key | Stability | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Value Type | Description | Example Values | | --- | --- | --- | --- | --- | --- | | [`otel.component.name`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | A name uniquely identifying the instance of the OpenTelemetry component within its containing SDK instance. [1] | `otlp_grpc_span_exporter/0`; `custom-name` | -| [`otel.component.shutdown.outcome`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | The outcome of an OpenTelemetry SDK component shutdown. | `success`; `failed`; `timed_out` | +| [`otel.component.shutdown.result`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | The result of an OpenTelemetry SDK component shutdown. | `success`; `failed`; `timed_out` | | [`otel.component.type`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | A name identifying the type of the OpenTelemetry component. [2] | `batching_span_processor`; `com.example.MySpanExporter` | | [`otel.component.dropped_count`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Recommended` [3] | int | The total number of items the component dropped over its lifetime, up to and including the shutdown. [4] | `0`; `42` | @@ -102,7 +102,7 @@ Components that do not track this MUST omit the attribute. Consumers MUST treat --- -`otel.component.shutdown.outcome` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. +`otel.component.shutdown.result` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. | Value | Description | Stability | | --- | --- | --- | diff --git a/docs/registry/attributes/otel.md b/docs/registry/attributes/otel.md index 59a76b680a..da90d71875 100644 --- a/docs/registry/attributes/otel.md +++ b/docs/registry/attributes/otel.md @@ -61,7 +61,7 @@ Attributes used for OpenTelemetry component self-monitoring | --- | --- | --- | --- | --- | | `otel.component.dropped_count` | ![Development](https://img.shields.io/badge/-development-blue) | int | The total number of telemetry items (spans, log records, metric data points, etc.) the OpenTelemetry SDK component dropped over its lifetime. [1] | `0`; `42` | | `otel.component.name` | ![Development](https://img.shields.io/badge/-development-blue) | string | A name uniquely identifying the instance of the OpenTelemetry component within its containing SDK instance. [2] | `otlp_grpc_span_exporter/0`; `custom-name` | -| `otel.component.shutdown.outcome` | ![Development](https://img.shields.io/badge/-development-blue) | string | The outcome of an OpenTelemetry SDK component shutdown. | `success`; `failed`; `timed_out` | +| `otel.component.shutdown.result` | ![Development](https://img.shields.io/badge/-development-blue) | string | The result of an OpenTelemetry SDK component shutdown. | `success`; `failed`; `timed_out` | | `otel.component.type` | ![Development](https://img.shields.io/badge/-development-blue) | string | A name identifying the type of the OpenTelemetry component. [3] | `batching_span_processor`; `com.example.MySpanExporter` | **[1] `otel.component.dropped_count`:** Counts items dropped for any reason, e.g. queue overflow or export failures that exhausted retries. @@ -92,7 +92,7 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. --- -`otel.component.shutdown.outcome` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. +`otel.component.shutdown.result` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. | Value | Description | Stability | | --- | --- | --- | diff --git a/model/otel/events.yaml b/model/otel/events.yaml index f2e95575be..16e49ae71c 100644 --- a/model/otel/events.yaml +++ b/model/otel/events.yaml @@ -17,13 +17,13 @@ groups: The severity of the emitted log record SHOULD be `WARN` if **any** of the following hold, and `INFO` otherwise: - - `otel.component.shutdown.outcome` is not `success`, or + - `otel.component.shutdown.result` is not `success`, or - `otel.component.dropped_count` is **present** and greater than `0`. Components that do not track a lifetime dropped count MUST omit `otel.component.dropped_count`. Absence of the attribute MUST NOT be treated as `0` for the severity rule above; it means "not applicable / not tracked" and the severity - is determined solely by `otel.component.shutdown.outcome` for those components. + is determined solely by `otel.component.shutdown.result` for those components. Implementations MUST take care that emitting this event does not itself depend on the component (or pipeline) that is being shut down. For example, the SDK SHOULD NOT route an @@ -36,7 +36,7 @@ groups: requirement_level: required - ref: otel.component.name requirement_level: required - - ref: otel.component.shutdown.outcome + - ref: otel.component.shutdown.result requirement_level: required - ref: otel.component.dropped_count requirement_level: diff --git a/model/otel/registry.yaml b/model/otel/registry.yaml index 615e383d7e..f166305253 100644 --- a/model/otel/registry.yaml +++ b/model/otel/registry.yaml @@ -208,7 +208,7 @@ groups: as `otel.component.name`, the second one `batching_span_processor/1` and so on. These values will therefore be reused in the case of an application restart. examples: ["otlp_grpc_span_exporter/0", "custom-name"] - - id: otel.component.shutdown.outcome + - id: otel.component.shutdown.result type: members: - id: success @@ -228,7 +228,7 @@ groups: stability: development stability: development brief: > - The outcome of an OpenTelemetry SDK component shutdown. + The result of an OpenTelemetry SDK component shutdown. examples: ["success", "failed", "timed_out"] - id: otel.component.dropped_count type: int From b5a1192ead780d4546fd6ebcf05e6b3921c476d2 Mon Sep 17 00:00:00 2001 From: cijothomas Date: Fri, 5 Jun 2026 13:51:27 -0700 Subject: [PATCH 04/24] Rename otel.component.dropped_count to otel.component.dropped The '_count' suffix is redundant for an int attribute named 'dropped'. Aligns with @thompson-tomo review feedback on #3723. --- .chloggen/sdk-component-shutdown-event.yaml | 2 +- docs/otel/sdk-events.md | 10 +++++----- docs/registry/attributes/otel.md | 4 ++-- model/otel/events.yaml | 6 +++--- model/otel/registry.yaml | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.chloggen/sdk-component-shutdown-event.yaml b/.chloggen/sdk-component-shutdown-event.yaml index ac2a889562..006a84a59e 100644 --- a/.chloggen/sdk-component-shutdown-event.yaml +++ b/.chloggen/sdk-component-shutdown-event.yaml @@ -2,7 +2,7 @@ change_type: enhancement component: otel -note: Add `otel.sdk.component.shutdown` self-observability event and supporting attributes (`otel.component.shutdown.result`, `otel.component.dropped_count`). +note: Add `otel.sdk.component.shutdown` self-observability event and supporting attributes (`otel.component.shutdown.result`, `otel.component.dropped`). issues: [3718] diff --git a/docs/otel/sdk-events.md b/docs/otel/sdk-events.md index 854ee40ab0..f0209f67a9 100644 --- a/docs/otel/sdk-events.md +++ b/docs/otel/sdk-events.md @@ -49,10 +49,10 @@ The severity of the emitted log record SHOULD be `WARN` if **any** of the follow and `INFO` otherwise: - `otel.component.shutdown.result` is not `success`, or -- `otel.component.dropped_count` is **present** and greater than `0`. +- `otel.component.dropped` is **present** and greater than `0`. Components that do not track a lifetime dropped count MUST omit -`otel.component.dropped_count`. Absence of the attribute MUST NOT be treated as `0` +`otel.component.dropped`. Absence of the attribute MUST NOT be treated as `0` for the severity rule above; it means "not applicable / not tracked" and the severity is determined solely by `otel.component.shutdown.result` for those components. @@ -70,7 +70,7 @@ The event body is not used (per the [event guidelines](/docs/general/events.md)) | [`otel.component.name`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | A name uniquely identifying the instance of the OpenTelemetry component within its containing SDK instance. [1] | `otlp_grpc_span_exporter/0`; `custom-name` | | [`otel.component.shutdown.result`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | The result of an OpenTelemetry SDK component shutdown. | `success`; `failed`; `timed_out` | | [`otel.component.type`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | A name identifying the type of the OpenTelemetry component. [2] | `batching_span_processor`; `com.example.MySpanExporter` | -| [`otel.component.dropped_count`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Recommended` [3] | int | The total number of items the component dropped over its lifetime, up to and including the shutdown. [4] | `0`; `42` | +| [`otel.component.dropped`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Recommended` [3] | int | The total number of items the component dropped over its lifetime, up to and including the shutdown. [4] | `0`; `42` | **[1] `otel.component.name`:** Implementations SHOULD ensure a low cardinality for this attribute, even across application or SDK restarts. E.g. implementations MUST NOT use UUIDs as values for this attribute. @@ -89,9 +89,9 @@ These values will therefore be reused in the case of an application restart. **[2] `otel.component.type`:** If none of the standardized values apply, implementations SHOULD use the language-defined name of the type. E.g. for Java the fully qualified classname SHOULD be used in this case. -**[3] `otel.component.dropped_count`:** If the component tracks a lifetime dropped count (e.g. queue-based processors such as the Batching Span Processor or Batching Log Record Processor). Components that do not track this MUST omit the attribute; consumers MUST treat absence as "unknown", not as `0`. +**[3] `otel.component.dropped`:** If the component tracks a lifetime dropped count (e.g. queue-based processors such as the Batching Span Processor or Batching Log Record Processor). Components that do not track this MUST omit the attribute; consumers MUST treat absence as "unknown", not as `0`. -**[4] `otel.component.dropped_count`:** Counts items dropped for any reason, e.g. queue overflow or export failures that exhausted retries. +**[4] `otel.component.dropped`:** Counts items dropped for any reason, e.g. queue overflow or export failures that exhausted retries. The value is the cumulative count from the time the component was started until the moment the enclosing event (e.g. `otel.sdk.component.shutdown`) is emitted. diff --git a/docs/registry/attributes/otel.md b/docs/registry/attributes/otel.md index da90d71875..cef365f753 100644 --- a/docs/registry/attributes/otel.md +++ b/docs/registry/attributes/otel.md @@ -59,12 +59,12 @@ Attributes used for OpenTelemetry component self-monitoring | Key | Stability | Value Type | Description | Example Values | | --- | --- | --- | --- | --- | -| `otel.component.dropped_count` | ![Development](https://img.shields.io/badge/-development-blue) | int | The total number of telemetry items (spans, log records, metric data points, etc.) the OpenTelemetry SDK component dropped over its lifetime. [1] | `0`; `42` | +| `otel.component.dropped` | ![Development](https://img.shields.io/badge/-development-blue) | int | The total number of telemetry items (spans, log records, metric data points, etc.) the OpenTelemetry SDK component dropped over its lifetime. [1] | `0`; `42` | | `otel.component.name` | ![Development](https://img.shields.io/badge/-development-blue) | string | A name uniquely identifying the instance of the OpenTelemetry component within its containing SDK instance. [2] | `otlp_grpc_span_exporter/0`; `custom-name` | | `otel.component.shutdown.result` | ![Development](https://img.shields.io/badge/-development-blue) | string | The result of an OpenTelemetry SDK component shutdown. | `success`; `failed`; `timed_out` | | `otel.component.type` | ![Development](https://img.shields.io/badge/-development-blue) | string | A name identifying the type of the OpenTelemetry component. [3] | `batching_span_processor`; `com.example.MySpanExporter` | -**[1] `otel.component.dropped_count`:** Counts items dropped for any reason, e.g. queue overflow or export failures that exhausted retries. +**[1] `otel.component.dropped`:** Counts items dropped for any reason, e.g. queue overflow or export failures that exhausted retries. The value is the cumulative count from the time the component was started until the moment the enclosing event (e.g. `otel.sdk.component.shutdown`) is emitted. diff --git a/model/otel/events.yaml b/model/otel/events.yaml index 16e49ae71c..d5b08020c7 100644 --- a/model/otel/events.yaml +++ b/model/otel/events.yaml @@ -18,10 +18,10 @@ groups: and `INFO` otherwise: - `otel.component.shutdown.result` is not `success`, or - - `otel.component.dropped_count` is **present** and greater than `0`. + - `otel.component.dropped` is **present** and greater than `0`. Components that do not track a lifetime dropped count MUST omit - `otel.component.dropped_count`. Absence of the attribute MUST NOT be treated as `0` + `otel.component.dropped`. Absence of the attribute MUST NOT be treated as `0` for the severity rule above; it means "not applicable / not tracked" and the severity is determined solely by `otel.component.shutdown.result` for those components. @@ -38,7 +38,7 @@ groups: requirement_level: required - ref: otel.component.shutdown.result requirement_level: required - - ref: otel.component.dropped_count + - ref: otel.component.dropped requirement_level: recommended: > If the component tracks a lifetime dropped count (e.g. queue-based processors such as diff --git a/model/otel/registry.yaml b/model/otel/registry.yaml index f166305253..35d2538087 100644 --- a/model/otel/registry.yaml +++ b/model/otel/registry.yaml @@ -230,7 +230,7 @@ groups: brief: > The result of an OpenTelemetry SDK component shutdown. examples: ["success", "failed", "timed_out"] - - id: otel.component.dropped_count + - id: otel.component.dropped type: int stability: development brief: > From 0692ea13085eb5d65c29f44d3d73f30e53b3ebcf Mon Sep 17 00:00:00 2001 From: cijothomas Date: Fri, 5 Jun 2026 18:35:46 -0700 Subject: [PATCH 05/24] Add otel.component.shutdown.dropped to capture shutdown-time loss Steady-state queue overflow and retry-exhausted drops are already covered by the existing otel.sdk.processor.* metrics and now by otel.component.dropped. What was previously silent is the case where items were successfully buffered, but could not be drained before shutdown terminated (timeout or failure). Adds otel.component.shutdown.dropped as a new recommended int attribute on the shutdown event, and tightens otel.component.dropped to explicitly exclude shutdown-drain losses (clean boundary between the two counters). The severity rule is extended to WARN on shutdown.dropped > 0 as well. --- .chloggen/sdk-component-shutdown-event.yaml | 2 +- docs/otel/sdk-events.md | 31 +++++++++++++++++---- docs/registry/attributes/otel.md | 29 +++++++++++++++---- model/otel/events.yaml | 21 +++++++++++--- model/otel/registry.yaml | 26 +++++++++++++++-- 5 files changed, 91 insertions(+), 18 deletions(-) diff --git a/.chloggen/sdk-component-shutdown-event.yaml b/.chloggen/sdk-component-shutdown-event.yaml index 006a84a59e..110c7edf88 100644 --- a/.chloggen/sdk-component-shutdown-event.yaml +++ b/.chloggen/sdk-component-shutdown-event.yaml @@ -2,7 +2,7 @@ change_type: enhancement component: otel -note: Add `otel.sdk.component.shutdown` self-observability event and supporting attributes (`otel.component.shutdown.result`, `otel.component.dropped`). +note: Add `otel.sdk.component.shutdown` self-observability event and supporting attributes (`otel.component.shutdown.result`, `otel.component.dropped`, `otel.component.shutdown.dropped`). issues: [3718] diff --git a/docs/otel/sdk-events.md b/docs/otel/sdk-events.md index f0209f67a9..52591af9f4 100644 --- a/docs/otel/sdk-events.md +++ b/docs/otel/sdk-events.md @@ -49,12 +49,14 @@ The severity of the emitted log record SHOULD be `WARN` if **any** of the follow and `INFO` otherwise: - `otel.component.shutdown.result` is not `success`, or -- `otel.component.dropped` is **present** and greater than `0`. +- `otel.component.dropped` is **present** and greater than `0`, or +- `otel.component.shutdown.dropped` is **present** and greater than `0`. Components that do not track a lifetime dropped count MUST omit -`otel.component.dropped`. Absence of the attribute MUST NOT be treated as `0` +`otel.component.dropped`, and components that do not buffer items MUST omit +`otel.component.shutdown.dropped`. Absence of either attribute MUST NOT be treated as `0` for the severity rule above; it means "not applicable / not tracked" and the severity -is determined solely by `otel.component.shutdown.result` for those components. +is determined by the remaining present attributes. Implementations MUST take care that emitting this event does not itself depend on the component (or pipeline) that is being shut down. For example, the SDK SHOULD NOT route an @@ -70,7 +72,8 @@ The event body is not used (per the [event guidelines](/docs/general/events.md)) | [`otel.component.name`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | A name uniquely identifying the instance of the OpenTelemetry component within its containing SDK instance. [1] | `otlp_grpc_span_exporter/0`; `custom-name` | | [`otel.component.shutdown.result`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | The result of an OpenTelemetry SDK component shutdown. | `success`; `failed`; `timed_out` | | [`otel.component.type`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | A name identifying the type of the OpenTelemetry component. [2] | `batching_span_processor`; `com.example.MySpanExporter` | -| [`otel.component.dropped`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Recommended` [3] | int | The total number of items the component dropped over its lifetime, up to and including the shutdown. [4] | `0`; `42` | +| [`otel.component.dropped`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Recommended` [3] | int | The total number of items the component dropped during normal operation over its lifetime, excluding items lost during the shutdown act itself (see `otel.component.shutdown.dropped`). [4] | `0`; `42` | +| [`otel.component.shutdown.dropped`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Recommended` [5] | int | The number of items left in the component's buffer when shutdown terminated without fully draining (typically non-zero only when `otel.component.shutdown.result` is `failed` or `timed_out`). [6] | `0`; `800` | **[1] `otel.component.name`:** Implementations SHOULD ensure a low cardinality for this attribute, even across application or SDK restarts. E.g. implementations MUST NOT use UUIDs as values for this attribute. @@ -91,15 +94,33 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. **[3] `otel.component.dropped`:** If the component tracks a lifetime dropped count (e.g. queue-based processors such as the Batching Span Processor or Batching Log Record Processor). Components that do not track this MUST omit the attribute; consumers MUST treat absence as "unknown", not as `0`. -**[4] `otel.component.dropped`:** Counts items dropped for any reason, e.g. queue overflow or export failures that exhausted retries. +**[4] `otel.component.dropped`:** Counts items dropped during normal operation for any reason, e.g. queue overflow or export failures that exhausted retries. The value is the cumulative count from the time the component was started until the moment the enclosing event (e.g. `otel.sdk.component.shutdown`) is emitted. +Items that were buffered by the component when shutdown was initiated but could not be drained +before shutdown terminated are reported separately via `otel.component.shutdown.dropped` and +are NOT included in this lifetime counter. + This attribute is only applicable to components that track a lifetime dropped count, such as queue-based processors (e.g. the Batching Span Processor or Batching Log Record Processor). Components that do not track this MUST omit the attribute. Consumers MUST treat absence as "unknown / not applicable", not as `0`. +**[5] `otel.component.shutdown.dropped`:** If the component buffers items (e.g. queue-based processors such as the Batching Span Processor or Batching Log Record Processor). Non-buffering components MUST omit the attribute; consumers MUST treat absence as "unknown", not as `0`. + +**[6] `otel.component.shutdown.dropped`:** Reported on `otel.sdk.component.shutdown` events. Captures items lost specifically during +the shutdown act — i.e., items that had been accepted into the component's buffer prior to +shutdown but were still pending when the shutdown completed (typically because the +configured shutdown timeout elapsed, or the final export attempt failed). + +A value of `0` means the shutdown drained cleanly. Non-zero values typically correlate with +`otel.component.shutdown.result` being `failed` or `timed_out`. + +This attribute is only applicable to components that buffer items (e.g. the Batching Span +Processor or Batching Log Record Processor). Non-buffering components MUST omit the +attribute. Consumers MUST treat absence as "unknown / not applicable", not as `0`. + --- `otel.component.shutdown.result` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. diff --git a/docs/registry/attributes/otel.md b/docs/registry/attributes/otel.md index cef365f753..da77d5f5c7 100644 --- a/docs/registry/attributes/otel.md +++ b/docs/registry/attributes/otel.md @@ -59,15 +59,20 @@ Attributes used for OpenTelemetry component self-monitoring | Key | Stability | Value Type | Description | Example Values | | --- | --- | --- | --- | --- | -| `otel.component.dropped` | ![Development](https://img.shields.io/badge/-development-blue) | int | The total number of telemetry items (spans, log records, metric data points, etc.) the OpenTelemetry SDK component dropped over its lifetime. [1] | `0`; `42` | +| `otel.component.dropped` | ![Development](https://img.shields.io/badge/-development-blue) | int | The total number of telemetry items (spans, log records, metric data points, etc.) the OpenTelemetry SDK component dropped during normal operation over its lifetime. [1] | `0`; `42` | | `otel.component.name` | ![Development](https://img.shields.io/badge/-development-blue) | string | A name uniquely identifying the instance of the OpenTelemetry component within its containing SDK instance. [2] | `otlp_grpc_span_exporter/0`; `custom-name` | +| `otel.component.shutdown.dropped` | ![Development](https://img.shields.io/badge/-development-blue) | int | The number of telemetry items that were buffered by the component when shutdown was initiated but could not be drained before shutdown terminated. [3] | `0`; `800` | | `otel.component.shutdown.result` | ![Development](https://img.shields.io/badge/-development-blue) | string | The result of an OpenTelemetry SDK component shutdown. | `success`; `failed`; `timed_out` | -| `otel.component.type` | ![Development](https://img.shields.io/badge/-development-blue) | string | A name identifying the type of the OpenTelemetry component. [3] | `batching_span_processor`; `com.example.MySpanExporter` | +| `otel.component.type` | ![Development](https://img.shields.io/badge/-development-blue) | string | A name identifying the type of the OpenTelemetry component. [4] | `batching_span_processor`; `com.example.MySpanExporter` | -**[1] `otel.component.dropped`:** Counts items dropped for any reason, e.g. queue overflow or export failures that exhausted retries. +**[1] `otel.component.dropped`:** Counts items dropped during normal operation for any reason, e.g. queue overflow or export failures that exhausted retries. The value is the cumulative count from the time the component was started until the moment the enclosing event (e.g. `otel.sdk.component.shutdown`) is emitted. +Items that were buffered by the component when shutdown was initiated but could not be drained +before shutdown terminated are reported separately via `otel.component.shutdown.dropped` and +are NOT included in this lifetime counter. + This attribute is only applicable to components that track a lifetime dropped count, such as queue-based processors (e.g. the Batching Span Processor or Batching Log Record Processor). Components that do not track this MUST omit the attribute. Consumers MUST treat absence as @@ -87,7 +92,19 @@ With this implementation, for example the first Batching Span Processor would ha as `otel.component.name`, the second one `batching_span_processor/1` and so on. These values will therefore be reused in the case of an application restart. -**[3] `otel.component.type`:** If none of the standardized values apply, implementations SHOULD use the language-defined name of the type. +**[3] `otel.component.shutdown.dropped`:** Reported on `otel.sdk.component.shutdown` events. Captures items lost specifically during +the shutdown act — i.e., items that had been accepted into the component's buffer prior to +shutdown but were still pending when the shutdown completed (typically because the +configured shutdown timeout elapsed, or the final export attempt failed). + +A value of `0` means the shutdown drained cleanly. Non-zero values typically correlate with +`otel.component.shutdown.result` being `failed` or `timed_out`. + +This attribute is only applicable to components that buffer items (e.g. the Batching Span +Processor or Batching Log Record Processor). Non-buffering components MUST omit the +attribute. Consumers MUST treat absence as "unknown / not applicable", not as `0`. + +**[4] `otel.component.type`:** If none of the standardized values apply, implementations SHOULD use the language-defined name of the type. E.g. for Java the fully qualified classname SHOULD be used in this case. --- @@ -131,9 +148,9 @@ Attributes used by non-OTLP exporters to represent OpenTelemetry Event's concept | Key | Stability | Value Type | Description | Example Values | | --- | --- | --- | --- | --- | -| `otel.event.name` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | string | Identifies the class / type of event. [4] | `browser.mouse.click`; `device.app.lifecycle` | +| `otel.event.name` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | string | Identifies the class / type of event. [5] | `browser.mouse.click`; `device.app.lifecycle` | -**[4] `otel.event.name`:** This attribute SHOULD be used by non-OTLP exporters when destination does not support `EventName` or equivalent field. This attribute MAY be used by applications using existing logging libraries so that it can be used to set the `EventName` field by Collector or SDK components. +**[5] `otel.event.name`:** This attribute SHOULD be used by non-OTLP exporters when destination does not support `EventName` or equivalent field. This attribute MAY be used by applications using existing logging libraries so that it can be used to set the `EventName` field by Collector or SDK components. ## OTel Scope Attributes diff --git a/model/otel/events.yaml b/model/otel/events.yaml index d5b08020c7..e443968ee5 100644 --- a/model/otel/events.yaml +++ b/model/otel/events.yaml @@ -18,12 +18,14 @@ groups: and `INFO` otherwise: - `otel.component.shutdown.result` is not `success`, or - - `otel.component.dropped` is **present** and greater than `0`. + - `otel.component.dropped` is **present** and greater than `0`, or + - `otel.component.shutdown.dropped` is **present** and greater than `0`. Components that do not track a lifetime dropped count MUST omit - `otel.component.dropped`. Absence of the attribute MUST NOT be treated as `0` + `otel.component.dropped`, and components that do not buffer items MUST omit + `otel.component.shutdown.dropped`. Absence of either attribute MUST NOT be treated as `0` for the severity rule above; it means "not applicable / not tracked" and the severity - is determined solely by `otel.component.shutdown.result` for those components. + is determined by the remaining present attributes. Implementations MUST take care that emitting this event does not itself depend on the component (or pipeline) that is being shut down. For example, the SDK SHOULD NOT route an @@ -46,4 +48,15 @@ groups: track this MUST omit the attribute; consumers MUST treat absence as "unknown", not as `0`. brief: > - The total number of items the component dropped over its lifetime, up to and including the shutdown. + The total number of items the component dropped during normal operation over its lifetime, + excluding items lost during the shutdown act itself (see `otel.component.shutdown.dropped`). + - ref: otel.component.shutdown.dropped + requirement_level: + recommended: > + If the component buffers items (e.g. queue-based processors such as the Batching Span + Processor or Batching Log Record Processor). Non-buffering components MUST omit the + attribute; consumers MUST treat absence as "unknown", not as `0`. + brief: > + The number of items left in the component's buffer when shutdown terminated without + fully draining (typically non-zero only when `otel.component.shutdown.result` is + `failed` or `timed_out`). diff --git a/model/otel/registry.yaml b/model/otel/registry.yaml index 35d2538087..bb5b4df35f 100644 --- a/model/otel/registry.yaml +++ b/model/otel/registry.yaml @@ -234,14 +234,36 @@ groups: type: int stability: development brief: > - The total number of telemetry items (spans, log records, metric data points, etc.) the OpenTelemetry SDK component dropped over its lifetime. + The total number of telemetry items (spans, log records, metric data points, etc.) the OpenTelemetry SDK component dropped during normal operation over its lifetime. note: | - Counts items dropped for any reason, e.g. queue overflow or export failures that exhausted retries. + Counts items dropped during normal operation for any reason, e.g. queue overflow or export failures that exhausted retries. The value is the cumulative count from the time the component was started until the moment the enclosing event (e.g. `otel.sdk.component.shutdown`) is emitted. + Items that were buffered by the component when shutdown was initiated but could not be drained + before shutdown terminated are reported separately via `otel.component.shutdown.dropped` and + are NOT included in this lifetime counter. + This attribute is only applicable to components that track a lifetime dropped count, such as queue-based processors (e.g. the Batching Span Processor or Batching Log Record Processor). Components that do not track this MUST omit the attribute. Consumers MUST treat absence as "unknown / not applicable", not as `0`. examples: [0, 42] + - id: otel.component.shutdown.dropped + type: int + stability: development + brief: > + The number of telemetry items that were buffered by the component when shutdown was initiated but could not be drained before shutdown terminated. + note: | + Reported on `otel.sdk.component.shutdown` events. Captures items lost specifically during + the shutdown act — i.e., items that had been accepted into the component's buffer prior to + shutdown but were still pending when the shutdown completed (typically because the + configured shutdown timeout elapsed, or the final export attempt failed). + + A value of `0` means the shutdown drained cleanly. Non-zero values typically correlate with + `otel.component.shutdown.result` being `failed` or `timed_out`. + + This attribute is only applicable to components that buffer items (e.g. the Batching Span + Processor or Batching Log Record Processor). Non-buffering components MUST omit the + attribute. Consumers MUST treat absence as "unknown / not applicable", not as `0`. + examples: [0, 800] From 82f4fa57d4870fe01f5cddf0ea590317130a5c41 Mon Sep 17 00:00:00 2001 From: cijothomas Date: Fri, 5 Jun 2026 19:56:24 -0700 Subject: [PATCH 06/24] Tighten otel.component.shutdown.dropped semantics Two clarifications to prevent implementation drift: 1. Invariant: shutdown.dropped MUST be 0 when shutdown.result is success. A successful shutdown by definition drained everything; any non-zero value implies result in {failed, timed_out}. 2. Upper-bound semantics: the count is what the SDK could not CONFIRM delivered, not what was actually lost. In-flight export requests that the SDK abandoned at timeout may still succeed on the wire after the SDK gave up - those items are nevertheless counted because the SDK cannot confirm. Spelled out as a SHOULD list covering: items still buffered, items in abandoned in-flight requests, and items rejected by the final export attempt (e.g. OTLP partial-success rejections). --- docs/otel/sdk-events.md | 38 ++++++++++++++++++++++---------- docs/registry/attributes/otel.md | 38 ++++++++++++++++++++++---------- model/otel/events.yaml | 7 +++--- model/otel/registry.yaml | 34 +++++++++++++++++++--------- 4 files changed, 80 insertions(+), 37 deletions(-) diff --git a/docs/otel/sdk-events.md b/docs/otel/sdk-events.md index 52591af9f4..811be439d7 100644 --- a/docs/otel/sdk-events.md +++ b/docs/otel/sdk-events.md @@ -73,7 +73,7 @@ The event body is not used (per the [event guidelines](/docs/general/events.md)) | [`otel.component.shutdown.result`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | The result of an OpenTelemetry SDK component shutdown. | `success`; `failed`; `timed_out` | | [`otel.component.type`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | A name identifying the type of the OpenTelemetry component. [2] | `batching_span_processor`; `com.example.MySpanExporter` | | [`otel.component.dropped`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Recommended` [3] | int | The total number of items the component dropped during normal operation over its lifetime, excluding items lost during the shutdown act itself (see `otel.component.shutdown.dropped`). [4] | `0`; `42` | -| [`otel.component.shutdown.dropped`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Recommended` [5] | int | The number of items left in the component's buffer when shutdown terminated without fully draining (typically non-zero only when `otel.component.shutdown.result` is `failed` or `timed_out`). [6] | `0`; `800` | +| [`otel.component.shutdown.dropped`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Recommended` [5] | int | The number of items the component could not confirm delivered before shutdown terminated. MUST be `0` when `otel.component.shutdown.result` is `success`; non-zero values are an upper bound on actual loss (in-flight export requests abandoned at timeout may still succeed on the wire). [6] | `0`; `800` | **[1] `otel.component.name`:** Implementations SHOULD ensure a low cardinality for this attribute, even across application or SDK restarts. E.g. implementations MUST NOT use UUIDs as values for this attribute. @@ -109,17 +109,31 @@ Components that do not track this MUST omit the attribute. Consumers MUST treat **[5] `otel.component.shutdown.dropped`:** If the component buffers items (e.g. queue-based processors such as the Batching Span Processor or Batching Log Record Processor). Non-buffering components MUST omit the attribute; consumers MUST treat absence as "unknown", not as `0`. -**[6] `otel.component.shutdown.dropped`:** Reported on `otel.sdk.component.shutdown` events. Captures items lost specifically during -the shutdown act — i.e., items that had been accepted into the component's buffer prior to -shutdown but were still pending when the shutdown completed (typically because the -configured shutdown timeout elapsed, or the final export attempt failed). - -A value of `0` means the shutdown drained cleanly. Non-zero values typically correlate with -`otel.component.shutdown.result` being `failed` or `timed_out`. - -This attribute is only applicable to components that buffer items (e.g. the Batching Span -Processor or Batching Log Record Processor). Non-buffering components MUST omit the -attribute. Consumers MUST treat absence as "unknown / not applicable", not as `0`. +**[6] `otel.component.shutdown.dropped`:** Reported on `otel.sdk.component.shutdown` events. Captures items that the component +had accepted prior to shutdown but could not confirm delivered by the time the +shutdown attempt was abandoned (typically because the configured shutdown timeout +elapsed, or the final export attempt failed). + +When `otel.component.shutdown.result` is `success`, this attribute MUST be `0`: a +successful shutdown means the drain completed and nothing was left unconfirmed. +Non-zero values therefore only occur when `otel.component.shutdown.result` is +`failed` or `timed_out`. + +The reported value is an **upper bound** on actual data loss, not a precise count. +The SDK counts items it could not confirm delivered at the moment the shutdown +attempt was abandoned. In particular, in-flight export requests that the SDK had to +abandon (e.g. at timeout) MAY still complete successfully on the wire after the SDK +gave up; their items are nevertheless counted here because the SDK cannot confirm +delivery. Implementations SHOULD count: + +- items still in the component's buffer that were never handed to an exporter, +- items handed to an exporter in a request that the SDK abandoned without a + confirmed response, and +- items rejected by the final export attempt (e.g. OTLP partial-success rejections). + +This attribute is only applicable to components that buffer items (e.g. the Batching +Span Processor or Batching Log Record Processor). Non-buffering components MUST omit +the attribute. Consumers MUST treat absence as "unknown / not applicable", not as `0`. --- diff --git a/docs/registry/attributes/otel.md b/docs/registry/attributes/otel.md index da77d5f5c7..80d54b41a0 100644 --- a/docs/registry/attributes/otel.md +++ b/docs/registry/attributes/otel.md @@ -61,7 +61,7 @@ Attributes used for OpenTelemetry component self-monitoring | --- | --- | --- | --- | --- | | `otel.component.dropped` | ![Development](https://img.shields.io/badge/-development-blue) | int | The total number of telemetry items (spans, log records, metric data points, etc.) the OpenTelemetry SDK component dropped during normal operation over its lifetime. [1] | `0`; `42` | | `otel.component.name` | ![Development](https://img.shields.io/badge/-development-blue) | string | A name uniquely identifying the instance of the OpenTelemetry component within its containing SDK instance. [2] | `otlp_grpc_span_exporter/0`; `custom-name` | -| `otel.component.shutdown.dropped` | ![Development](https://img.shields.io/badge/-development-blue) | int | The number of telemetry items that were buffered by the component when shutdown was initiated but could not be drained before shutdown terminated. [3] | `0`; `800` | +| `otel.component.shutdown.dropped` | ![Development](https://img.shields.io/badge/-development-blue) | int | The number of telemetry items that were buffered by the component when shutdown was initiated but could not be confirmed delivered before shutdown terminated. [3] | `0`; `800` | | `otel.component.shutdown.result` | ![Development](https://img.shields.io/badge/-development-blue) | string | The result of an OpenTelemetry SDK component shutdown. | `success`; `failed`; `timed_out` | | `otel.component.type` | ![Development](https://img.shields.io/badge/-development-blue) | string | A name identifying the type of the OpenTelemetry component. [4] | `batching_span_processor`; `com.example.MySpanExporter` | @@ -92,17 +92,31 @@ With this implementation, for example the first Batching Span Processor would ha as `otel.component.name`, the second one `batching_span_processor/1` and so on. These values will therefore be reused in the case of an application restart. -**[3] `otel.component.shutdown.dropped`:** Reported on `otel.sdk.component.shutdown` events. Captures items lost specifically during -the shutdown act — i.e., items that had been accepted into the component's buffer prior to -shutdown but were still pending when the shutdown completed (typically because the -configured shutdown timeout elapsed, or the final export attempt failed). - -A value of `0` means the shutdown drained cleanly. Non-zero values typically correlate with -`otel.component.shutdown.result` being `failed` or `timed_out`. - -This attribute is only applicable to components that buffer items (e.g. the Batching Span -Processor or Batching Log Record Processor). Non-buffering components MUST omit the -attribute. Consumers MUST treat absence as "unknown / not applicable", not as `0`. +**[3] `otel.component.shutdown.dropped`:** Reported on `otel.sdk.component.shutdown` events. Captures items that the component +had accepted prior to shutdown but could not confirm delivered by the time the +shutdown attempt was abandoned (typically because the configured shutdown timeout +elapsed, or the final export attempt failed). + +When `otel.component.shutdown.result` is `success`, this attribute MUST be `0`: a +successful shutdown means the drain completed and nothing was left unconfirmed. +Non-zero values therefore only occur when `otel.component.shutdown.result` is +`failed` or `timed_out`. + +The reported value is an **upper bound** on actual data loss, not a precise count. +The SDK counts items it could not confirm delivered at the moment the shutdown +attempt was abandoned. In particular, in-flight export requests that the SDK had to +abandon (e.g. at timeout) MAY still complete successfully on the wire after the SDK +gave up; their items are nevertheless counted here because the SDK cannot confirm +delivery. Implementations SHOULD count: + +- items still in the component's buffer that were never handed to an exporter, +- items handed to an exporter in a request that the SDK abandoned without a + confirmed response, and +- items rejected by the final export attempt (e.g. OTLP partial-success rejections). + +This attribute is only applicable to components that buffer items (e.g. the Batching +Span Processor or Batching Log Record Processor). Non-buffering components MUST omit +the attribute. Consumers MUST treat absence as "unknown / not applicable", not as `0`. **[4] `otel.component.type`:** If none of the standardized values apply, implementations SHOULD use the language-defined name of the type. E.g. for Java the fully qualified classname SHOULD be used in this case. diff --git a/model/otel/events.yaml b/model/otel/events.yaml index e443968ee5..2286d3e986 100644 --- a/model/otel/events.yaml +++ b/model/otel/events.yaml @@ -57,6 +57,7 @@ groups: Processor or Batching Log Record Processor). Non-buffering components MUST omit the attribute; consumers MUST treat absence as "unknown", not as `0`. brief: > - The number of items left in the component's buffer when shutdown terminated without - fully draining (typically non-zero only when `otel.component.shutdown.result` is - `failed` or `timed_out`). + The number of items the component could not confirm delivered before shutdown terminated. + MUST be `0` when `otel.component.shutdown.result` is `success`; non-zero values are an + upper bound on actual loss (in-flight export requests abandoned at timeout may still + succeed on the wire). diff --git a/model/otel/registry.yaml b/model/otel/registry.yaml index bb5b4df35f..b4f5d1ad3c 100644 --- a/model/otel/registry.yaml +++ b/model/otel/registry.yaml @@ -253,17 +253,31 @@ groups: type: int stability: development brief: > - The number of telemetry items that were buffered by the component when shutdown was initiated but could not be drained before shutdown terminated. + The number of telemetry items that were buffered by the component when shutdown was initiated but could not be confirmed delivered before shutdown terminated. note: | - Reported on `otel.sdk.component.shutdown` events. Captures items lost specifically during - the shutdown act — i.e., items that had been accepted into the component's buffer prior to - shutdown but were still pending when the shutdown completed (typically because the - configured shutdown timeout elapsed, or the final export attempt failed). + Reported on `otel.sdk.component.shutdown` events. Captures items that the component + had accepted prior to shutdown but could not confirm delivered by the time the + shutdown attempt was abandoned (typically because the configured shutdown timeout + elapsed, or the final export attempt failed). - A value of `0` means the shutdown drained cleanly. Non-zero values typically correlate with - `otel.component.shutdown.result` being `failed` or `timed_out`. + When `otel.component.shutdown.result` is `success`, this attribute MUST be `0`: a + successful shutdown means the drain completed and nothing was left unconfirmed. + Non-zero values therefore only occur when `otel.component.shutdown.result` is + `failed` or `timed_out`. - This attribute is only applicable to components that buffer items (e.g. the Batching Span - Processor or Batching Log Record Processor). Non-buffering components MUST omit the - attribute. Consumers MUST treat absence as "unknown / not applicable", not as `0`. + The reported value is an **upper bound** on actual data loss, not a precise count. + The SDK counts items it could not confirm delivered at the moment the shutdown + attempt was abandoned. In particular, in-flight export requests that the SDK had to + abandon (e.g. at timeout) MAY still complete successfully on the wire after the SDK + gave up; their items are nevertheless counted here because the SDK cannot confirm + delivery. Implementations SHOULD count: + + - items still in the component's buffer that were never handed to an exporter, + - items handed to an exporter in a request that the SDK abandoned without a + confirmed response, and + - items rejected by the final export attempt (e.g. OTLP partial-success rejections). + + This attribute is only applicable to components that buffer items (e.g. the Batching + Span Processor or Batching Log Record Processor). Non-buffering components MUST omit + the attribute. Consumers MUST treat absence as "unknown / not applicable", not as `0`. examples: [0, 800] From 3f41f0c61398b94dc6378dda808a5c57023d39d0 Mon Sep 17 00:00:00 2001 From: cijothomas Date: Sat, 6 Jun 2026 11:02:43 -0700 Subject: [PATCH 07/24] Tighten shutdown event spec for first-of-its-kind clarity --- docs/otel/sdk-events.md | 232 +++++++++++++++++++++---------- docs/registry/attributes/otel.md | 118 ++++++++++------ model/otel/events.yaml | 136 +++++++++++++----- model/otel/registry.yaml | 100 ++++++++----- 4 files changed, 401 insertions(+), 185 deletions(-) diff --git a/docs/otel/sdk-events.md b/docs/otel/sdk-events.md index 811be439d7..96c073785f 100644 --- a/docs/otel/sdk-events.md +++ b/docs/otel/sdk-events.md @@ -35,45 +35,109 @@ that metrics cannot easily answer on their own, such as The event name MUST be `otel.sdk.component.shutdown`. -Indicates that an OpenTelemetry SDK component (e.g. a span processor or exporter) has finished shutting down. +Indicates that an OpenTelemetry SDK component's shutdown attempt has ended, whether by completing successfully, failing, or being abandoned (e.g. on timeout). -The OpenTelemetry SDK SHOULD emit an `otel.sdk.component.shutdown` event from each long-lived -SDK component (e.g. the Batching Span Processor) when its `Shutdown` operation has completed, -either successfully, with errors, or after a timeout. +**Applicability.** -The event is intended for SDK self-observability and answers the question -"did my pipeline drain cleanly when the application was shutting down?". -It is emitted exactly once per component instance per shutdown. +SDK implementations SHOULD emit an `otel.sdk.component.shutdown` event for each +SDK component instance that has an explicit shutdown (or equivalent close/dispose) +operation and that owns telemetry processing, buffering, reading, or exporting state. +This includes, when applicable, span processors, log record processors, metric +readers, and exporters. Passive helpers such as samplers, ID generators, propagators, +and resource detectors are out of scope. -The severity of the emitted log record SHOULD be `WARN` if **any** of the following hold, -and `INFO` otherwise: +Provider-level shutdown (e.g. `TracerProvider`, `LoggerProvider`, `MeterProvider`) +is reported via the events emitted by the provider's child components, not by the +provider itself, unless the provider has shutdown work whose outcome is not +represented by any child component event. -- `otel.component.shutdown.result` is not `success`, or -- `otel.component.dropped` is **present** and greater than `0`, or -- `otel.component.shutdown.dropped` is **present** and greater than `0`. +**Emission rules.** -Components that do not track a lifetime dropped count MUST omit -`otel.component.dropped`, and components that do not buffer items MUST omit -`otel.component.shutdown.dropped`. Absence of either attribute MUST NOT be treated as `0` -for the severity rule above; it means "not applicable / not tracked" and the severity -is determined by the remaining present attributes. +The event SHOULD be emitted exactly once per component instance per logical +shutdown transition, regardless of how many times the shutdown API is invoked. +Repeated idempotent shutdown calls that perform no additional shutdown work +MUST NOT emit additional events. + +If the process terminates without invoking the component's shutdown operation +(e.g. a crash, `SIGKILL`, container eviction, or immediate process termination), +no event is expected. Consumers MUST NOT interpret the absence of this event as +evidence of a clean shutdown. + +A single SDK pipeline MAY produce multiple `otel.sdk.component.shutdown` events, +one per component instance whose shutdown is reported. These events are +component-local: consumers SHOULD use `otel.component.name` and +`otel.component.type` to distinguish instances, and SHOULD NOT sum drop counts +across events to compute a pipeline-wide loss number (the same telemetry item +may be represented by more than one component's event). + +The event timestamp SHOULD reflect the time at which the shutdown attempt ended +(whether by completing, failing, or being abandoned). The event body SHOULD be +omitted; all event data defined by this convention is conveyed through attributes. -Implementations MUST take care that emitting this event does not itself depend on the -component (or pipeline) that is being shut down. For example, the SDK SHOULD NOT route an -`otel.sdk.component.shutdown` event for a log processor through the same `LoggerProvider` -that owns the processor being shut down. +**Severity.** -The event body is not used (per the [event guidelines](/docs/general/events.md)). +Implementations SHOULD set the log record severity to `WARN` +(`SeverityNumber` = `13`) if **any** of the following hold, and to `INFO` +(`SeverityNumber` = `9`) otherwise: + +- `otel.component.shutdown.result` is not `success`, +- `otel.component.shutdown.dropped` is **present** and greater than `0`, or +- `otel.component.dropped` is **present** and greater than `0`. + +A component MAY therefore emit an event with `otel.component.shutdown.result` = +`success` and `WARN` severity if it reports lifetime drops that occurred before +shutdown. This is intentional: the event is meant to be a single terminal place +to detect that the SDK lost telemetry, including drops that may have happened +earlier when the metrics pipeline was unavailable or unreliable. + +Components that do not track a lifetime dropped count MUST omit +`otel.component.dropped`, and components that do not own queued, buffered, retry, +or in-flight telemetry items at shutdown MUST omit `otel.component.shutdown.dropped`. +Absence of either attribute MUST NOT be treated as `0` for the severity rule +above; absence means "not applicable / not tracked", and the severity is +determined by the remaining present attributes. + +**Relationship with existing SDK metrics.** + +The drop counts on this event are component-local terminal summaries and are +**not additive** with SDK self-observability metrics such as +`otel.sdk.processor.*.processed` (with `error.type`) or +`otel.sdk.exporter.*.exported` (with `error.type`). The same telemetry item MAY +be represented both by an exporter failure metric data point and by a drop count +on this event. This event exists in addition to those metrics because the metrics +pipeline itself may be shutting down, and so the final state of the SDK is not +always observable from metrics alone. + +The reason a shutdown failed is intentionally not classified on this event +(there is no `error.type` attribute). Failure-cause classification is the +responsibility of the operation-level signals +(e.g. `otel.sdk.exporter.*.exported` with `error.type`) emitted while the SDK +is still healthy. + +**Self-feedback.** + +Implementations MUST NOT emit this event through the same component instance whose +shutdown is being reported. For log SDK components, implementations MUST NOT route +the event through the same `LoggerProvider`, `LogRecordProcessor`, or +`LogRecordExporter` instance that is currently being shut down. If no independent +self-observability emission path is available, implementations MAY suppress the +event rather than route it through the component or pipeline being shut down. + +**Forward compatibility.** + +Additional attributes (e.g. a shutdown duration) MAY be added in future revisions +of this convention. Consumers MUST tolerate the presence of attributes they do +not recognize. **Attributes:** | Key | Stability | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Value Type | Description | Example Values | | --- | --- | --- | --- | --- | --- | | [`otel.component.name`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | A name uniquely identifying the instance of the OpenTelemetry component within its containing SDK instance. [1] | `otlp_grpc_span_exporter/0`; `custom-name` | -| [`otel.component.shutdown.result`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | The result of an OpenTelemetry SDK component shutdown. | `success`; `failed`; `timed_out` | -| [`otel.component.type`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | A name identifying the type of the OpenTelemetry component. [2] | `batching_span_processor`; `com.example.MySpanExporter` | -| [`otel.component.dropped`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Recommended` [3] | int | The total number of items the component dropped during normal operation over its lifetime, excluding items lost during the shutdown act itself (see `otel.component.shutdown.dropped`). [4] | `0`; `42` | -| [`otel.component.shutdown.dropped`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Recommended` [5] | int | The number of items the component could not confirm delivered before shutdown terminated. MUST be `0` when `otel.component.shutdown.result` is `success`; non-zero values are an upper bound on actual loss (in-flight export requests abandoned at timeout may still succeed on the wire). [6] | `0`; `800` | +| [`otel.component.shutdown.result`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | The result of an OpenTelemetry SDK component shutdown attempt. [2] | `success`; `failed`; `timed_out` | +| [`otel.component.type`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | A name identifying the type of the OpenTelemetry component. [3] | `batching_span_processor`; `com.example.MySpanExporter` | +| [`otel.component.dropped`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Recommended` [4] | int | The total number of items the component dropped during normal operation over its lifetime, excluding items abandoned during the shutdown attempt itself (see `otel.component.shutdown.dropped`). [5] | `0`; `42` | +| [`otel.component.shutdown.dropped`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Recommended` [6] | int | The number of telemetry items the component could not confirm delivered before the shutdown attempt ended. MUST be `0` when `otel.component.shutdown.result` is `success`; non-zero values are an upper bound on actual loss (in-flight export requests abandoned at timeout may still succeed on the wire). [7] | `0`; `800` | **[1] `otel.component.name`:** Implementations SHOULD ensure a low cardinality for this attribute, even across application or SDK restarts. E.g. implementations MUST NOT use UUIDs as values for this attribute. @@ -89,51 +153,79 @@ With this implementation, for example the first Batching Span Processor would ha as `otel.component.name`, the second one `batching_span_processor/1` and so on. These values will therefore be reused in the case of an application restart. -**[2] `otel.component.type`:** If none of the standardized values apply, implementations SHOULD use the language-defined name of the type. -E.g. for Java the fully qualified classname SHOULD be used in this case. - -**[3] `otel.component.dropped`:** If the component tracks a lifetime dropped count (e.g. queue-based processors such as the Batching Span Processor or Batching Log Record Processor). Components that do not track this MUST omit the attribute; consumers MUST treat absence as "unknown", not as `0`. - -**[4] `otel.component.dropped`:** Counts items dropped during normal operation for any reason, e.g. queue overflow or export failures that exhausted retries. -The value is the cumulative count from the time the component was started until the moment the -enclosing event (e.g. `otel.sdk.component.shutdown`) is emitted. - -Items that were buffered by the component when shutdown was initiated but could not be drained -before shutdown terminated are reported separately via `otel.component.shutdown.dropped` and -are NOT included in this lifetime counter. +**[2] `otel.component.shutdown.result`:** `timed_out` takes precedence over `failed` when both are observed for the same +shutdown attempt (e.g. when an exporter request is abandoned because the +shutdown timeout expired). -This attribute is only applicable to components that track a lifetime dropped count, such as -queue-based processors (e.g. the Batching Span Processor or Batching Log Record Processor). -Components that do not track this MUST omit the attribute. Consumers MUST treat absence as -"unknown / not applicable", not as `0`. +`success` MUST only be reported when the shutdown completed within the +configured time budget AND no required shutdown step reported a failure. -**[5] `otel.component.shutdown.dropped`:** If the component buffers items (e.g. queue-based processors such as the Batching Span Processor or Batching Log Record Processor). Non-buffering components MUST omit the attribute; consumers MUST treat absence as "unknown", not as `0`. +If no shutdown timeout/deadline applies to the component, implementations MUST +NOT report `timed_out` unless the underlying shutdown API explicitly reports a +timeout condition. -**[6] `otel.component.shutdown.dropped`:** Reported on `otel.sdk.component.shutdown` events. Captures items that the component -had accepted prior to shutdown but could not confirm delivered by the time the -shutdown attempt was abandoned (typically because the configured shutdown timeout -elapsed, or the final export attempt failed). - -When `otel.component.shutdown.result` is `success`, this attribute MUST be `0`: a -successful shutdown means the drain completed and nothing was left unconfirmed. -Non-zero values therefore only occur when `otel.component.shutdown.result` is -`failed` or `timed_out`. - -The reported value is an **upper bound** on actual data loss, not a precise count. -The SDK counts items it could not confirm delivered at the moment the shutdown -attempt was abandoned. In particular, in-flight export requests that the SDK had to -abandon (e.g. at timeout) MAY still complete successfully on the wire after the SDK -gave up; their items are nevertheless counted here because the SDK cannot confirm -delivery. Implementations SHOULD count: - -- items still in the component's buffer that were never handed to an exporter, -- items handed to an exporter in a request that the SDK abandoned without a - confirmed response, and -- items rejected by the final export attempt (e.g. OTLP partial-success rejections). +**[3] `otel.component.type`:** If none of the standardized values apply, implementations SHOULD use the language-defined name of the type. +E.g. for Java the fully qualified classname SHOULD be used in this case. -This attribute is only applicable to components that buffer items (e.g. the Batching -Span Processor or Batching Log Record Processor). Non-buffering components MUST omit -the attribute. Consumers MUST treat absence as "unknown / not applicable", not as `0`. +**[4] `otel.component.dropped`:** If the component tracks a lifetime dropped count (e.g. queue-based processors such as the Batching Span Processor or Batching Log Record Processor). Components that do not track this MUST omit the attribute; consumers MUST treat absence as "unknown / not applicable", not as `0`. + +**[5] `otel.component.dropped`:** Counts telemetry items that the component accepted (or attempted to accept) +and then dropped during normal operation for any reason, e.g. queue overflow or +export failures that exhausted retries. The value MUST be a non-negative +integer and is cumulative from the time the component was started until the +moment the enclosing event (e.g. `otel.sdk.component.shutdown`) is emitted. + +This counter MUST NOT include: + +- items that the component refused because its shutdown had already begun or + completed (those situations are typically already exposed by other SDK + metrics, e.g. `otel.sdk.processor.*.processed` with `error.type`), or +- items reported via `otel.component.shutdown.dropped`. + +This attribute is only applicable to components that track a lifetime dropped +count, such as queue-based processors (e.g. the Batching Span Processor or +Batching Log Record Processor). Components that do not track this MUST omit +the attribute. Consumers MUST treat absence as "unknown / not applicable", +not as `0`. + +**[6] `otel.component.shutdown.dropped`:** If the component owns queued, buffered, retry, or in-flight telemetry items at the time shutdown is initiated (e.g. queue-based processors such as the Batching Span Processor, or an exporter with an in-flight export request). Components that do not own such items MUST omit the attribute; consumers MUST treat absence as "unknown / not applicable", not as `0`. + +**[7] `otel.component.shutdown.dropped`:** Reported on the `otel.sdk.component.shutdown` event. Captures telemetry items +that the component had accepted (queued, buffered, scheduled for retry, or +handed to a downstream component/exporter) prior to shutdown but could not +confirm delivered by the time the shutdown attempt ended (typically because +the configured shutdown timeout elapsed, or the final export attempt failed). +The value MUST be a non-negative integer. + +**Invariant.** When `otel.component.shutdown.result` is `success`, this +attribute MUST be `0` — a successful shutdown means the drain completed and +nothing was left unconfirmed. Non-zero values therefore only occur when +`otel.component.shutdown.result` is `failed` or `timed_out`. + +**Upper-bound semantics.** The reported value is an **upper bound** on actual +data loss, not a precise count. The SDK counts items it could not confirm +delivered at the moment the shutdown attempt ended. In particular, in-flight +export requests that the SDK had to abandon (e.g. at timeout) MAY still +complete successfully on the wire after the SDK gave up; their items are +nevertheless counted here because the SDK cannot confirm delivery. +Implementations SHOULD count, for the component instance reporting the event: + +- items still in the component's queue/buffer that were never handed to a + downstream component or exporter, +- items handed to a downstream component or exporter in an operation that the + SDK abandoned without a confirmed response, and +- items rejected by the final export/processing attempt (e.g. items reported + as rejected by an OTLP partial-success response). + +This attribute is applicable to any component that owns queued, buffered, +retry, or in-flight telemetry items at the time shutdown is initiated. This +includes both buffering components (e.g. the Batching Span Processor) and +non-buffering components with an in-flight export request at shutdown time +(e.g. an OTLP exporter). Components that do not own any such items at +shutdown MUST omit the attribute. Consumers MUST treat absence as +"unknown / not applicable", not as `0`, and SHOULD NOT sum this value across +components to compute a pipeline-wide loss number (the same telemetry item +may be counted by more than one component's event). --- @@ -141,9 +233,9 @@ the attribute. Consumers MUST treat absence as "unknown / not applicable", not a | Value | Description | Stability | | --- | --- | --- | -| `failed` | The component shut down with one or more failures other than a timeout (e.g. an exporter rejected the final batch). | ![Development](https://img.shields.io/badge/-development-blue) | -| `success` | The component shut down cleanly and drained any pending work. | ![Development](https://img.shields.io/badge/-development-blue) | -| `timed_out` | The component did not finish shutting down within the configured shutdown timeout. | ![Development](https://img.shields.io/badge/-development-blue) | +| `failed` | The shutdown attempt ended within the configured time budget but one or more required shutdown steps failed (e.g. an exporter rejected the final batch, or a cleanup step threw). | ![Development](https://img.shields.io/badge/-development-blue) | +| `success` | The shutdown attempt completed within the configured time budget and confirmed processing/delivery of all telemetry the component owned at the time shutdown was initiated. | ![Development](https://img.shields.io/badge/-development-blue) | +| `timed_out` | The shutdown attempt was abandoned because the configured shutdown timeout, deadline, or equivalent time budget expired. | ![Development](https://img.shields.io/badge/-development-blue) | --- diff --git a/docs/registry/attributes/otel.md b/docs/registry/attributes/otel.md index 80d54b41a0..09b04e0781 100644 --- a/docs/registry/attributes/otel.md +++ b/docs/registry/attributes/otel.md @@ -61,22 +61,28 @@ Attributes used for OpenTelemetry component self-monitoring | --- | --- | --- | --- | --- | | `otel.component.dropped` | ![Development](https://img.shields.io/badge/-development-blue) | int | The total number of telemetry items (spans, log records, metric data points, etc.) the OpenTelemetry SDK component dropped during normal operation over its lifetime. [1] | `0`; `42` | | `otel.component.name` | ![Development](https://img.shields.io/badge/-development-blue) | string | A name uniquely identifying the instance of the OpenTelemetry component within its containing SDK instance. [2] | `otlp_grpc_span_exporter/0`; `custom-name` | -| `otel.component.shutdown.dropped` | ![Development](https://img.shields.io/badge/-development-blue) | int | The number of telemetry items that were buffered by the component when shutdown was initiated but could not be confirmed delivered before shutdown terminated. [3] | `0`; `800` | -| `otel.component.shutdown.result` | ![Development](https://img.shields.io/badge/-development-blue) | string | The result of an OpenTelemetry SDK component shutdown. | `success`; `failed`; `timed_out` | -| `otel.component.type` | ![Development](https://img.shields.io/badge/-development-blue) | string | A name identifying the type of the OpenTelemetry component. [4] | `batching_span_processor`; `com.example.MySpanExporter` | +| `otel.component.shutdown.dropped` | ![Development](https://img.shields.io/badge/-development-blue) | int | The number of telemetry items that the component had taken responsibility for before shutdown was initiated but could not confirm delivered before the shutdown attempt ended. [3] | `0`; `800` | +| `otel.component.shutdown.result` | ![Development](https://img.shields.io/badge/-development-blue) | string | The result of an OpenTelemetry SDK component shutdown attempt. [4] | `success`; `failed`; `timed_out` | +| `otel.component.type` | ![Development](https://img.shields.io/badge/-development-blue) | string | A name identifying the type of the OpenTelemetry component. [5] | `batching_span_processor`; `com.example.MySpanExporter` | -**[1] `otel.component.dropped`:** Counts items dropped during normal operation for any reason, e.g. queue overflow or export failures that exhausted retries. -The value is the cumulative count from the time the component was started until the moment the -enclosing event (e.g. `otel.sdk.component.shutdown`) is emitted. +**[1] `otel.component.dropped`:** Counts telemetry items that the component accepted (or attempted to accept) +and then dropped during normal operation for any reason, e.g. queue overflow or +export failures that exhausted retries. The value MUST be a non-negative +integer and is cumulative from the time the component was started until the +moment the enclosing event (e.g. `otel.sdk.component.shutdown`) is emitted. -Items that were buffered by the component when shutdown was initiated but could not be drained -before shutdown terminated are reported separately via `otel.component.shutdown.dropped` and -are NOT included in this lifetime counter. +This counter MUST NOT include: -This attribute is only applicable to components that track a lifetime dropped count, such as -queue-based processors (e.g. the Batching Span Processor or Batching Log Record Processor). -Components that do not track this MUST omit the attribute. Consumers MUST treat absence as -"unknown / not applicable", not as `0`. +- items that the component refused because its shutdown had already begun or + completed (those situations are typically already exposed by other SDK + metrics, e.g. `otel.sdk.processor.*.processed` with `error.type`), or +- items reported via `otel.component.shutdown.dropped`. + +This attribute is only applicable to components that track a lifetime dropped +count, such as queue-based processors (e.g. the Batching Span Processor or +Batching Log Record Processor). Components that do not track this MUST omit +the attribute. Consumers MUST treat absence as "unknown / not applicable", +not as `0`. **[2] `otel.component.name`:** Implementations SHOULD ensure a low cardinality for this attribute, even across application or SDK restarts. E.g. implementations MUST NOT use UUIDs as values for this attribute. @@ -92,33 +98,55 @@ With this implementation, for example the first Batching Span Processor would ha as `otel.component.name`, the second one `batching_span_processor/1` and so on. These values will therefore be reused in the case of an application restart. -**[3] `otel.component.shutdown.dropped`:** Reported on `otel.sdk.component.shutdown` events. Captures items that the component -had accepted prior to shutdown but could not confirm delivered by the time the -shutdown attempt was abandoned (typically because the configured shutdown timeout -elapsed, or the final export attempt failed). - -When `otel.component.shutdown.result` is `success`, this attribute MUST be `0`: a -successful shutdown means the drain completed and nothing was left unconfirmed. -Non-zero values therefore only occur when `otel.component.shutdown.result` is -`failed` or `timed_out`. - -The reported value is an **upper bound** on actual data loss, not a precise count. -The SDK counts items it could not confirm delivered at the moment the shutdown -attempt was abandoned. In particular, in-flight export requests that the SDK had to -abandon (e.g. at timeout) MAY still complete successfully on the wire after the SDK -gave up; their items are nevertheless counted here because the SDK cannot confirm -delivery. Implementations SHOULD count: - -- items still in the component's buffer that were never handed to an exporter, -- items handed to an exporter in a request that the SDK abandoned without a - confirmed response, and -- items rejected by the final export attempt (e.g. OTLP partial-success rejections). - -This attribute is only applicable to components that buffer items (e.g. the Batching -Span Processor or Batching Log Record Processor). Non-buffering components MUST omit -the attribute. Consumers MUST treat absence as "unknown / not applicable", not as `0`. - -**[4] `otel.component.type`:** If none of the standardized values apply, implementations SHOULD use the language-defined name of the type. +**[3] `otel.component.shutdown.dropped`:** Reported on the `otel.sdk.component.shutdown` event. Captures telemetry items +that the component had accepted (queued, buffered, scheduled for retry, or +handed to a downstream component/exporter) prior to shutdown but could not +confirm delivered by the time the shutdown attempt ended (typically because +the configured shutdown timeout elapsed, or the final export attempt failed). +The value MUST be a non-negative integer. + +**Invariant.** When `otel.component.shutdown.result` is `success`, this +attribute MUST be `0` — a successful shutdown means the drain completed and +nothing was left unconfirmed. Non-zero values therefore only occur when +`otel.component.shutdown.result` is `failed` or `timed_out`. + +**Upper-bound semantics.** The reported value is an **upper bound** on actual +data loss, not a precise count. The SDK counts items it could not confirm +delivered at the moment the shutdown attempt ended. In particular, in-flight +export requests that the SDK had to abandon (e.g. at timeout) MAY still +complete successfully on the wire after the SDK gave up; their items are +nevertheless counted here because the SDK cannot confirm delivery. +Implementations SHOULD count, for the component instance reporting the event: + +- items still in the component's queue/buffer that were never handed to a + downstream component or exporter, +- items handed to a downstream component or exporter in an operation that the + SDK abandoned without a confirmed response, and +- items rejected by the final export/processing attempt (e.g. items reported + as rejected by an OTLP partial-success response). + +This attribute is applicable to any component that owns queued, buffered, +retry, or in-flight telemetry items at the time shutdown is initiated. This +includes both buffering components (e.g. the Batching Span Processor) and +non-buffering components with an in-flight export request at shutdown time +(e.g. an OTLP exporter). Components that do not own any such items at +shutdown MUST omit the attribute. Consumers MUST treat absence as +"unknown / not applicable", not as `0`, and SHOULD NOT sum this value across +components to compute a pipeline-wide loss number (the same telemetry item +may be counted by more than one component's event). + +**[4] `otel.component.shutdown.result`:** `timed_out` takes precedence over `failed` when both are observed for the same +shutdown attempt (e.g. when an exporter request is abandoned because the +shutdown timeout expired). + +`success` MUST only be reported when the shutdown completed within the +configured time budget AND no required shutdown step reported a failure. + +If no shutdown timeout/deadline applies to the component, implementations MUST +NOT report `timed_out` unless the underlying shutdown API explicitly reports a +timeout condition. + +**[5] `otel.component.type`:** If none of the standardized values apply, implementations SHOULD use the language-defined name of the type. E.g. for Java the fully qualified classname SHOULD be used in this case. --- @@ -127,9 +155,9 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. | Value | Description | Stability | | --- | --- | --- | -| `failed` | The component shut down with one or more failures other than a timeout (e.g. an exporter rejected the final batch). | ![Development](https://img.shields.io/badge/-development-blue) | -| `success` | The component shut down cleanly and drained any pending work. | ![Development](https://img.shields.io/badge/-development-blue) | -| `timed_out` | The component did not finish shutting down within the configured shutdown timeout. | ![Development](https://img.shields.io/badge/-development-blue) | +| `failed` | The shutdown attempt ended within the configured time budget but one or more required shutdown steps failed (e.g. an exporter rejected the final batch, or a cleanup step threw). | ![Development](https://img.shields.io/badge/-development-blue) | +| `success` | The shutdown attempt completed within the configured time budget and confirmed processing/delivery of all telemetry the component owned at the time shutdown was initiated. | ![Development](https://img.shields.io/badge/-development-blue) | +| `timed_out` | The shutdown attempt was abandoned because the configured shutdown timeout, deadline, or equivalent time budget expired. | ![Development](https://img.shields.io/badge/-development-blue) | --- @@ -162,9 +190,9 @@ Attributes used by non-OTLP exporters to represent OpenTelemetry Event's concept | Key | Stability | Value Type | Description | Example Values | | --- | --- | --- | --- | --- | -| `otel.event.name` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | string | Identifies the class / type of event. [5] | `browser.mouse.click`; `device.app.lifecycle` | +| `otel.event.name` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | string | Identifies the class / type of event. [6] | `browser.mouse.click`; `device.app.lifecycle` | -**[5] `otel.event.name`:** This attribute SHOULD be used by non-OTLP exporters when destination does not support `EventName` or equivalent field. This attribute MAY be used by applications using existing logging libraries so that it can be used to set the `EventName` field by Collector or SDK components. +**[6] `otel.event.name`:** This attribute SHOULD be used by non-OTLP exporters when destination does not support `EventName` or equivalent field. This attribute MAY be used by applications using existing logging libraries so that it can be used to set the `EventName` field by Collector or SDK components. ## OTel Scope Attributes diff --git a/model/otel/events.yaml b/model/otel/events.yaml index 2286d3e986..2a113c20e7 100644 --- a/model/otel/events.yaml +++ b/model/otel/events.yaml @@ -4,35 +4,100 @@ groups: name: otel.sdk.component.shutdown stability: development brief: > - Indicates that an OpenTelemetry SDK component (e.g. a span processor or exporter) has finished shutting down. + Indicates that an OpenTelemetry SDK component's shutdown attempt has ended, + whether by completing successfully, failing, or being abandoned (e.g. on timeout). note: | - The OpenTelemetry SDK SHOULD emit an `otel.sdk.component.shutdown` event from each long-lived - SDK component (e.g. the Batching Span Processor) when its `Shutdown` operation has completed, - either successfully, with errors, or after a timeout. + **Applicability.** - The event is intended for SDK self-observability and answers the question - "did my pipeline drain cleanly when the application was shutting down?". - It is emitted exactly once per component instance per shutdown. + SDK implementations SHOULD emit an `otel.sdk.component.shutdown` event for each + SDK component instance that has an explicit shutdown (or equivalent close/dispose) + operation and that owns telemetry processing, buffering, reading, or exporting state. + This includes, when applicable, span processors, log record processors, metric + readers, and exporters. Passive helpers such as samplers, ID generators, propagators, + and resource detectors are out of scope. - The severity of the emitted log record SHOULD be `WARN` if **any** of the following hold, - and `INFO` otherwise: + Provider-level shutdown (e.g. `TracerProvider`, `LoggerProvider`, `MeterProvider`) + is reported via the events emitted by the provider's child components, not by the + provider itself, unless the provider has shutdown work whose outcome is not + represented by any child component event. - - `otel.component.shutdown.result` is not `success`, or - - `otel.component.dropped` is **present** and greater than `0`, or - - `otel.component.shutdown.dropped` is **present** and greater than `0`. + **Emission rules.** + + The event SHOULD be emitted exactly once per component instance per logical + shutdown transition, regardless of how many times the shutdown API is invoked. + Repeated idempotent shutdown calls that perform no additional shutdown work + MUST NOT emit additional events. + + If the process terminates without invoking the component's shutdown operation + (e.g. a crash, `SIGKILL`, container eviction, or immediate process termination), + no event is expected. Consumers MUST NOT interpret the absence of this event as + evidence of a clean shutdown. + + A single SDK pipeline MAY produce multiple `otel.sdk.component.shutdown` events, + one per component instance whose shutdown is reported. These events are + component-local: consumers SHOULD use `otel.component.name` and + `otel.component.type` to distinguish instances, and SHOULD NOT sum drop counts + across events to compute a pipeline-wide loss number (the same telemetry item + may be represented by more than one component's event). + + The event timestamp SHOULD reflect the time at which the shutdown attempt ended + (whether by completing, failing, or being abandoned). The event body SHOULD be + omitted; all event data defined by this convention is conveyed through attributes. + + **Severity.** + + Implementations SHOULD set the log record severity to `WARN` + (`SeverityNumber` = `13`) if **any** of the following hold, and to `INFO` + (`SeverityNumber` = `9`) otherwise: + + - `otel.component.shutdown.result` is not `success`, + - `otel.component.shutdown.dropped` is **present** and greater than `0`, or + - `otel.component.dropped` is **present** and greater than `0`. + + A component MAY therefore emit an event with `otel.component.shutdown.result` = + `success` and `WARN` severity if it reports lifetime drops that occurred before + shutdown. This is intentional: the event is meant to be a single terminal place + to detect that the SDK lost telemetry, including drops that may have happened + earlier when the metrics pipeline was unavailable or unreliable. Components that do not track a lifetime dropped count MUST omit - `otel.component.dropped`, and components that do not buffer items MUST omit - `otel.component.shutdown.dropped`. Absence of either attribute MUST NOT be treated as `0` - for the severity rule above; it means "not applicable / not tracked" and the severity - is determined by the remaining present attributes. + `otel.component.dropped`, and components that do not own queued, buffered, retry, + or in-flight telemetry items at shutdown MUST omit `otel.component.shutdown.dropped`. + Absence of either attribute MUST NOT be treated as `0` for the severity rule + above; absence means "not applicable / not tracked", and the severity is + determined by the remaining present attributes. + + **Relationship with existing SDK metrics.** + + The drop counts on this event are component-local terminal summaries and are + **not additive** with SDK self-observability metrics such as + `otel.sdk.processor.*.processed` (with `error.type`) or + `otel.sdk.exporter.*.exported` (with `error.type`). The same telemetry item MAY + be represented both by an exporter failure metric data point and by a drop count + on this event. This event exists in addition to those metrics because the metrics + pipeline itself may be shutting down, and so the final state of the SDK is not + always observable from metrics alone. + + The reason a shutdown failed is intentionally not classified on this event + (there is no `error.type` attribute). Failure-cause classification is the + responsibility of the operation-level signals + (e.g. `otel.sdk.exporter.*.exported` with `error.type`) emitted while the SDK + is still healthy. + + **Self-feedback.** + + Implementations MUST NOT emit this event through the same component instance whose + shutdown is being reported. For log SDK components, implementations MUST NOT route + the event through the same `LoggerProvider`, `LogRecordProcessor`, or + `LogRecordExporter` instance that is currently being shut down. If no independent + self-observability emission path is available, implementations MAY suppress the + event rather than route it through the component or pipeline being shut down. - Implementations MUST take care that emitting this event does not itself depend on the - component (or pipeline) that is being shut down. For example, the SDK SHOULD NOT route an - `otel.sdk.component.shutdown` event for a log processor through the same `LoggerProvider` - that owns the processor being shut down. + **Forward compatibility.** - The event body is not used (per the [event guidelines](/docs/general/events.md)). + Additional attributes (e.g. a shutdown duration) MAY be added in future revisions + of this convention. Consumers MUST tolerate the presence of attributes they do + not recognize. attributes: - ref: otel.component.type requirement_level: required @@ -43,21 +108,24 @@ groups: - ref: otel.component.dropped requirement_level: recommended: > - If the component tracks a lifetime dropped count (e.g. queue-based processors such as - the Batching Span Processor or Batching Log Record Processor). Components that do not - track this MUST omit the attribute; consumers MUST treat absence as "unknown", - not as `0`. + If the component tracks a lifetime dropped count (e.g. queue-based + processors such as the Batching Span Processor or Batching Log Record + Processor). Components that do not track this MUST omit the attribute; + consumers MUST treat absence as "unknown / not applicable", not as `0`. brief: > - The total number of items the component dropped during normal operation over its lifetime, - excluding items lost during the shutdown act itself (see `otel.component.shutdown.dropped`). + The total number of items the component dropped during normal operation over + its lifetime, excluding items abandoned during the shutdown attempt itself + (see `otel.component.shutdown.dropped`). - ref: otel.component.shutdown.dropped requirement_level: recommended: > - If the component buffers items (e.g. queue-based processors such as the Batching Span - Processor or Batching Log Record Processor). Non-buffering components MUST omit the - attribute; consumers MUST treat absence as "unknown", not as `0`. + If the component owns queued, buffered, retry, or in-flight telemetry items + at the time shutdown is initiated (e.g. queue-based processors such as the + Batching Span Processor, or an exporter with an in-flight export request). + Components that do not own such items MUST omit the attribute; consumers + MUST treat absence as "unknown / not applicable", not as `0`. brief: > - The number of items the component could not confirm delivered before shutdown terminated. - MUST be `0` when `otel.component.shutdown.result` is `success`; non-zero values are an - upper bound on actual loss (in-flight export requests abandoned at timeout may still - succeed on the wire). + The number of telemetry items the component could not confirm delivered before + the shutdown attempt ended. MUST be `0` when `otel.component.shutdown.result` + is `success`; non-zero values are an upper bound on actual loss (in-flight + export requests abandoned at timeout may still succeed on the wire). diff --git a/model/otel/registry.yaml b/model/otel/registry.yaml index b4f5d1ad3c..921b9a299e 100644 --- a/model/otel/registry.yaml +++ b/model/otel/registry.yaml @@ -214,21 +214,32 @@ groups: - id: success value: "success" brief: > - The component shut down cleanly and drained any pending work. + The shutdown attempt completed within the configured time budget and confirmed processing/delivery of all telemetry the component owned at the time shutdown was initiated. stability: development - id: failed value: "failed" brief: > - The component shut down with one or more failures other than a timeout (e.g. an exporter rejected the final batch). + The shutdown attempt ended within the configured time budget but one or more required shutdown steps failed (e.g. an exporter rejected the final batch, or a cleanup step threw). stability: development - id: timed_out value: "timed_out" brief: > - The component did not finish shutting down within the configured shutdown timeout. + The shutdown attempt was abandoned because the configured shutdown timeout, deadline, or equivalent time budget expired. stability: development stability: development brief: > - The result of an OpenTelemetry SDK component shutdown. + The result of an OpenTelemetry SDK component shutdown attempt. + note: | + `timed_out` takes precedence over `failed` when both are observed for the same + shutdown attempt (e.g. when an exporter request is abandoned because the + shutdown timeout expired). + + `success` MUST only be reported when the shutdown completed within the + configured time budget AND no required shutdown step reported a failure. + + If no shutdown timeout/deadline applies to the component, implementations MUST + NOT report `timed_out` unless the underlying shutdown API explicitly reports a + timeout condition. examples: ["success", "failed", "timed_out"] - id: otel.component.dropped type: int @@ -236,48 +247,65 @@ groups: brief: > The total number of telemetry items (spans, log records, metric data points, etc.) the OpenTelemetry SDK component dropped during normal operation over its lifetime. note: | - Counts items dropped during normal operation for any reason, e.g. queue overflow or export failures that exhausted retries. - The value is the cumulative count from the time the component was started until the moment the - enclosing event (e.g. `otel.sdk.component.shutdown`) is emitted. + Counts telemetry items that the component accepted (or attempted to accept) + and then dropped during normal operation for any reason, e.g. queue overflow or + export failures that exhausted retries. The value MUST be a non-negative + integer and is cumulative from the time the component was started until the + moment the enclosing event (e.g. `otel.sdk.component.shutdown`) is emitted. + + This counter MUST NOT include: - Items that were buffered by the component when shutdown was initiated but could not be drained - before shutdown terminated are reported separately via `otel.component.shutdown.dropped` and - are NOT included in this lifetime counter. + - items that the component refused because its shutdown had already begun or + completed (those situations are typically already exposed by other SDK + metrics, e.g. `otel.sdk.processor.*.processed` with `error.type`), or + - items reported via `otel.component.shutdown.dropped`. - This attribute is only applicable to components that track a lifetime dropped count, such as - queue-based processors (e.g. the Batching Span Processor or Batching Log Record Processor). - Components that do not track this MUST omit the attribute. Consumers MUST treat absence as - "unknown / not applicable", not as `0`. + This attribute is only applicable to components that track a lifetime dropped + count, such as queue-based processors (e.g. the Batching Span Processor or + Batching Log Record Processor). Components that do not track this MUST omit + the attribute. Consumers MUST treat absence as "unknown / not applicable", + not as `0`. examples: [0, 42] - id: otel.component.shutdown.dropped type: int stability: development brief: > - The number of telemetry items that were buffered by the component when shutdown was initiated but could not be confirmed delivered before shutdown terminated. + The number of telemetry items that the component had taken responsibility for before shutdown was initiated but could not confirm delivered before the shutdown attempt ended. note: | - Reported on `otel.sdk.component.shutdown` events. Captures items that the component - had accepted prior to shutdown but could not confirm delivered by the time the - shutdown attempt was abandoned (typically because the configured shutdown timeout - elapsed, or the final export attempt failed). + Reported on the `otel.sdk.component.shutdown` event. Captures telemetry items + that the component had accepted (queued, buffered, scheduled for retry, or + handed to a downstream component/exporter) prior to shutdown but could not + confirm delivered by the time the shutdown attempt ended (typically because + the configured shutdown timeout elapsed, or the final export attempt failed). + The value MUST be a non-negative integer. - When `otel.component.shutdown.result` is `success`, this attribute MUST be `0`: a - successful shutdown means the drain completed and nothing was left unconfirmed. - Non-zero values therefore only occur when `otel.component.shutdown.result` is - `failed` or `timed_out`. + **Invariant.** When `otel.component.shutdown.result` is `success`, this + attribute MUST be `0` — a successful shutdown means the drain completed and + nothing was left unconfirmed. Non-zero values therefore only occur when + `otel.component.shutdown.result` is `failed` or `timed_out`. - The reported value is an **upper bound** on actual data loss, not a precise count. - The SDK counts items it could not confirm delivered at the moment the shutdown - attempt was abandoned. In particular, in-flight export requests that the SDK had to - abandon (e.g. at timeout) MAY still complete successfully on the wire after the SDK - gave up; their items are nevertheless counted here because the SDK cannot confirm - delivery. Implementations SHOULD count: + **Upper-bound semantics.** The reported value is an **upper bound** on actual + data loss, not a precise count. The SDK counts items it could not confirm + delivered at the moment the shutdown attempt ended. In particular, in-flight + export requests that the SDK had to abandon (e.g. at timeout) MAY still + complete successfully on the wire after the SDK gave up; their items are + nevertheless counted here because the SDK cannot confirm delivery. + Implementations SHOULD count, for the component instance reporting the event: - - items still in the component's buffer that were never handed to an exporter, - - items handed to an exporter in a request that the SDK abandoned without a - confirmed response, and - - items rejected by the final export attempt (e.g. OTLP partial-success rejections). + - items still in the component's queue/buffer that were never handed to a + downstream component or exporter, + - items handed to a downstream component or exporter in an operation that the + SDK abandoned without a confirmed response, and + - items rejected by the final export/processing attempt (e.g. items reported + as rejected by an OTLP partial-success response). - This attribute is only applicable to components that buffer items (e.g. the Batching - Span Processor or Batching Log Record Processor). Non-buffering components MUST omit - the attribute. Consumers MUST treat absence as "unknown / not applicable", not as `0`. + This attribute is applicable to any component that owns queued, buffered, + retry, or in-flight telemetry items at the time shutdown is initiated. This + includes both buffering components (e.g. the Batching Span Processor) and + non-buffering components with an in-flight export request at shutdown time + (e.g. an OTLP exporter). Components that do not own any such items at + shutdown MUST omit the attribute. Consumers MUST treat absence as + "unknown / not applicable", not as `0`, and SHOULD NOT sum this value across + components to compute a pipeline-wide loss number (the same telemetry item + may be counted by more than one component's event). examples: [0, 800] From ea20a61bb07f2eae5bf8e201f82116b9d6eeb059 Mon Sep 17 00:00:00 2001 From: cijothomas Date: Sun, 7 Jun 2026 09:32:57 -0700 Subject: [PATCH 08/24] Trim shutdown event count semantics for clarity --- docs/otel/sdk-events.md | 82 +++++++++++--------------------- docs/registry/attributes/otel.md | 57 ++++++++-------------- model/otel/events.yaml | 25 ++++------ model/otel/registry.yaml | 55 ++++++++------------- 4 files changed, 77 insertions(+), 142 deletions(-) diff --git a/docs/otel/sdk-events.md b/docs/otel/sdk-events.md index 96c073785f..4fc475f204 100644 --- a/docs/otel/sdk-events.md +++ b/docs/otel/sdk-events.md @@ -64,11 +64,8 @@ no event is expected. Consumers MUST NOT interpret the absence of this event as evidence of a clean shutdown. A single SDK pipeline MAY produce multiple `otel.sdk.component.shutdown` events, -one per component instance whose shutdown is reported. These events are -component-local: consumers SHOULD use `otel.component.name` and -`otel.component.type` to distinguish instances, and SHOULD NOT sum drop counts -across events to compute a pipeline-wide loss number (the same telemetry item -may be represented by more than one component's event). +one per component instance whose shutdown is reported. Consumers SHOULD use +`otel.component.name` and `otel.component.type` to distinguish instances. The event timestamp SHOULD reflect the time at which the shutdown attempt ended (whether by completing, failing, or being abandoned). The event body SHOULD be @@ -99,20 +96,16 @@ determined by the remaining present attributes. **Relationship with existing SDK metrics.** -The drop counts on this event are component-local terminal summaries and are -**not additive** with SDK self-observability metrics such as -`otel.sdk.processor.*.processed` (with `error.type`) or -`otel.sdk.exporter.*.exported` (with `error.type`). The same telemetry item MAY -be represented both by an exporter failure metric data point and by a drop count -on this event. This event exists in addition to those metrics because the metrics -pipeline itself may be shutting down, and so the final state of the SDK is not -always observable from metrics alone. +The drop counts on this event are a terminal summary emitted at shutdown, when +the metrics pipeline itself may no longer be reliable. These counts MAY overlap +with per-operation SDK metrics (e.g. `otel.sdk.processor.*.processed` or +`otel.sdk.exporter.*.exported`, both with `error.type`) and SHOULD NOT be +combined with those metrics to compute aggregate loss. The reason a shutdown failed is intentionally not classified on this event (there is no `error.type` attribute). Failure-cause classification is the -responsibility of the operation-level signals -(e.g. `otel.sdk.exporter.*.exported` with `error.type`) emitted while the SDK -is still healthy. +responsibility of the operation-level signals (e.g. `otel.sdk.exporter.*.exported` +with `error.type`) emitted while the SDK is still healthy. **Self-feedback.** @@ -170,17 +163,16 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. **[4] `otel.component.dropped`:** If the component tracks a lifetime dropped count (e.g. queue-based processors such as the Batching Span Processor or Batching Log Record Processor). Components that do not track this MUST omit the attribute; consumers MUST treat absence as "unknown / not applicable", not as `0`. **[5] `otel.component.dropped`:** Counts telemetry items that the component accepted (or attempted to accept) -and then dropped during normal operation for any reason, e.g. queue overflow or -export failures that exhausted retries. The value MUST be a non-negative +and then dropped during normal operation for any reason, e.g. queue overflow +or export failures that exhausted retries. The value MUST be a non-negative integer and is cumulative from the time the component was started until the moment the enclosing event (e.g. `otel.sdk.component.shutdown`) is emitted. -This counter MUST NOT include: - -- items that the component refused because its shutdown had already begun or - completed (those situations are typically already exposed by other SDK - metrics, e.g. `otel.sdk.processor.*.processed` with `error.type`), or -- items reported via `otel.component.shutdown.dropped`. +This counter does NOT include items reported via +`otel.component.shutdown.dropped`, and does NOT include items refused because +the component's shutdown had already begun (those are typically already +exposed by other SDK metrics, e.g. `otel.sdk.processor.*.processed` with +`error.type`). This attribute is only applicable to components that track a lifetime dropped count, such as queue-based processors (e.g. the Batching Span Processor or @@ -190,32 +182,18 @@ not as `0`. **[6] `otel.component.shutdown.dropped`:** If the component owns queued, buffered, retry, or in-flight telemetry items at the time shutdown is initiated (e.g. queue-based processors such as the Batching Span Processor, or an exporter with an in-flight export request). Components that do not own such items MUST omit the attribute; consumers MUST treat absence as "unknown / not applicable", not as `0`. -**[7] `otel.component.shutdown.dropped`:** Reported on the `otel.sdk.component.shutdown` event. Captures telemetry items -that the component had accepted (queued, buffered, scheduled for retry, or -handed to a downstream component/exporter) prior to shutdown but could not -confirm delivered by the time the shutdown attempt ended (typically because -the configured shutdown timeout elapsed, or the final export attempt failed). -The value MUST be a non-negative integer. - -**Invariant.** When `otel.component.shutdown.result` is `success`, this -attribute MUST be `0` — a successful shutdown means the drain completed and -nothing was left unconfirmed. Non-zero values therefore only occur when -`otel.component.shutdown.result` is `failed` or `timed_out`. - -**Upper-bound semantics.** The reported value is an **upper bound** on actual -data loss, not a precise count. The SDK counts items it could not confirm -delivered at the moment the shutdown attempt ended. In particular, in-flight -export requests that the SDK had to abandon (e.g. at timeout) MAY still -complete successfully on the wire after the SDK gave up; their items are -nevertheless counted here because the SDK cannot confirm delivery. -Implementations SHOULD count, for the component instance reporting the event: - -- items still in the component's queue/buffer that were never handed to a - downstream component or exporter, -- items handed to a downstream component or exporter in an operation that the - SDK abandoned without a confirmed response, and -- items rejected by the final export/processing attempt (e.g. items reported - as rejected by an OTLP partial-success response). +**[7] `otel.component.shutdown.dropped`:** Reported on the `otel.sdk.component.shutdown` event. Counts telemetry items +the component had accepted prior to shutdown (queued, buffered, scheduled for +retry, or handed to a downstream component/exporter in an operation that did +not return) and could not confirm delivered by the time the shutdown attempt +ended (typically because the configured shutdown timeout elapsed, or the +final export attempt failed). + +The value MUST be a non-negative integer. When `otel.component.shutdown.result` +is `success`, this attribute MUST be `0`. Non-zero values are an upper bound +on actual loss: in-flight export requests that the SDK abandoned (e.g. at +timeout) MAY still complete successfully on the wire after the SDK gave up, +but the SDK cannot confirm delivery so they are counted here. This attribute is applicable to any component that owns queued, buffered, retry, or in-flight telemetry items at the time shutdown is initiated. This @@ -223,9 +201,7 @@ includes both buffering components (e.g. the Batching Span Processor) and non-buffering components with an in-flight export request at shutdown time (e.g. an OTLP exporter). Components that do not own any such items at shutdown MUST omit the attribute. Consumers MUST treat absence as -"unknown / not applicable", not as `0`, and SHOULD NOT sum this value across -components to compute a pipeline-wide loss number (the same telemetry item -may be counted by more than one component's event). +"unknown / not applicable", not as `0`. --- diff --git a/docs/registry/attributes/otel.md b/docs/registry/attributes/otel.md index 09b04e0781..8bd83ef568 100644 --- a/docs/registry/attributes/otel.md +++ b/docs/registry/attributes/otel.md @@ -66,17 +66,16 @@ Attributes used for OpenTelemetry component self-monitoring | `otel.component.type` | ![Development](https://img.shields.io/badge/-development-blue) | string | A name identifying the type of the OpenTelemetry component. [5] | `batching_span_processor`; `com.example.MySpanExporter` | **[1] `otel.component.dropped`:** Counts telemetry items that the component accepted (or attempted to accept) -and then dropped during normal operation for any reason, e.g. queue overflow or -export failures that exhausted retries. The value MUST be a non-negative +and then dropped during normal operation for any reason, e.g. queue overflow +or export failures that exhausted retries. The value MUST be a non-negative integer and is cumulative from the time the component was started until the moment the enclosing event (e.g. `otel.sdk.component.shutdown`) is emitted. -This counter MUST NOT include: - -- items that the component refused because its shutdown had already begun or - completed (those situations are typically already exposed by other SDK - metrics, e.g. `otel.sdk.processor.*.processed` with `error.type`), or -- items reported via `otel.component.shutdown.dropped`. +This counter does NOT include items reported via +`otel.component.shutdown.dropped`, and does NOT include items refused because +the component's shutdown had already begun (those are typically already +exposed by other SDK metrics, e.g. `otel.sdk.processor.*.processed` with +`error.type`). This attribute is only applicable to components that track a lifetime dropped count, such as queue-based processors (e.g. the Batching Span Processor or @@ -98,32 +97,18 @@ With this implementation, for example the first Batching Span Processor would ha as `otel.component.name`, the second one `batching_span_processor/1` and so on. These values will therefore be reused in the case of an application restart. -**[3] `otel.component.shutdown.dropped`:** Reported on the `otel.sdk.component.shutdown` event. Captures telemetry items -that the component had accepted (queued, buffered, scheduled for retry, or -handed to a downstream component/exporter) prior to shutdown but could not -confirm delivered by the time the shutdown attempt ended (typically because -the configured shutdown timeout elapsed, or the final export attempt failed). -The value MUST be a non-negative integer. - -**Invariant.** When `otel.component.shutdown.result` is `success`, this -attribute MUST be `0` — a successful shutdown means the drain completed and -nothing was left unconfirmed. Non-zero values therefore only occur when -`otel.component.shutdown.result` is `failed` or `timed_out`. - -**Upper-bound semantics.** The reported value is an **upper bound** on actual -data loss, not a precise count. The SDK counts items it could not confirm -delivered at the moment the shutdown attempt ended. In particular, in-flight -export requests that the SDK had to abandon (e.g. at timeout) MAY still -complete successfully on the wire after the SDK gave up; their items are -nevertheless counted here because the SDK cannot confirm delivery. -Implementations SHOULD count, for the component instance reporting the event: - -- items still in the component's queue/buffer that were never handed to a - downstream component or exporter, -- items handed to a downstream component or exporter in an operation that the - SDK abandoned without a confirmed response, and -- items rejected by the final export/processing attempt (e.g. items reported - as rejected by an OTLP partial-success response). +**[3] `otel.component.shutdown.dropped`:** Reported on the `otel.sdk.component.shutdown` event. Counts telemetry items +the component had accepted prior to shutdown (queued, buffered, scheduled for +retry, or handed to a downstream component/exporter in an operation that did +not return) and could not confirm delivered by the time the shutdown attempt +ended (typically because the configured shutdown timeout elapsed, or the +final export attempt failed). + +The value MUST be a non-negative integer. When `otel.component.shutdown.result` +is `success`, this attribute MUST be `0`. Non-zero values are an upper bound +on actual loss: in-flight export requests that the SDK abandoned (e.g. at +timeout) MAY still complete successfully on the wire after the SDK gave up, +but the SDK cannot confirm delivery so they are counted here. This attribute is applicable to any component that owns queued, buffered, retry, or in-flight telemetry items at the time shutdown is initiated. This @@ -131,9 +116,7 @@ includes both buffering components (e.g. the Batching Span Processor) and non-buffering components with an in-flight export request at shutdown time (e.g. an OTLP exporter). Components that do not own any such items at shutdown MUST omit the attribute. Consumers MUST treat absence as -"unknown / not applicable", not as `0`, and SHOULD NOT sum this value across -components to compute a pipeline-wide loss number (the same telemetry item -may be counted by more than one component's event). +"unknown / not applicable", not as `0`. **[4] `otel.component.shutdown.result`:** `timed_out` takes precedence over `failed` when both are observed for the same shutdown attempt (e.g. when an exporter request is abandoned because the diff --git a/model/otel/events.yaml b/model/otel/events.yaml index 2a113c20e7..ab8f08273c 100644 --- a/model/otel/events.yaml +++ b/model/otel/events.yaml @@ -34,11 +34,8 @@ groups: evidence of a clean shutdown. A single SDK pipeline MAY produce multiple `otel.sdk.component.shutdown` events, - one per component instance whose shutdown is reported. These events are - component-local: consumers SHOULD use `otel.component.name` and - `otel.component.type` to distinguish instances, and SHOULD NOT sum drop counts - across events to compute a pipeline-wide loss number (the same telemetry item - may be represented by more than one component's event). + one per component instance whose shutdown is reported. Consumers SHOULD use + `otel.component.name` and `otel.component.type` to distinguish instances. The event timestamp SHOULD reflect the time at which the shutdown attempt ended (whether by completing, failing, or being abandoned). The event body SHOULD be @@ -69,20 +66,16 @@ groups: **Relationship with existing SDK metrics.** - The drop counts on this event are component-local terminal summaries and are - **not additive** with SDK self-observability metrics such as - `otel.sdk.processor.*.processed` (with `error.type`) or - `otel.sdk.exporter.*.exported` (with `error.type`). The same telemetry item MAY - be represented both by an exporter failure metric data point and by a drop count - on this event. This event exists in addition to those metrics because the metrics - pipeline itself may be shutting down, and so the final state of the SDK is not - always observable from metrics alone. + The drop counts on this event are a terminal summary emitted at shutdown, when + the metrics pipeline itself may no longer be reliable. These counts MAY overlap + with per-operation SDK metrics (e.g. `otel.sdk.processor.*.processed` or + `otel.sdk.exporter.*.exported`, both with `error.type`) and SHOULD NOT be + combined with those metrics to compute aggregate loss. The reason a shutdown failed is intentionally not classified on this event (there is no `error.type` attribute). Failure-cause classification is the - responsibility of the operation-level signals - (e.g. `otel.sdk.exporter.*.exported` with `error.type`) emitted while the SDK - is still healthy. + responsibility of the operation-level signals (e.g. `otel.sdk.exporter.*.exported` + with `error.type`) emitted while the SDK is still healthy. **Self-feedback.** diff --git a/model/otel/registry.yaml b/model/otel/registry.yaml index 921b9a299e..8e535c896c 100644 --- a/model/otel/registry.yaml +++ b/model/otel/registry.yaml @@ -248,17 +248,16 @@ groups: The total number of telemetry items (spans, log records, metric data points, etc.) the OpenTelemetry SDK component dropped during normal operation over its lifetime. note: | Counts telemetry items that the component accepted (or attempted to accept) - and then dropped during normal operation for any reason, e.g. queue overflow or - export failures that exhausted retries. The value MUST be a non-negative + and then dropped during normal operation for any reason, e.g. queue overflow + or export failures that exhausted retries. The value MUST be a non-negative integer and is cumulative from the time the component was started until the moment the enclosing event (e.g. `otel.sdk.component.shutdown`) is emitted. - This counter MUST NOT include: - - - items that the component refused because its shutdown had already begun or - completed (those situations are typically already exposed by other SDK - metrics, e.g. `otel.sdk.processor.*.processed` with `error.type`), or - - items reported via `otel.component.shutdown.dropped`. + This counter does NOT include items reported via + `otel.component.shutdown.dropped`, and does NOT include items refused because + the component's shutdown had already begun (those are typically already + exposed by other SDK metrics, e.g. `otel.sdk.processor.*.processed` with + `error.type`). This attribute is only applicable to components that track a lifetime dropped count, such as queue-based processors (e.g. the Batching Span Processor or @@ -272,32 +271,18 @@ groups: brief: > The number of telemetry items that the component had taken responsibility for before shutdown was initiated but could not confirm delivered before the shutdown attempt ended. note: | - Reported on the `otel.sdk.component.shutdown` event. Captures telemetry items - that the component had accepted (queued, buffered, scheduled for retry, or - handed to a downstream component/exporter) prior to shutdown but could not - confirm delivered by the time the shutdown attempt ended (typically because - the configured shutdown timeout elapsed, or the final export attempt failed). - The value MUST be a non-negative integer. - - **Invariant.** When `otel.component.shutdown.result` is `success`, this - attribute MUST be `0` — a successful shutdown means the drain completed and - nothing was left unconfirmed. Non-zero values therefore only occur when - `otel.component.shutdown.result` is `failed` or `timed_out`. - - **Upper-bound semantics.** The reported value is an **upper bound** on actual - data loss, not a precise count. The SDK counts items it could not confirm - delivered at the moment the shutdown attempt ended. In particular, in-flight - export requests that the SDK had to abandon (e.g. at timeout) MAY still - complete successfully on the wire after the SDK gave up; their items are - nevertheless counted here because the SDK cannot confirm delivery. - Implementations SHOULD count, for the component instance reporting the event: + Reported on the `otel.sdk.component.shutdown` event. Counts telemetry items + the component had accepted prior to shutdown (queued, buffered, scheduled for + retry, or handed to a downstream component/exporter in an operation that did + not return) and could not confirm delivered by the time the shutdown attempt + ended (typically because the configured shutdown timeout elapsed, or the + final export attempt failed). - - items still in the component's queue/buffer that were never handed to a - downstream component or exporter, - - items handed to a downstream component or exporter in an operation that the - SDK abandoned without a confirmed response, and - - items rejected by the final export/processing attempt (e.g. items reported - as rejected by an OTLP partial-success response). + The value MUST be a non-negative integer. When `otel.component.shutdown.result` + is `success`, this attribute MUST be `0`. Non-zero values are an upper bound + on actual loss: in-flight export requests that the SDK abandoned (e.g. at + timeout) MAY still complete successfully on the wire after the SDK gave up, + but the SDK cannot confirm delivery so they are counted here. This attribute is applicable to any component that owns queued, buffered, retry, or in-flight telemetry items at the time shutdown is initiated. This @@ -305,7 +290,5 @@ groups: non-buffering components with an in-flight export request at shutdown time (e.g. an OTLP exporter). Components that do not own any such items at shutdown MUST omit the attribute. Consumers MUST treat absence as - "unknown / not applicable", not as `0`, and SHOULD NOT sum this value across - components to compute a pipeline-wide loss number (the same telemetry item - may be counted by more than one component's event). + "unknown / not applicable", not as `0`. examples: [0, 800] From ad063f0d45decfcfa3b4f7c11dea9a442038dcd6 Mon Sep 17 00:00:00 2001 From: cijothomas Date: Sun, 7 Jun 2026 10:35:38 -0700 Subject: [PATCH 09/24] Use Shutdown only (drop close/dispose mention) --- docs/otel/sdk-events.md | 4 ++-- model/otel/events.yaml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/otel/sdk-events.md b/docs/otel/sdk-events.md index 4fc475f204..bce7415037 100644 --- a/docs/otel/sdk-events.md +++ b/docs/otel/sdk-events.md @@ -40,8 +40,8 @@ Indicates that an OpenTelemetry SDK component's shutdown attempt has ended, whet **Applicability.** SDK implementations SHOULD emit an `otel.sdk.component.shutdown` event for each -SDK component instance that has an explicit shutdown (or equivalent close/dispose) -operation and that owns telemetry processing, buffering, reading, or exporting state. +SDK component instance that has an explicit `Shutdown` operation and that owns +telemetry processing, buffering, reading, or exporting state. This includes, when applicable, span processors, log record processors, metric readers, and exporters. Passive helpers such as samplers, ID generators, propagators, and resource detectors are out of scope. diff --git a/model/otel/events.yaml b/model/otel/events.yaml index ab8f08273c..c10f306e4c 100644 --- a/model/otel/events.yaml +++ b/model/otel/events.yaml @@ -10,8 +10,8 @@ groups: **Applicability.** SDK implementations SHOULD emit an `otel.sdk.component.shutdown` event for each - SDK component instance that has an explicit shutdown (or equivalent close/dispose) - operation and that owns telemetry processing, buffering, reading, or exporting state. + SDK component instance that has an explicit `Shutdown` operation and that owns + telemetry processing, buffering, reading, or exporting state. This includes, when applicable, span processors, log record processors, metric readers, and exporters. Passive helpers such as samplers, ID generators, propagators, and resource detectors are out of scope. From 6288ab81fa3bce643fff09429be5a64181d145e7 Mon Sep 17 00:00:00 2001 From: cijothomas Date: Sun, 7 Jun 2026 10:38:53 -0700 Subject: [PATCH 10/24] Explain provider event rationale inline --- docs/otel/sdk-events.md | 11 +++++++---- model/otel/events.yaml | 11 +++++++---- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/docs/otel/sdk-events.md b/docs/otel/sdk-events.md index bce7415037..4e366003be 100644 --- a/docs/otel/sdk-events.md +++ b/docs/otel/sdk-events.md @@ -46,10 +46,13 @@ This includes, when applicable, span processors, log record processors, metric readers, and exporters. Passive helpers such as samplers, ID generators, propagators, and resource detectors are out of scope. -Provider-level shutdown (e.g. `TracerProvider`, `LoggerProvider`, `MeterProvider`) -is reported via the events emitted by the provider's child components, not by the -provider itself, unless the provider has shutdown work whose outcome is not -represented by any child component event. +Providers (e.g. `TracerProvider`, `LoggerProvider`, `MeterProvider`) are not +required to emit a separate `otel.sdk.component.shutdown` event: a provider's +shutdown is already covered by the events emitted by its child components, and a +higher-level provider event would carry no information beyond what those child +events already convey. Implementations MAY emit an event for the provider only if +it has shutdown work whose outcome is not represented by any child component +event (e.g., releasing a provider-scoped resource). **Emission rules.** diff --git a/model/otel/events.yaml b/model/otel/events.yaml index c10f306e4c..0a40836c82 100644 --- a/model/otel/events.yaml +++ b/model/otel/events.yaml @@ -16,10 +16,13 @@ groups: readers, and exporters. Passive helpers such as samplers, ID generators, propagators, and resource detectors are out of scope. - Provider-level shutdown (e.g. `TracerProvider`, `LoggerProvider`, `MeterProvider`) - is reported via the events emitted by the provider's child components, not by the - provider itself, unless the provider has shutdown work whose outcome is not - represented by any child component event. + Providers (e.g. `TracerProvider`, `LoggerProvider`, `MeterProvider`) are not + required to emit a separate `otel.sdk.component.shutdown` event: a provider's + shutdown is already covered by the events emitted by its child components, and a + higher-level provider event would carry no information beyond what those child + events already convey. Implementations MAY emit an event for the provider only if + it has shutdown work whose outcome is not represented by any child component + event (e.g., releasing a provider-scoped resource). **Emission rules.** From 52ede2d5d7cff750f3df4902d1727ed0ca5e1d71 Mon Sep 17 00:00:00 2001 From: cijothomas Date: Sun, 7 Jun 2026 10:42:12 -0700 Subject: [PATCH 11/24] Forbid provider-level shutdown event in v0 --- docs/otel/sdk-events.md | 12 +++++------- model/otel/events.yaml | 12 +++++------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/docs/otel/sdk-events.md b/docs/otel/sdk-events.md index 4e366003be..fa07f364db 100644 --- a/docs/otel/sdk-events.md +++ b/docs/otel/sdk-events.md @@ -46,13 +46,11 @@ This includes, when applicable, span processors, log record processors, metric readers, and exporters. Passive helpers such as samplers, ID generators, propagators, and resource detectors are out of scope. -Providers (e.g. `TracerProvider`, `LoggerProvider`, `MeterProvider`) are not -required to emit a separate `otel.sdk.component.shutdown` event: a provider's -shutdown is already covered by the events emitted by its child components, and a -higher-level provider event would carry no information beyond what those child -events already convey. Implementations MAY emit an event for the provider only if -it has shutdown work whose outcome is not represented by any child component -event (e.g., releasing a provider-scoped resource). +Providers (e.g. `TracerProvider`, `LoggerProvider`, `MeterProvider`) MUST NOT +emit this event. A provider's shutdown is already covered by the events emitted +by its child components, and a higher-level provider event would carry no +information beyond what those child events already convey. A future revision of +this convention MAY define provider-level shutdown events if a need emerges. **Emission rules.** diff --git a/model/otel/events.yaml b/model/otel/events.yaml index 0a40836c82..e2c4ce1815 100644 --- a/model/otel/events.yaml +++ b/model/otel/events.yaml @@ -16,13 +16,11 @@ groups: readers, and exporters. Passive helpers such as samplers, ID generators, propagators, and resource detectors are out of scope. - Providers (e.g. `TracerProvider`, `LoggerProvider`, `MeterProvider`) are not - required to emit a separate `otel.sdk.component.shutdown` event: a provider's - shutdown is already covered by the events emitted by its child components, and a - higher-level provider event would carry no information beyond what those child - events already convey. Implementations MAY emit an event for the provider only if - it has shutdown work whose outcome is not represented by any child component - event (e.g., releasing a provider-scoped resource). + Providers (e.g. `TracerProvider`, `LoggerProvider`, `MeterProvider`) MUST NOT + emit this event. A provider's shutdown is already covered by the events emitted + by its child components, and a higher-level provider event would carry no + information beyond what those child events already convey. A future revision of + this convention MAY define provider-level shutdown events if a need emerges. **Emission rules.** From cc20c69aa66dd8bf81542af5661159ffdc9da99b Mon Sep 17 00:00:00 2001 From: cijothomas Date: Sun, 7 Jun 2026 10:44:32 -0700 Subject: [PATCH 12/24] Soften provider wording to non-normative --- docs/otel/sdk-events.md | 11 ++++++----- model/otel/events.yaml | 11 ++++++----- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/docs/otel/sdk-events.md b/docs/otel/sdk-events.md index fa07f364db..21cf320b7a 100644 --- a/docs/otel/sdk-events.md +++ b/docs/otel/sdk-events.md @@ -46,11 +46,12 @@ This includes, when applicable, span processors, log record processors, metric readers, and exporters. Passive helpers such as samplers, ID generators, propagators, and resource detectors are out of scope. -Providers (e.g. `TracerProvider`, `LoggerProvider`, `MeterProvider`) MUST NOT -emit this event. A provider's shutdown is already covered by the events emitted -by its child components, and a higher-level provider event would carry no -information beyond what those child events already convey. A future revision of -this convention MAY define provider-level shutdown events if a need emerges. +Providers (e.g. `TracerProvider`, `LoggerProvider`, `MeterProvider`) are not +expected to emit this event. A provider's shutdown is already covered by the +events emitted by its child components, and a higher-level provider event would +carry no information beyond what those child events already convey. A future +revision of this convention may define provider-level shutdown events if a need +emerges. **Emission rules.** diff --git a/model/otel/events.yaml b/model/otel/events.yaml index e2c4ce1815..56b2f50eb6 100644 --- a/model/otel/events.yaml +++ b/model/otel/events.yaml @@ -16,11 +16,12 @@ groups: readers, and exporters. Passive helpers such as samplers, ID generators, propagators, and resource detectors are out of scope. - Providers (e.g. `TracerProvider`, `LoggerProvider`, `MeterProvider`) MUST NOT - emit this event. A provider's shutdown is already covered by the events emitted - by its child components, and a higher-level provider event would carry no - information beyond what those child events already convey. A future revision of - this convention MAY define provider-level shutdown events if a need emerges. + Providers (e.g. `TracerProvider`, `LoggerProvider`, `MeterProvider`) are not + expected to emit this event. A provider's shutdown is already covered by the + events emitted by its child components, and a higher-level provider event would + carry no information beyond what those child events already convey. A future + revision of this convention may define provider-level shutdown events if a need + emerges. **Emission rules.** From a8bde935a0bbcf4d9cc6bd12fdb8cef1a48c4a0e Mon Sep 17 00:00:00 2001 From: cijothomas Date: Mon, 8 Jun 2026 17:30:07 -0700 Subject: [PATCH 13/24] Tighten applicability, add shutdown.duration, drop obvious sentences --- docs/otel/sdk-events.md | 39 +++++++++++++++++++------------- docs/registry/attributes/otel.md | 20 +++++++++++----- model/otel/events.yaml | 37 +++++++++++++++++------------- model/otel/registry.yaml | 13 +++++++++++ 4 files changed, 71 insertions(+), 38 deletions(-) diff --git a/docs/otel/sdk-events.md b/docs/otel/sdk-events.md index 21cf320b7a..eb8c5f32c1 100644 --- a/docs/otel/sdk-events.md +++ b/docs/otel/sdk-events.md @@ -42,9 +42,11 @@ Indicates that an OpenTelemetry SDK component's shutdown attempt has ended, whet SDK implementations SHOULD emit an `otel.sdk.component.shutdown` event for each SDK component instance that has an explicit `Shutdown` operation and that owns telemetry processing, buffering, reading, or exporting state. -This includes, when applicable, span processors, log record processors, metric -readers, and exporters. Passive helpers such as samplers, ID generators, propagators, -and resource detectors are out of scope. +This includes span processors, log record processors, metric readers, span +exporters, log record exporters, and metric exporters, as well as custom +implementations of any of these categories. See the well-known values of +[`otel.component.type`](/docs/registry/attributes/otel.md) for the full list of +built-in types. Providers (e.g. `TracerProvider`, `LoggerProvider`, `MeterProvider`) are not expected to emit this event. A provider's shutdown is already covered by the @@ -55,23 +57,21 @@ emerges. **Emission rules.** -The event SHOULD be emitted exactly once per component instance per logical -shutdown transition, regardless of how many times the shutdown API is invoked. -Repeated idempotent shutdown calls that perform no additional shutdown work -MUST NOT emit additional events. +An OpenTelemetry SDK component is shut down at most once. The event SHOULD be +emitted exactly once per component instance, reporting the result of that one +shutdown. Subsequent invocations of the shutdown API on a component that is +already shut down MUST NOT emit additional events. If the process terminates without invoking the component's shutdown operation (e.g. a crash, `SIGKILL`, container eviction, or immediate process termination), no event is expected. Consumers MUST NOT interpret the absence of this event as evidence of a clean shutdown. -A single SDK pipeline MAY produce multiple `otel.sdk.component.shutdown` events, -one per component instance whose shutdown is reported. Consumers SHOULD use -`otel.component.name` and `otel.component.type` to distinguish instances. - The event timestamp SHOULD reflect the time at which the shutdown attempt ended -(whether by completing, failing, or being abandoned). The event body SHOULD be -omitted; all event data defined by this convention is conveyed through attributes. +(whether by completing, failing, or being abandoned). Combined with +`otel.component.shutdown.duration`, the start of the shutdown attempt can be +reconstructed as `timestamp - duration`. The event body SHOULD be omitted; all +event data defined by this convention is conveyed through attributes. **Severity.** @@ -120,9 +120,8 @@ event rather than route it through the component or pipeline being shut down. **Forward compatibility.** -Additional attributes (e.g. a shutdown duration) MAY be added in future revisions -of this convention. Consumers MUST tolerate the presence of attributes they do -not recognize. +Additional attributes MAY be added in future revisions of this convention. +Consumers MUST tolerate the presence of attributes they do not recognize. **Attributes:** @@ -133,6 +132,7 @@ not recognize. | [`otel.component.type`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | A name identifying the type of the OpenTelemetry component. [3] | `batching_span_processor`; `com.example.MySpanExporter` | | [`otel.component.dropped`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Recommended` [4] | int | The total number of items the component dropped during normal operation over its lifetime, excluding items abandoned during the shutdown attempt itself (see `otel.component.shutdown.dropped`). [5] | `0`; `42` | | [`otel.component.shutdown.dropped`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Recommended` [6] | int | The number of telemetry items the component could not confirm delivered before the shutdown attempt ended. MUST be `0` when `otel.component.shutdown.result` is `success`; non-zero values are an upper bound on actual loss (in-flight export requests abandoned at timeout may still succeed on the wire). [7] | `0`; `800` | +| [`otel.component.shutdown.duration`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Recommended` | double | The wall-clock elapsed time of the shutdown attempt, in seconds. Combined with the event timestamp, this lets consumers compute when the shutdown attempt started. [8] | `0.015`; `30.0` | **[1] `otel.component.name`:** Implementations SHOULD ensure a low cardinality for this attribute, even across application or SDK restarts. E.g. implementations MUST NOT use UUIDs as values for this attribute. @@ -205,6 +205,13 @@ non-buffering components with an in-flight export request at shutdown time shutdown MUST omit the attribute. Consumers MUST treat absence as "unknown / not applicable", not as `0`. +**[8] `otel.component.shutdown.duration`:** Measured from the moment the component's shutdown operation started to the +moment the shutdown attempt ended (whether by completing, failing, or being +abandoned). MUST be a non-negative value expressed in seconds. + +This attribute is informational and SHOULD NOT affect the severity of the +enclosing event. + --- `otel.component.shutdown.result` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. diff --git a/docs/registry/attributes/otel.md b/docs/registry/attributes/otel.md index 8bd83ef568..70d90739c0 100644 --- a/docs/registry/attributes/otel.md +++ b/docs/registry/attributes/otel.md @@ -62,8 +62,9 @@ Attributes used for OpenTelemetry component self-monitoring | `otel.component.dropped` | ![Development](https://img.shields.io/badge/-development-blue) | int | The total number of telemetry items (spans, log records, metric data points, etc.) the OpenTelemetry SDK component dropped during normal operation over its lifetime. [1] | `0`; `42` | | `otel.component.name` | ![Development](https://img.shields.io/badge/-development-blue) | string | A name uniquely identifying the instance of the OpenTelemetry component within its containing SDK instance. [2] | `otlp_grpc_span_exporter/0`; `custom-name` | | `otel.component.shutdown.dropped` | ![Development](https://img.shields.io/badge/-development-blue) | int | The number of telemetry items that the component had taken responsibility for before shutdown was initiated but could not confirm delivered before the shutdown attempt ended. [3] | `0`; `800` | -| `otel.component.shutdown.result` | ![Development](https://img.shields.io/badge/-development-blue) | string | The result of an OpenTelemetry SDK component shutdown attempt. [4] | `success`; `failed`; `timed_out` | -| `otel.component.type` | ![Development](https://img.shields.io/badge/-development-blue) | string | A name identifying the type of the OpenTelemetry component. [5] | `batching_span_processor`; `com.example.MySpanExporter` | +| `otel.component.shutdown.duration` | ![Development](https://img.shields.io/badge/-development-blue) | double | The wall-clock elapsed time of the component's shutdown attempt, in seconds. [4] | `0.015`; `30.0` | +| `otel.component.shutdown.result` | ![Development](https://img.shields.io/badge/-development-blue) | string | The result of an OpenTelemetry SDK component shutdown attempt. [5] | `success`; `failed`; `timed_out` | +| `otel.component.type` | ![Development](https://img.shields.io/badge/-development-blue) | string | A name identifying the type of the OpenTelemetry component. [6] | `batching_span_processor`; `com.example.MySpanExporter` | **[1] `otel.component.dropped`:** Counts telemetry items that the component accepted (or attempted to accept) and then dropped during normal operation for any reason, e.g. queue overflow @@ -118,7 +119,14 @@ non-buffering components with an in-flight export request at shutdown time shutdown MUST omit the attribute. Consumers MUST treat absence as "unknown / not applicable", not as `0`. -**[4] `otel.component.shutdown.result`:** `timed_out` takes precedence over `failed` when both are observed for the same +**[4] `otel.component.shutdown.duration`:** Measured from the moment the component's shutdown operation started to the +moment the shutdown attempt ended (whether by completing, failing, or being +abandoned). MUST be a non-negative value expressed in seconds. + +This attribute is informational and SHOULD NOT affect the severity of the +enclosing event. + +**[5] `otel.component.shutdown.result`:** `timed_out` takes precedence over `failed` when both are observed for the same shutdown attempt (e.g. when an exporter request is abandoned because the shutdown timeout expired). @@ -129,7 +137,7 @@ If no shutdown timeout/deadline applies to the component, implementations MUST NOT report `timed_out` unless the underlying shutdown API explicitly reports a timeout condition. -**[5] `otel.component.type`:** If none of the standardized values apply, implementations SHOULD use the language-defined name of the type. +**[6] `otel.component.type`:** If none of the standardized values apply, implementations SHOULD use the language-defined name of the type. E.g. for Java the fully qualified classname SHOULD be used in this case. --- @@ -173,9 +181,9 @@ Attributes used by non-OTLP exporters to represent OpenTelemetry Event's concept | Key | Stability | Value Type | Description | Example Values | | --- | --- | --- | --- | --- | -| `otel.event.name` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | string | Identifies the class / type of event. [6] | `browser.mouse.click`; `device.app.lifecycle` | +| `otel.event.name` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | string | Identifies the class / type of event. [7] | `browser.mouse.click`; `device.app.lifecycle` | -**[6] `otel.event.name`:** This attribute SHOULD be used by non-OTLP exporters when destination does not support `EventName` or equivalent field. This attribute MAY be used by applications using existing logging libraries so that it can be used to set the `EventName` field by Collector or SDK components. +**[7] `otel.event.name`:** This attribute SHOULD be used by non-OTLP exporters when destination does not support `EventName` or equivalent field. This attribute MAY be used by applications using existing logging libraries so that it can be used to set the `EventName` field by Collector or SDK components. ## OTel Scope Attributes diff --git a/model/otel/events.yaml b/model/otel/events.yaml index 56b2f50eb6..97bff66d53 100644 --- a/model/otel/events.yaml +++ b/model/otel/events.yaml @@ -12,9 +12,11 @@ groups: SDK implementations SHOULD emit an `otel.sdk.component.shutdown` event for each SDK component instance that has an explicit `Shutdown` operation and that owns telemetry processing, buffering, reading, or exporting state. - This includes, when applicable, span processors, log record processors, metric - readers, and exporters. Passive helpers such as samplers, ID generators, propagators, - and resource detectors are out of scope. + This includes span processors, log record processors, metric readers, span + exporters, log record exporters, and metric exporters, as well as custom + implementations of any of these categories. See the well-known values of + [`otel.component.type`](/docs/registry/attributes/otel.md) for the full list of + built-in types. Providers (e.g. `TracerProvider`, `LoggerProvider`, `MeterProvider`) are not expected to emit this event. A provider's shutdown is already covered by the @@ -25,23 +27,21 @@ groups: **Emission rules.** - The event SHOULD be emitted exactly once per component instance per logical - shutdown transition, regardless of how many times the shutdown API is invoked. - Repeated idempotent shutdown calls that perform no additional shutdown work - MUST NOT emit additional events. + An OpenTelemetry SDK component is shut down at most once. The event SHOULD be + emitted exactly once per component instance, reporting the result of that one + shutdown. Subsequent invocations of the shutdown API on a component that is + already shut down MUST NOT emit additional events. If the process terminates without invoking the component's shutdown operation (e.g. a crash, `SIGKILL`, container eviction, or immediate process termination), no event is expected. Consumers MUST NOT interpret the absence of this event as evidence of a clean shutdown. - A single SDK pipeline MAY produce multiple `otel.sdk.component.shutdown` events, - one per component instance whose shutdown is reported. Consumers SHOULD use - `otel.component.name` and `otel.component.type` to distinguish instances. - The event timestamp SHOULD reflect the time at which the shutdown attempt ended - (whether by completing, failing, or being abandoned). The event body SHOULD be - omitted; all event data defined by this convention is conveyed through attributes. + (whether by completing, failing, or being abandoned). Combined with + `otel.component.shutdown.duration`, the start of the shutdown attempt can be + reconstructed as `timestamp - duration`. The event body SHOULD be omitted; all + event data defined by this convention is conveyed through attributes. **Severity.** @@ -90,9 +90,8 @@ groups: **Forward compatibility.** - Additional attributes (e.g. a shutdown duration) MAY be added in future revisions - of this convention. Consumers MUST tolerate the presence of attributes they do - not recognize. + Additional attributes MAY be added in future revisions of this convention. + Consumers MUST tolerate the presence of attributes they do not recognize. attributes: - ref: otel.component.type requirement_level: required @@ -124,3 +123,9 @@ groups: the shutdown attempt ended. MUST be `0` when `otel.component.shutdown.result` is `success`; non-zero values are an upper bound on actual loss (in-flight export requests abandoned at timeout may still succeed on the wire). + - ref: otel.component.shutdown.duration + requirement_level: recommended + brief: > + The wall-clock elapsed time of the shutdown attempt, in seconds. Combined with + the event timestamp, this lets consumers compute when the shutdown attempt + started. diff --git a/model/otel/registry.yaml b/model/otel/registry.yaml index 8e535c896c..2f2c8479f1 100644 --- a/model/otel/registry.yaml +++ b/model/otel/registry.yaml @@ -292,3 +292,16 @@ groups: shutdown MUST omit the attribute. Consumers MUST treat absence as "unknown / not applicable", not as `0`. examples: [0, 800] + - id: otel.component.shutdown.duration + type: double + stability: development + brief: > + The wall-clock elapsed time of the component's shutdown attempt, in seconds. + note: | + Measured from the moment the component's shutdown operation started to the + moment the shutdown attempt ended (whether by completing, failing, or being + abandoned). MUST be a non-negative value expressed in seconds. + + This attribute is informational and SHOULD NOT affect the severity of the + enclosing event. + examples: [0.015, 30.0] From ea592f52adc96270d3820c6a4a71e7c4fd188522 Mon Sep 17 00:00:00 2001 From: cijothomas Date: Mon, 8 Jun 2026 17:36:46 -0700 Subject: [PATCH 14/24] Narrow severity to shutdown-only; drop self-feedback and forward-compat sections --- docs/otel/sdk-events.md | 42 +++++++++++++---------------------------- model/otel/events.yaml | 42 +++++++++++++---------------------------- 2 files changed, 26 insertions(+), 58 deletions(-) diff --git a/docs/otel/sdk-events.md b/docs/otel/sdk-events.md index eb8c5f32c1..0c5aef1bc1 100644 --- a/docs/otel/sdk-events.md +++ b/docs/otel/sdk-events.md @@ -76,25 +76,23 @@ event data defined by this convention is conveyed through attributes. **Severity.** Implementations SHOULD set the log record severity to `WARN` -(`SeverityNumber` = `13`) if **any** of the following hold, and to `INFO` +(`SeverityNumber` = `13`) if either of the following holds, and to `INFO` (`SeverityNumber` = `9`) otherwise: -- `otel.component.shutdown.result` is not `success`, -- `otel.component.shutdown.dropped` is **present** and greater than `0`, or -- `otel.component.dropped` is **present** and greater than `0`. +- `otel.component.shutdown.result` is not `success`, or +- `otel.component.shutdown.dropped` is **present** and greater than `0`. -A component MAY therefore emit an event with `otel.component.shutdown.result` = -`success` and `WARN` severity if it reports lifetime drops that occurred before -shutdown. This is intentional: the event is meant to be a single terminal place -to detect that the SDK lost telemetry, including drops that may have happened -earlier when the metrics pipeline was unavailable or unreliable. +`otel.component.dropped` (the lifetime counter) does not affect severity: it is +reported on this event as a diagnostic snapshot, but lifetime drops are the +domain of per-operation SDK metrics (e.g. `otel.sdk.processor.*.processed` with +`error.type`) and should be alerted on there. Operators who specifically want a +"lost-any-data-ever" signal from this event alone can query for +`otel.component.dropped > 0` directly. -Components that do not track a lifetime dropped count MUST omit -`otel.component.dropped`, and components that do not own queued, buffered, retry, -or in-flight telemetry items at shutdown MUST omit `otel.component.shutdown.dropped`. -Absence of either attribute MUST NOT be treated as `0` for the severity rule -above; absence means "not applicable / not tracked", and the severity is -determined by the remaining present attributes. +Components that do not own queued, buffered, retry, or in-flight telemetry items +at shutdown MUST omit `otel.component.shutdown.dropped`. Absence of the +attribute MUST NOT be treated as `0` for the severity rule above; absence means +"not applicable / not tracked". **Relationship with existing SDK metrics.** @@ -109,20 +107,6 @@ The reason a shutdown failed is intentionally not classified on this event responsibility of the operation-level signals (e.g. `otel.sdk.exporter.*.exported` with `error.type`) emitted while the SDK is still healthy. -**Self-feedback.** - -Implementations MUST NOT emit this event through the same component instance whose -shutdown is being reported. For log SDK components, implementations MUST NOT route -the event through the same `LoggerProvider`, `LogRecordProcessor`, or -`LogRecordExporter` instance that is currently being shut down. If no independent -self-observability emission path is available, implementations MAY suppress the -event rather than route it through the component or pipeline being shut down. - -**Forward compatibility.** - -Additional attributes MAY be added in future revisions of this convention. -Consumers MUST tolerate the presence of attributes they do not recognize. - **Attributes:** | Key | Stability | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Value Type | Description | Example Values | diff --git a/model/otel/events.yaml b/model/otel/events.yaml index 97bff66d53..e976afdb61 100644 --- a/model/otel/events.yaml +++ b/model/otel/events.yaml @@ -46,25 +46,23 @@ groups: **Severity.** Implementations SHOULD set the log record severity to `WARN` - (`SeverityNumber` = `13`) if **any** of the following hold, and to `INFO` + (`SeverityNumber` = `13`) if either of the following holds, and to `INFO` (`SeverityNumber` = `9`) otherwise: - - `otel.component.shutdown.result` is not `success`, - - `otel.component.shutdown.dropped` is **present** and greater than `0`, or - - `otel.component.dropped` is **present** and greater than `0`. + - `otel.component.shutdown.result` is not `success`, or + - `otel.component.shutdown.dropped` is **present** and greater than `0`. - A component MAY therefore emit an event with `otel.component.shutdown.result` = - `success` and `WARN` severity if it reports lifetime drops that occurred before - shutdown. This is intentional: the event is meant to be a single terminal place - to detect that the SDK lost telemetry, including drops that may have happened - earlier when the metrics pipeline was unavailable or unreliable. + `otel.component.dropped` (the lifetime counter) does not affect severity: it is + reported on this event as a diagnostic snapshot, but lifetime drops are the + domain of per-operation SDK metrics (e.g. `otel.sdk.processor.*.processed` with + `error.type`) and should be alerted on there. Operators who specifically want a + "lost-any-data-ever" signal from this event alone can query for + `otel.component.dropped > 0` directly. - Components that do not track a lifetime dropped count MUST omit - `otel.component.dropped`, and components that do not own queued, buffered, retry, - or in-flight telemetry items at shutdown MUST omit `otel.component.shutdown.dropped`. - Absence of either attribute MUST NOT be treated as `0` for the severity rule - above; absence means "not applicable / not tracked", and the severity is - determined by the remaining present attributes. + Components that do not own queued, buffered, retry, or in-flight telemetry items + at shutdown MUST omit `otel.component.shutdown.dropped`. Absence of the + attribute MUST NOT be treated as `0` for the severity rule above; absence means + "not applicable / not tracked". **Relationship with existing SDK metrics.** @@ -78,20 +76,6 @@ groups: (there is no `error.type` attribute). Failure-cause classification is the responsibility of the operation-level signals (e.g. `otel.sdk.exporter.*.exported` with `error.type`) emitted while the SDK is still healthy. - - **Self-feedback.** - - Implementations MUST NOT emit this event through the same component instance whose - shutdown is being reported. For log SDK components, implementations MUST NOT route - the event through the same `LoggerProvider`, `LogRecordProcessor`, or - `LogRecordExporter` instance that is currently being shut down. If no independent - self-observability emission path is available, implementations MAY suppress the - event rather than route it through the component or pipeline being shut down. - - **Forward compatibility.** - - Additional attributes MAY be added in future revisions of this convention. - Consumers MUST tolerate the presence of attributes they do not recognize. attributes: - ref: otel.component.type requirement_level: required From ee52ee777831d7084c9ba08f587ee3312444691c Mon Sep 17 00:00:00 2001 From: cijothomas Date: Mon, 8 Jun 2026 17:44:41 -0700 Subject: [PATCH 15/24] Simplify severity rule to single condition --- docs/otel/sdk-events.md | 12 ++---------- model/otel/events.yaml | 12 ++---------- 2 files changed, 4 insertions(+), 20 deletions(-) diff --git a/docs/otel/sdk-events.md b/docs/otel/sdk-events.md index 0c5aef1bc1..51ad758358 100644 --- a/docs/otel/sdk-events.md +++ b/docs/otel/sdk-events.md @@ -76,11 +76,8 @@ event data defined by this convention is conveyed through attributes. **Severity.** Implementations SHOULD set the log record severity to `WARN` -(`SeverityNumber` = `13`) if either of the following holds, and to `INFO` -(`SeverityNumber` = `9`) otherwise: - -- `otel.component.shutdown.result` is not `success`, or -- `otel.component.shutdown.dropped` is **present** and greater than `0`. +(`SeverityNumber` = `13`) when `otel.component.shutdown.result` is not +`success`, and to `INFO` (`SeverityNumber` = `9`) otherwise. `otel.component.dropped` (the lifetime counter) does not affect severity: it is reported on this event as a diagnostic snapshot, but lifetime drops are the @@ -89,11 +86,6 @@ domain of per-operation SDK metrics (e.g. `otel.sdk.processor.*.processed` with "lost-any-data-ever" signal from this event alone can query for `otel.component.dropped > 0` directly. -Components that do not own queued, buffered, retry, or in-flight telemetry items -at shutdown MUST omit `otel.component.shutdown.dropped`. Absence of the -attribute MUST NOT be treated as `0` for the severity rule above; absence means -"not applicable / not tracked". - **Relationship with existing SDK metrics.** The drop counts on this event are a terminal summary emitted at shutdown, when diff --git a/model/otel/events.yaml b/model/otel/events.yaml index e976afdb61..e5636e27a5 100644 --- a/model/otel/events.yaml +++ b/model/otel/events.yaml @@ -46,11 +46,8 @@ groups: **Severity.** Implementations SHOULD set the log record severity to `WARN` - (`SeverityNumber` = `13`) if either of the following holds, and to `INFO` - (`SeverityNumber` = `9`) otherwise: - - - `otel.component.shutdown.result` is not `success`, or - - `otel.component.shutdown.dropped` is **present** and greater than `0`. + (`SeverityNumber` = `13`) when `otel.component.shutdown.result` is not + `success`, and to `INFO` (`SeverityNumber` = `9`) otherwise. `otel.component.dropped` (the lifetime counter) does not affect severity: it is reported on this event as a diagnostic snapshot, but lifetime drops are the @@ -59,11 +56,6 @@ groups: "lost-any-data-ever" signal from this event alone can query for `otel.component.dropped > 0` directly. - Components that do not own queued, buffered, retry, or in-flight telemetry items - at shutdown MUST omit `otel.component.shutdown.dropped`. Absence of the - attribute MUST NOT be treated as `0` for the severity rule above; absence means - "not applicable / not tracked". - **Relationship with existing SDK metrics.** The drop counts on this event are a terminal summary emitted at shutdown, when From edd72dca7f9c017d45f42d59a583e502abdd68db Mon Sep 17 00:00:00 2001 From: cijothomas Date: Mon, 8 Jun 2026 17:46:03 -0700 Subject: [PATCH 16/24] Trim severity and metrics-relationship prose --- docs/otel/sdk-events.md | 19 ++++++++----------- model/otel/events.yaml | 19 ++++++++----------- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/docs/otel/sdk-events.md b/docs/otel/sdk-events.md index 51ad758358..92917968db 100644 --- a/docs/otel/sdk-events.md +++ b/docs/otel/sdk-events.md @@ -79,20 +79,17 @@ Implementations SHOULD set the log record severity to `WARN` (`SeverityNumber` = `13`) when `otel.component.shutdown.result` is not `success`, and to `INFO` (`SeverityNumber` = `9`) otherwise. -`otel.component.dropped` (the lifetime counter) does not affect severity: it is -reported on this event as a diagnostic snapshot, but lifetime drops are the -domain of per-operation SDK metrics (e.g. `otel.sdk.processor.*.processed` with -`error.type`) and should be alerted on there. Operators who specifically want a -"lost-any-data-ever" signal from this event alone can query for -`otel.component.dropped > 0` directly. +`otel.component.dropped` (the lifetime counter) does not affect severity; it is +a diagnostic snapshot on this event, and lifetime drops are alerted on via +per-operation SDK metrics such as `otel.sdk.processor.*.processed` with +`error.type`. **Relationship with existing SDK metrics.** -The drop counts on this event are a terminal summary emitted at shutdown, when -the metrics pipeline itself may no longer be reliable. These counts MAY overlap -with per-operation SDK metrics (e.g. `otel.sdk.processor.*.processed` or -`otel.sdk.exporter.*.exported`, both with `error.type`) and SHOULD NOT be -combined with those metrics to compute aggregate loss. +Drop counts on this event MAY overlap with per-operation SDK metrics +(e.g. `otel.sdk.processor.*.processed` or `otel.sdk.exporter.*.exported`, both +with `error.type`) and SHOULD NOT be combined with those metrics to compute +aggregate loss. The reason a shutdown failed is intentionally not classified on this event (there is no `error.type` attribute). Failure-cause classification is the diff --git a/model/otel/events.yaml b/model/otel/events.yaml index e5636e27a5..2b8e54069b 100644 --- a/model/otel/events.yaml +++ b/model/otel/events.yaml @@ -49,20 +49,17 @@ groups: (`SeverityNumber` = `13`) when `otel.component.shutdown.result` is not `success`, and to `INFO` (`SeverityNumber` = `9`) otherwise. - `otel.component.dropped` (the lifetime counter) does not affect severity: it is - reported on this event as a diagnostic snapshot, but lifetime drops are the - domain of per-operation SDK metrics (e.g. `otel.sdk.processor.*.processed` with - `error.type`) and should be alerted on there. Operators who specifically want a - "lost-any-data-ever" signal from this event alone can query for - `otel.component.dropped > 0` directly. + `otel.component.dropped` (the lifetime counter) does not affect severity; it is + a diagnostic snapshot on this event, and lifetime drops are alerted on via + per-operation SDK metrics such as `otel.sdk.processor.*.processed` with + `error.type`. **Relationship with existing SDK metrics.** - The drop counts on this event are a terminal summary emitted at shutdown, when - the metrics pipeline itself may no longer be reliable. These counts MAY overlap - with per-operation SDK metrics (e.g. `otel.sdk.processor.*.processed` or - `otel.sdk.exporter.*.exported`, both with `error.type`) and SHOULD NOT be - combined with those metrics to compute aggregate loss. + Drop counts on this event MAY overlap with per-operation SDK metrics + (e.g. `otel.sdk.processor.*.processed` or `otel.sdk.exporter.*.exported`, both + with `error.type`) and SHOULD NOT be combined with those metrics to compute + aggregate loss. The reason a shutdown failed is intentionally not classified on this event (there is no `error.type` attribute). Failure-cause classification is the From ee0e12adfd1def1b0d824fae4b5525324395f990 Mon Sep 17 00:00:00 2001 From: cijothomas Date: Mon, 8 Jun 2026 17:51:05 -0700 Subject: [PATCH 17/24] Drop cross-signal sum callout --- docs/otel/sdk-events.md | 7 +------ model/otel/events.yaml | 7 +------ 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/docs/otel/sdk-events.md b/docs/otel/sdk-events.md index 92917968db..41dd817ef8 100644 --- a/docs/otel/sdk-events.md +++ b/docs/otel/sdk-events.md @@ -84,12 +84,7 @@ a diagnostic snapshot on this event, and lifetime drops are alerted on via per-operation SDK metrics such as `otel.sdk.processor.*.processed` with `error.type`. -**Relationship with existing SDK metrics.** - -Drop counts on this event MAY overlap with per-operation SDK metrics -(e.g. `otel.sdk.processor.*.processed` or `otel.sdk.exporter.*.exported`, both -with `error.type`) and SHOULD NOT be combined with those metrics to compute -aggregate loss. +**Relationship with `error.type`.** The reason a shutdown failed is intentionally not classified on this event (there is no `error.type` attribute). Failure-cause classification is the diff --git a/model/otel/events.yaml b/model/otel/events.yaml index 2b8e54069b..6c9cf3d561 100644 --- a/model/otel/events.yaml +++ b/model/otel/events.yaml @@ -54,12 +54,7 @@ groups: per-operation SDK metrics such as `otel.sdk.processor.*.processed` with `error.type`. - **Relationship with existing SDK metrics.** - - Drop counts on this event MAY overlap with per-operation SDK metrics - (e.g. `otel.sdk.processor.*.processed` or `otel.sdk.exporter.*.exported`, both - with `error.type`) and SHOULD NOT be combined with those metrics to compute - aggregate loss. + **Relationship with `error.type`.** The reason a shutdown failed is intentionally not classified on this event (there is no `error.type` attribute). Failure-cause classification is the From a5fc1b2d975f763c10212450ec4ebba2b219b1ea Mon Sep 17 00:00:00 2001 From: cijothomas Date: Wed, 10 Jun 2026 18:12:27 -0700 Subject: [PATCH 18/24] Drop lifetime and shutdown drop counters; keep result + duration only --- .chloggen/sdk-component-shutdown-event.yaml | 2 +- docs/otel/sdk-events.md | 69 ++++----------------- docs/registry/attributes/otel.md | 63 ++++--------------- model/otel/events.yaml | 44 ++++--------- model/otel/registry.yaml | 51 --------------- 5 files changed, 36 insertions(+), 193 deletions(-) diff --git a/.chloggen/sdk-component-shutdown-event.yaml b/.chloggen/sdk-component-shutdown-event.yaml index 110c7edf88..9559203cbe 100644 --- a/.chloggen/sdk-component-shutdown-event.yaml +++ b/.chloggen/sdk-component-shutdown-event.yaml @@ -2,7 +2,7 @@ change_type: enhancement component: otel -note: Add `otel.sdk.component.shutdown` self-observability event and supporting attributes (`otel.component.shutdown.result`, `otel.component.dropped`, `otel.component.shutdown.dropped`). +note: Add `otel.sdk.component.shutdown` self-observability event and supporting attributes (`otel.component.shutdown.result`, `otel.component.shutdown.duration`). issues: [3718] diff --git a/docs/otel/sdk-events.md b/docs/otel/sdk-events.md index 41dd817ef8..563f2af39d 100644 --- a/docs/otel/sdk-events.md +++ b/docs/otel/sdk-events.md @@ -79,17 +79,19 @@ Implementations SHOULD set the log record severity to `WARN` (`SeverityNumber` = `13`) when `otel.component.shutdown.result` is not `success`, and to `INFO` (`SeverityNumber` = `9`) otherwise. -`otel.component.dropped` (the lifetime counter) does not affect severity; it is -a diagnostic snapshot on this event, and lifetime drops are alerted on via -per-operation SDK metrics such as `otel.sdk.processor.*.processed` with -`error.type`. - -**Relationship with `error.type`.** +**Relationship with `error.type` and per-operation drop accounting.** The reason a shutdown failed is intentionally not classified on this event -(there is no `error.type` attribute). Failure-cause classification is the -responsibility of the operation-level signals (e.g. `otel.sdk.exporter.*.exported` -with `error.type`) emitted while the SDK is still healthy. +(there is no `error.type` attribute). Failure-cause classification and +lifetime/per-operation drop accounting are the responsibility of the +operation-level signals (e.g. `otel.sdk.exporter.*.exported` and +`otel.sdk.processor.*.processed` with `error.type`) emitted while the SDK +is still healthy. The exact count of telemetry items abandoned during a +`failed` or `timed_out` shutdown is often unknowable to the component +(e.g. items still in a worker thread's buffer at the moment shutdown is +abandoned). Consumers should treat a non-`success` `result` as +"shutdown was not clean; some loss possible" and rely on per-operation +signals for precise accounting. **Attributes:** @@ -98,9 +100,7 @@ with `error.type`) emitted while the SDK is still healthy. | [`otel.component.name`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | A name uniquely identifying the instance of the OpenTelemetry component within its containing SDK instance. [1] | `otlp_grpc_span_exporter/0`; `custom-name` | | [`otel.component.shutdown.result`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | The result of an OpenTelemetry SDK component shutdown attempt. [2] | `success`; `failed`; `timed_out` | | [`otel.component.type`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | A name identifying the type of the OpenTelemetry component. [3] | `batching_span_processor`; `com.example.MySpanExporter` | -| [`otel.component.dropped`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Recommended` [4] | int | The total number of items the component dropped during normal operation over its lifetime, excluding items abandoned during the shutdown attempt itself (see `otel.component.shutdown.dropped`). [5] | `0`; `42` | -| [`otel.component.shutdown.dropped`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Recommended` [6] | int | The number of telemetry items the component could not confirm delivered before the shutdown attempt ended. MUST be `0` when `otel.component.shutdown.result` is `success`; non-zero values are an upper bound on actual loss (in-flight export requests abandoned at timeout may still succeed on the wire). [7] | `0`; `800` | -| [`otel.component.shutdown.duration`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Recommended` | double | The wall-clock elapsed time of the shutdown attempt, in seconds. Combined with the event timestamp, this lets consumers compute when the shutdown attempt started. [8] | `0.015`; `30.0` | +| [`otel.component.shutdown.duration`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Recommended` | double | The wall-clock elapsed time of the shutdown attempt, in seconds. Combined with the event timestamp, this lets consumers compute when the shutdown attempt started. [4] | `0.015`; `30.0` | **[1] `otel.component.name`:** Implementations SHOULD ensure a low cardinality for this attribute, even across application or SDK restarts. E.g. implementations MUST NOT use UUIDs as values for this attribute. @@ -130,50 +130,7 @@ timeout condition. **[3] `otel.component.type`:** If none of the standardized values apply, implementations SHOULD use the language-defined name of the type. E.g. for Java the fully qualified classname SHOULD be used in this case. -**[4] `otel.component.dropped`:** If the component tracks a lifetime dropped count (e.g. queue-based processors such as the Batching Span Processor or Batching Log Record Processor). Components that do not track this MUST omit the attribute; consumers MUST treat absence as "unknown / not applicable", not as `0`. - -**[5] `otel.component.dropped`:** Counts telemetry items that the component accepted (or attempted to accept) -and then dropped during normal operation for any reason, e.g. queue overflow -or export failures that exhausted retries. The value MUST be a non-negative -integer and is cumulative from the time the component was started until the -moment the enclosing event (e.g. `otel.sdk.component.shutdown`) is emitted. - -This counter does NOT include items reported via -`otel.component.shutdown.dropped`, and does NOT include items refused because -the component's shutdown had already begun (those are typically already -exposed by other SDK metrics, e.g. `otel.sdk.processor.*.processed` with -`error.type`). - -This attribute is only applicable to components that track a lifetime dropped -count, such as queue-based processors (e.g. the Batching Span Processor or -Batching Log Record Processor). Components that do not track this MUST omit -the attribute. Consumers MUST treat absence as "unknown / not applicable", -not as `0`. - -**[6] `otel.component.shutdown.dropped`:** If the component owns queued, buffered, retry, or in-flight telemetry items at the time shutdown is initiated (e.g. queue-based processors such as the Batching Span Processor, or an exporter with an in-flight export request). Components that do not own such items MUST omit the attribute; consumers MUST treat absence as "unknown / not applicable", not as `0`. - -**[7] `otel.component.shutdown.dropped`:** Reported on the `otel.sdk.component.shutdown` event. Counts telemetry items -the component had accepted prior to shutdown (queued, buffered, scheduled for -retry, or handed to a downstream component/exporter in an operation that did -not return) and could not confirm delivered by the time the shutdown attempt -ended (typically because the configured shutdown timeout elapsed, or the -final export attempt failed). - -The value MUST be a non-negative integer. When `otel.component.shutdown.result` -is `success`, this attribute MUST be `0`. Non-zero values are an upper bound -on actual loss: in-flight export requests that the SDK abandoned (e.g. at -timeout) MAY still complete successfully on the wire after the SDK gave up, -but the SDK cannot confirm delivery so they are counted here. - -This attribute is applicable to any component that owns queued, buffered, -retry, or in-flight telemetry items at the time shutdown is initiated. This -includes both buffering components (e.g. the Batching Span Processor) and -non-buffering components with an in-flight export request at shutdown time -(e.g. an OTLP exporter). Components that do not own any such items at -shutdown MUST omit the attribute. Consumers MUST treat absence as -"unknown / not applicable", not as `0`. - -**[8] `otel.component.shutdown.duration`:** Measured from the moment the component's shutdown operation started to the +**[4] `otel.component.shutdown.duration`:** Measured from the moment the component's shutdown operation started to the moment the shutdown attempt ended (whether by completing, failing, or being abandoned). MUST be a non-negative value expressed in seconds. diff --git a/docs/registry/attributes/otel.md b/docs/registry/attributes/otel.md index 70d90739c0..d723214dc8 100644 --- a/docs/registry/attributes/otel.md +++ b/docs/registry/attributes/otel.md @@ -59,32 +59,12 @@ Attributes used for OpenTelemetry component self-monitoring | Key | Stability | Value Type | Description | Example Values | | --- | --- | --- | --- | --- | -| `otel.component.dropped` | ![Development](https://img.shields.io/badge/-development-blue) | int | The total number of telemetry items (spans, log records, metric data points, etc.) the OpenTelemetry SDK component dropped during normal operation over its lifetime. [1] | `0`; `42` | -| `otel.component.name` | ![Development](https://img.shields.io/badge/-development-blue) | string | A name uniquely identifying the instance of the OpenTelemetry component within its containing SDK instance. [2] | `otlp_grpc_span_exporter/0`; `custom-name` | -| `otel.component.shutdown.dropped` | ![Development](https://img.shields.io/badge/-development-blue) | int | The number of telemetry items that the component had taken responsibility for before shutdown was initiated but could not confirm delivered before the shutdown attempt ended. [3] | `0`; `800` | -| `otel.component.shutdown.duration` | ![Development](https://img.shields.io/badge/-development-blue) | double | The wall-clock elapsed time of the component's shutdown attempt, in seconds. [4] | `0.015`; `30.0` | -| `otel.component.shutdown.result` | ![Development](https://img.shields.io/badge/-development-blue) | string | The result of an OpenTelemetry SDK component shutdown attempt. [5] | `success`; `failed`; `timed_out` | -| `otel.component.type` | ![Development](https://img.shields.io/badge/-development-blue) | string | A name identifying the type of the OpenTelemetry component. [6] | `batching_span_processor`; `com.example.MySpanExporter` | - -**[1] `otel.component.dropped`:** Counts telemetry items that the component accepted (or attempted to accept) -and then dropped during normal operation for any reason, e.g. queue overflow -or export failures that exhausted retries. The value MUST be a non-negative -integer and is cumulative from the time the component was started until the -moment the enclosing event (e.g. `otel.sdk.component.shutdown`) is emitted. - -This counter does NOT include items reported via -`otel.component.shutdown.dropped`, and does NOT include items refused because -the component's shutdown had already begun (those are typically already -exposed by other SDK metrics, e.g. `otel.sdk.processor.*.processed` with -`error.type`). - -This attribute is only applicable to components that track a lifetime dropped -count, such as queue-based processors (e.g. the Batching Span Processor or -Batching Log Record Processor). Components that do not track this MUST omit -the attribute. Consumers MUST treat absence as "unknown / not applicable", -not as `0`. - -**[2] `otel.component.name`:** Implementations SHOULD ensure a low cardinality for this attribute, even across application or SDK restarts. +| `otel.component.name` | ![Development](https://img.shields.io/badge/-development-blue) | string | A name uniquely identifying the instance of the OpenTelemetry component within its containing SDK instance. [1] | `otlp_grpc_span_exporter/0`; `custom-name` | +| `otel.component.shutdown.duration` | ![Development](https://img.shields.io/badge/-development-blue) | double | The wall-clock elapsed time of the component's shutdown attempt, in seconds. [2] | `0.015`; `30.0` | +| `otel.component.shutdown.result` | ![Development](https://img.shields.io/badge/-development-blue) | string | The result of an OpenTelemetry SDK component shutdown attempt. [3] | `success`; `failed`; `timed_out` | +| `otel.component.type` | ![Development](https://img.shields.io/badge/-development-blue) | string | A name identifying the type of the OpenTelemetry component. [4] | `batching_span_processor`; `com.example.MySpanExporter` | + +**[1] `otel.component.name`:** Implementations SHOULD ensure a low cardinality for this attribute, even across application or SDK restarts. E.g. implementations MUST NOT use UUIDs as values for this attribute. Implementations MAY achieve these goals by following a `/` pattern, e.g. `batching_span_processor/0`. @@ -98,35 +78,14 @@ With this implementation, for example the first Batching Span Processor would ha as `otel.component.name`, the second one `batching_span_processor/1` and so on. These values will therefore be reused in the case of an application restart. -**[3] `otel.component.shutdown.dropped`:** Reported on the `otel.sdk.component.shutdown` event. Counts telemetry items -the component had accepted prior to shutdown (queued, buffered, scheduled for -retry, or handed to a downstream component/exporter in an operation that did -not return) and could not confirm delivered by the time the shutdown attempt -ended (typically because the configured shutdown timeout elapsed, or the -final export attempt failed). - -The value MUST be a non-negative integer. When `otel.component.shutdown.result` -is `success`, this attribute MUST be `0`. Non-zero values are an upper bound -on actual loss: in-flight export requests that the SDK abandoned (e.g. at -timeout) MAY still complete successfully on the wire after the SDK gave up, -but the SDK cannot confirm delivery so they are counted here. - -This attribute is applicable to any component that owns queued, buffered, -retry, or in-flight telemetry items at the time shutdown is initiated. This -includes both buffering components (e.g. the Batching Span Processor) and -non-buffering components with an in-flight export request at shutdown time -(e.g. an OTLP exporter). Components that do not own any such items at -shutdown MUST omit the attribute. Consumers MUST treat absence as -"unknown / not applicable", not as `0`. - -**[4] `otel.component.shutdown.duration`:** Measured from the moment the component's shutdown operation started to the +**[2] `otel.component.shutdown.duration`:** Measured from the moment the component's shutdown operation started to the moment the shutdown attempt ended (whether by completing, failing, or being abandoned). MUST be a non-negative value expressed in seconds. This attribute is informational and SHOULD NOT affect the severity of the enclosing event. -**[5] `otel.component.shutdown.result`:** `timed_out` takes precedence over `failed` when both are observed for the same +**[3] `otel.component.shutdown.result`:** `timed_out` takes precedence over `failed` when both are observed for the same shutdown attempt (e.g. when an exporter request is abandoned because the shutdown timeout expired). @@ -137,7 +96,7 @@ If no shutdown timeout/deadline applies to the component, implementations MUST NOT report `timed_out` unless the underlying shutdown API explicitly reports a timeout condition. -**[6] `otel.component.type`:** If none of the standardized values apply, implementations SHOULD use the language-defined name of the type. +**[4] `otel.component.type`:** If none of the standardized values apply, implementations SHOULD use the language-defined name of the type. E.g. for Java the fully qualified classname SHOULD be used in this case. --- @@ -181,9 +140,9 @@ Attributes used by non-OTLP exporters to represent OpenTelemetry Event's concept | Key | Stability | Value Type | Description | Example Values | | --- | --- | --- | --- | --- | -| `otel.event.name` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | string | Identifies the class / type of event. [7] | `browser.mouse.click`; `device.app.lifecycle` | +| `otel.event.name` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | string | Identifies the class / type of event. [5] | `browser.mouse.click`; `device.app.lifecycle` | -**[7] `otel.event.name`:** This attribute SHOULD be used by non-OTLP exporters when destination does not support `EventName` or equivalent field. This attribute MAY be used by applications using existing logging libraries so that it can be used to set the `EventName` field by Collector or SDK components. +**[5] `otel.event.name`:** This attribute SHOULD be used by non-OTLP exporters when destination does not support `EventName` or equivalent field. This attribute MAY be used by applications using existing logging libraries so that it can be used to set the `EventName` field by Collector or SDK components. ## OTel Scope Attributes diff --git a/model/otel/events.yaml b/model/otel/events.yaml index 6c9cf3d561..ba0dff75ff 100644 --- a/model/otel/events.yaml +++ b/model/otel/events.yaml @@ -49,17 +49,19 @@ groups: (`SeverityNumber` = `13`) when `otel.component.shutdown.result` is not `success`, and to `INFO` (`SeverityNumber` = `9`) otherwise. - `otel.component.dropped` (the lifetime counter) does not affect severity; it is - a diagnostic snapshot on this event, and lifetime drops are alerted on via - per-operation SDK metrics such as `otel.sdk.processor.*.processed` with - `error.type`. - - **Relationship with `error.type`.** + **Relationship with `error.type` and per-operation drop accounting.** The reason a shutdown failed is intentionally not classified on this event - (there is no `error.type` attribute). Failure-cause classification is the - responsibility of the operation-level signals (e.g. `otel.sdk.exporter.*.exported` - with `error.type`) emitted while the SDK is still healthy. + (there is no `error.type` attribute). Failure-cause classification and + lifetime/per-operation drop accounting are the responsibility of the + operation-level signals (e.g. `otel.sdk.exporter.*.exported` and + `otel.sdk.processor.*.processed` with `error.type`) emitted while the SDK + is still healthy. The exact count of telemetry items abandoned during a + `failed` or `timed_out` shutdown is often unknowable to the component + (e.g. items still in a worker thread's buffer at the moment shutdown is + abandoned). Consumers should treat a non-`success` `result` as + "shutdown was not clean; some loss possible" and rely on per-operation + signals for precise accounting. attributes: - ref: otel.component.type requirement_level: required @@ -67,30 +69,6 @@ groups: requirement_level: required - ref: otel.component.shutdown.result requirement_level: required - - ref: otel.component.dropped - requirement_level: - recommended: > - If the component tracks a lifetime dropped count (e.g. queue-based - processors such as the Batching Span Processor or Batching Log Record - Processor). Components that do not track this MUST omit the attribute; - consumers MUST treat absence as "unknown / not applicable", not as `0`. - brief: > - The total number of items the component dropped during normal operation over - its lifetime, excluding items abandoned during the shutdown attempt itself - (see `otel.component.shutdown.dropped`). - - ref: otel.component.shutdown.dropped - requirement_level: - recommended: > - If the component owns queued, buffered, retry, or in-flight telemetry items - at the time shutdown is initiated (e.g. queue-based processors such as the - Batching Span Processor, or an exporter with an in-flight export request). - Components that do not own such items MUST omit the attribute; consumers - MUST treat absence as "unknown / not applicable", not as `0`. - brief: > - The number of telemetry items the component could not confirm delivered before - the shutdown attempt ended. MUST be `0` when `otel.component.shutdown.result` - is `success`; non-zero values are an upper bound on actual loss (in-flight - export requests abandoned at timeout may still succeed on the wire). - ref: otel.component.shutdown.duration requirement_level: recommended brief: > diff --git a/model/otel/registry.yaml b/model/otel/registry.yaml index 2f2c8479f1..4da8679741 100644 --- a/model/otel/registry.yaml +++ b/model/otel/registry.yaml @@ -241,57 +241,6 @@ groups: NOT report `timed_out` unless the underlying shutdown API explicitly reports a timeout condition. examples: ["success", "failed", "timed_out"] - - id: otel.component.dropped - type: int - stability: development - brief: > - The total number of telemetry items (spans, log records, metric data points, etc.) the OpenTelemetry SDK component dropped during normal operation over its lifetime. - note: | - Counts telemetry items that the component accepted (or attempted to accept) - and then dropped during normal operation for any reason, e.g. queue overflow - or export failures that exhausted retries. The value MUST be a non-negative - integer and is cumulative from the time the component was started until the - moment the enclosing event (e.g. `otel.sdk.component.shutdown`) is emitted. - - This counter does NOT include items reported via - `otel.component.shutdown.dropped`, and does NOT include items refused because - the component's shutdown had already begun (those are typically already - exposed by other SDK metrics, e.g. `otel.sdk.processor.*.processed` with - `error.type`). - - This attribute is only applicable to components that track a lifetime dropped - count, such as queue-based processors (e.g. the Batching Span Processor or - Batching Log Record Processor). Components that do not track this MUST omit - the attribute. Consumers MUST treat absence as "unknown / not applicable", - not as `0`. - examples: [0, 42] - - id: otel.component.shutdown.dropped - type: int - stability: development - brief: > - The number of telemetry items that the component had taken responsibility for before shutdown was initiated but could not confirm delivered before the shutdown attempt ended. - note: | - Reported on the `otel.sdk.component.shutdown` event. Counts telemetry items - the component had accepted prior to shutdown (queued, buffered, scheduled for - retry, or handed to a downstream component/exporter in an operation that did - not return) and could not confirm delivered by the time the shutdown attempt - ended (typically because the configured shutdown timeout elapsed, or the - final export attempt failed). - - The value MUST be a non-negative integer. When `otel.component.shutdown.result` - is `success`, this attribute MUST be `0`. Non-zero values are an upper bound - on actual loss: in-flight export requests that the SDK abandoned (e.g. at - timeout) MAY still complete successfully on the wire after the SDK gave up, - but the SDK cannot confirm delivery so they are counted here. - - This attribute is applicable to any component that owns queued, buffered, - retry, or in-flight telemetry items at the time shutdown is initiated. This - includes both buffering components (e.g. the Batching Span Processor) and - non-buffering components with an in-flight export request at shutdown time - (e.g. an OTLP exporter). Components that do not own any such items at - shutdown MUST omit the attribute. Consumers MUST treat absence as - "unknown / not applicable", not as `0`. - examples: [0, 800] - id: otel.component.shutdown.duration type: double stability: development From 2a9ea8605a8837ea0825f96de4e29963d05d36bb Mon Sep 17 00:00:00 2001 From: cijothomas Date: Wed, 10 Jun 2026 19:14:30 -0700 Subject: [PATCH 19/24] Tighten shutdown event: MUST severity, closed result enum, duration nesting note --- docs/otel/sdk-events.md | 16 +++++++++++++++- docs/registry/attributes/otel.md | 5 +++++ model/otel/events.yaml | 11 ++++++++++- model/otel/registry.yaml | 5 +++++ 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/docs/otel/sdk-events.md b/docs/otel/sdk-events.md index 563f2af39d..56574291eb 100644 --- a/docs/otel/sdk-events.md +++ b/docs/otel/sdk-events.md @@ -75,7 +75,7 @@ event data defined by this convention is conveyed through attributes. **Severity.** -Implementations SHOULD set the log record severity to `WARN` +Implementations MUST set the log record severity to `WARN` (`SeverityNumber` = `13`) when `otel.component.shutdown.result` is not `success`, and to `INFO` (`SeverityNumber` = `9`) otherwise. @@ -93,6 +93,15 @@ abandoned). Consumers should treat a non-`success` `result` as "shutdown was not clean; some loss possible" and rely on per-operation signals for precise accounting. +**Nesting.** + +When an SDK component invokes the shutdown of a child component inline as +part of its own shutdown (e.g. a batching processor shutting down its +exporter), the parent's `otel.component.shutdown.duration` mechanically +includes the time spent shutting down its children. Consumers SHOULD NOT +sum `otel.component.shutdown.duration` across components in the same +pipeline to estimate total shutdown wall time. + **Attributes:** | Key | Stability | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Value Type | Description | Example Values | @@ -127,6 +136,11 @@ If no shutdown timeout/deadline applies to the component, implementations MUST NOT report `timed_out` unless the underlying shutdown API explicitly reports a timeout condition. +Implementations MUST set `otel.component.shutdown.result` to one of the +well-known values defined in this convention. The three values are intended +to be exhaustive: any shutdown attempt that did not complete cleanly is +either `failed` or `timed_out`. Custom values MUST NOT be used. + **[3] `otel.component.type`:** If none of the standardized values apply, implementations SHOULD use the language-defined name of the type. E.g. for Java the fully qualified classname SHOULD be used in this case. diff --git a/docs/registry/attributes/otel.md b/docs/registry/attributes/otel.md index d723214dc8..e325b12acd 100644 --- a/docs/registry/attributes/otel.md +++ b/docs/registry/attributes/otel.md @@ -96,6 +96,11 @@ If no shutdown timeout/deadline applies to the component, implementations MUST NOT report `timed_out` unless the underlying shutdown API explicitly reports a timeout condition. +Implementations MUST set `otel.component.shutdown.result` to one of the +well-known values defined in this convention. The three values are intended +to be exhaustive: any shutdown attempt that did not complete cleanly is +either `failed` or `timed_out`. Custom values MUST NOT be used. + **[4] `otel.component.type`:** If none of the standardized values apply, implementations SHOULD use the language-defined name of the type. E.g. for Java the fully qualified classname SHOULD be used in this case. diff --git a/model/otel/events.yaml b/model/otel/events.yaml index ba0dff75ff..2557b9fc95 100644 --- a/model/otel/events.yaml +++ b/model/otel/events.yaml @@ -45,7 +45,7 @@ groups: **Severity.** - Implementations SHOULD set the log record severity to `WARN` + Implementations MUST set the log record severity to `WARN` (`SeverityNumber` = `13`) when `otel.component.shutdown.result` is not `success`, and to `INFO` (`SeverityNumber` = `9`) otherwise. @@ -62,6 +62,15 @@ groups: abandoned). Consumers should treat a non-`success` `result` as "shutdown was not clean; some loss possible" and rely on per-operation signals for precise accounting. + + **Nesting.** + + When an SDK component invokes the shutdown of a child component inline as + part of its own shutdown (e.g. a batching processor shutting down its + exporter), the parent's `otel.component.shutdown.duration` mechanically + includes the time spent shutting down its children. Consumers SHOULD NOT + sum `otel.component.shutdown.duration` across components in the same + pipeline to estimate total shutdown wall time. attributes: - ref: otel.component.type requirement_level: required diff --git a/model/otel/registry.yaml b/model/otel/registry.yaml index 4da8679741..666e0aa1c2 100644 --- a/model/otel/registry.yaml +++ b/model/otel/registry.yaml @@ -240,6 +240,11 @@ groups: If no shutdown timeout/deadline applies to the component, implementations MUST NOT report `timed_out` unless the underlying shutdown API explicitly reports a timeout condition. + + Implementations MUST set `otel.component.shutdown.result` to one of the + well-known values defined in this convention. The three values are intended + to be exhaustive: any shutdown attempt that did not complete cleanly is + either `failed` or `timed_out`. Custom values MUST NOT be used. examples: ["success", "failed", "timed_out"] - id: otel.component.shutdown.duration type: double From 11f3a38e59e6ab8e3a0739d539fba28c2fb1dae4 Mon Sep 17 00:00:00 2001 From: cijothomas Date: Wed, 24 Jun 2026 13:32:42 +0530 Subject: [PATCH 20/24] Polish shutdown event: tighten prose, align with semconv patterns - Applicability: use SHOULD (aligns with other events in the repo) - Emission rules: declarative 'at most one per instance per lifetime' - Drop 'body SHOULD be omitted' (unnecessary) - Drop 'Relationship with error.type' section (design justification, not convention) - Drop 'SHOULD NOT sum durations' (implied by nesting sentence) - Intro: shorter, references metrics complementarity --- docs/otel/sdk-events.md | 46 ++++++++++++----------------------------- model/otel/events.yaml | 39 +++++++++------------------------- 2 files changed, 23 insertions(+), 62 deletions(-) diff --git a/docs/otel/sdk-events.md b/docs/otel/sdk-events.md index 56574291eb..d883e3a0b0 100644 --- a/docs/otel/sdk-events.md +++ b/docs/otel/sdk-events.md @@ -6,11 +6,10 @@ linkTitle: SDK Events **Status**: [Development][DocumentStatus] -This document describes events emitted by the OpenTelemetry SDK components themselves about their own lifecycle. +Self-observability events emitted by OpenTelemetry SDK components. -These events are intended for SDK self-observability and answer questions -that metrics cannot easily answer on their own, such as -"did my pipeline drain cleanly when the application was shutting down?". +These events complement SDK self-observability metrics by providing per-instance +confirmation of lifecycle transitions, such as whether shutdown completed cleanly. > [!NOTE] > Events are in-development and not yet available in some languages. Check the [spec-compliance matrix](https://github.com/open-telemetry/opentelemetry-specification/blob/main/spec-compliance-matrix.md#logs) to see the implementation status in the corresponding language. @@ -39,12 +38,12 @@ Indicates that an OpenTelemetry SDK component's shutdown attempt has ended, whet **Applicability.** -SDK implementations SHOULD emit an `otel.sdk.component.shutdown` event for each -SDK component instance that has an explicit `Shutdown` operation and that owns -telemetry processing, buffering, reading, or exporting state. -This includes span processors, log record processors, metric readers, span -exporters, log record exporters, and metric exporters, as well as custom -implementations of any of these categories. See the well-known values of +This event SHOULD be emitted by each SDK component instance that has an +explicit `Shutdown` operation and that owns telemetry processing, buffering, +reading, or exporting state. This includes span processors, log record +processors, metric readers, span exporters, log record exporters, and metric +exporters, as well as custom implementations of any of these categories. See +the well-known values of [`otel.component.type`](/docs/registry/attributes/otel.md) for the full list of built-in types. @@ -57,10 +56,8 @@ emerges. **Emission rules.** -An OpenTelemetry SDK component is shut down at most once. The event SHOULD be -emitted exactly once per component instance, reporting the result of that one -shutdown. Subsequent invocations of the shutdown API on a component that is -already shut down MUST NOT emit additional events. +At most one `otel.sdk.component.shutdown` event is emitted per component +instance per process lifetime, reporting the result of that one shutdown. If the process terminates without invoking the component's shutdown operation (e.g. a crash, `SIGKILL`, container eviction, or immediate process termination), @@ -70,8 +67,7 @@ evidence of a clean shutdown. The event timestamp SHOULD reflect the time at which the shutdown attempt ended (whether by completing, failing, or being abandoned). Combined with `otel.component.shutdown.duration`, the start of the shutdown attempt can be -reconstructed as `timestamp - duration`. The event body SHOULD be omitted; all -event data defined by this convention is conveyed through attributes. +reconstructed as `timestamp - duration`. **Severity.** @@ -79,28 +75,12 @@ Implementations MUST set the log record severity to `WARN` (`SeverityNumber` = `13`) when `otel.component.shutdown.result` is not `success`, and to `INFO` (`SeverityNumber` = `9`) otherwise. -**Relationship with `error.type` and per-operation drop accounting.** - -The reason a shutdown failed is intentionally not classified on this event -(there is no `error.type` attribute). Failure-cause classification and -lifetime/per-operation drop accounting are the responsibility of the -operation-level signals (e.g. `otel.sdk.exporter.*.exported` and -`otel.sdk.processor.*.processed` with `error.type`) emitted while the SDK -is still healthy. The exact count of telemetry items abandoned during a -`failed` or `timed_out` shutdown is often unknowable to the component -(e.g. items still in a worker thread's buffer at the moment shutdown is -abandoned). Consumers should treat a non-`success` `result` as -"shutdown was not clean; some loss possible" and rely on per-operation -signals for precise accounting. - **Nesting.** When an SDK component invokes the shutdown of a child component inline as part of its own shutdown (e.g. a batching processor shutting down its exporter), the parent's `otel.component.shutdown.duration` mechanically -includes the time spent shutting down its children. Consumers SHOULD NOT -sum `otel.component.shutdown.duration` across components in the same -pipeline to estimate total shutdown wall time. +includes the time spent shutting down its children. **Attributes:** diff --git a/model/otel/events.yaml b/model/otel/events.yaml index 2557b9fc95..6bba11a043 100644 --- a/model/otel/events.yaml +++ b/model/otel/events.yaml @@ -9,12 +9,12 @@ groups: note: | **Applicability.** - SDK implementations SHOULD emit an `otel.sdk.component.shutdown` event for each - SDK component instance that has an explicit `Shutdown` operation and that owns - telemetry processing, buffering, reading, or exporting state. - This includes span processors, log record processors, metric readers, span - exporters, log record exporters, and metric exporters, as well as custom - implementations of any of these categories. See the well-known values of + This event SHOULD be emitted by each SDK component instance that has an + explicit `Shutdown` operation and that owns telemetry processing, buffering, + reading, or exporting state. This includes span processors, log record + processors, metric readers, span exporters, log record exporters, and metric + exporters, as well as custom implementations of any of these categories. See + the well-known values of [`otel.component.type`](/docs/registry/attributes/otel.md) for the full list of built-in types. @@ -27,10 +27,8 @@ groups: **Emission rules.** - An OpenTelemetry SDK component is shut down at most once. The event SHOULD be - emitted exactly once per component instance, reporting the result of that one - shutdown. Subsequent invocations of the shutdown API on a component that is - already shut down MUST NOT emit additional events. + At most one `otel.sdk.component.shutdown` event is emitted per component + instance per process lifetime, reporting the result of that one shutdown. If the process terminates without invoking the component's shutdown operation (e.g. a crash, `SIGKILL`, container eviction, or immediate process termination), @@ -40,8 +38,7 @@ groups: The event timestamp SHOULD reflect the time at which the shutdown attempt ended (whether by completing, failing, or being abandoned). Combined with `otel.component.shutdown.duration`, the start of the shutdown attempt can be - reconstructed as `timestamp - duration`. The event body SHOULD be omitted; all - event data defined by this convention is conveyed through attributes. + reconstructed as `timestamp - duration`. **Severity.** @@ -49,28 +46,12 @@ groups: (`SeverityNumber` = `13`) when `otel.component.shutdown.result` is not `success`, and to `INFO` (`SeverityNumber` = `9`) otherwise. - **Relationship with `error.type` and per-operation drop accounting.** - - The reason a shutdown failed is intentionally not classified on this event - (there is no `error.type` attribute). Failure-cause classification and - lifetime/per-operation drop accounting are the responsibility of the - operation-level signals (e.g. `otel.sdk.exporter.*.exported` and - `otel.sdk.processor.*.processed` with `error.type`) emitted while the SDK - is still healthy. The exact count of telemetry items abandoned during a - `failed` or `timed_out` shutdown is often unknowable to the component - (e.g. items still in a worker thread's buffer at the moment shutdown is - abandoned). Consumers should treat a non-`success` `result` as - "shutdown was not clean; some loss possible" and rely on per-operation - signals for precise accounting. - **Nesting.** When an SDK component invokes the shutdown of a child component inline as part of its own shutdown (e.g. a batching processor shutting down its exporter), the parent's `otel.component.shutdown.duration` mechanically - includes the time spent shutting down its children. Consumers SHOULD NOT - sum `otel.component.shutdown.duration` across components in the same - pipeline to estimate total shutdown wall time. + includes the time spent shutting down its children. attributes: - ref: otel.component.type requirement_level: required From ebcff1972ceec0c81e2ecf2f94931c3e731ceed3 Mon Sep 17 00:00:00 2001 From: cijothomas Date: Fri, 26 Jun 2026 18:44:03 +0530 Subject: [PATCH 21/24] Pivot to provider-level shutdown event with error.type - Emit from providers (TracerProvider, LoggerProvider, MeterProvider) instead of per-component (processors, exporters). Simpler first step; per-component events can follow as DEBUG-level refinement. - Replace custom otel.component.shutdown.result enum with canonical error.type (absent = success, 'timeout' or 'failed' on failure). - Add logger_provider, tracer_provider, meter_provider to otel.component.type well-known values. - Remove otel.component.shutdown.result from registry (no longer needed). - Severity: INFO when no error.type, WARN when error.type present. Addresses review feedback from @lmolkova. --- docs/otel/sdk-events.md | 99 ++++++++++++-------------------- docs/otel/sdk-metrics.md | 42 ++++++++++++++ docs/registry/attributes/otel.md | 49 ++++------------ model/otel/events.yaml | 82 +++++++++++++------------- model/otel/registry.yaml | 64 ++++++--------------- 5 files changed, 150 insertions(+), 186 deletions(-) diff --git a/docs/otel/sdk-events.md b/docs/otel/sdk-events.md index d883e3a0b0..8a5d43618a 100644 --- a/docs/otel/sdk-events.md +++ b/docs/otel/sdk-events.md @@ -34,61 +34,43 @@ confirmation of lifecycle transitions, such as whether shutdown completed cleanl The event name MUST be `otel.sdk.component.shutdown`. -Indicates that an OpenTelemetry SDK component's shutdown attempt has ended, whether by completing successfully, failing, or being abandoned (e.g. on timeout). +Indicates that an OpenTelemetry SDK provider's shutdown attempt has ended, whether by completing successfully, failing, or timing out. **Applicability.** -This event SHOULD be emitted by each SDK component instance that has an -explicit `Shutdown` operation and that owns telemetry processing, buffering, -reading, or exporting state. This includes span processors, log record -processors, metric readers, span exporters, log record exporters, and metric -exporters, as well as custom implementations of any of these categories. See -the well-known values of -[`otel.component.type`](/docs/registry/attributes/otel.md) for the full list of -built-in types. - -Providers (e.g. `TracerProvider`, `LoggerProvider`, `MeterProvider`) are not -expected to emit this event. A provider's shutdown is already covered by the -events emitted by its child components, and a higher-level provider event would -carry no information beyond what those child events already convey. A future -revision of this convention may define provider-level shutdown events if a need -emerges. +This event SHOULD be emitted by each SDK provider instance +(`TracerProvider`, `LoggerProvider`, `MeterProvider`) when its shutdown +operation completes. **Emission rules.** -At most one `otel.sdk.component.shutdown` event is emitted per component -instance per process lifetime, reporting the result of that one shutdown. +At most one `otel.sdk.component.shutdown` event is emitted per provider +instance per process lifetime. -If the process terminates without invoking the component's shutdown operation -(e.g. a crash, `SIGKILL`, container eviction, or immediate process termination), -no event is expected. Consumers MUST NOT interpret the absence of this event as -evidence of a clean shutdown. +If the process terminates without invoking the provider's shutdown +(e.g. a crash, `SIGKILL`, container eviction, or immediate process +termination), no event is expected. Consumers MUST NOT interpret the +absence of this event as evidence of a clean shutdown. -The event timestamp SHOULD reflect the time at which the shutdown attempt ended -(whether by completing, failing, or being abandoned). Combined with -`otel.component.shutdown.duration`, the start of the shutdown attempt can be -reconstructed as `timestamp - duration`. +The event timestamp SHOULD reflect the time at which the provider fully +completed the shutdown process, including shutting down all child +components. Combined with the `otel.component.shutdown.duration` +attribute, the start of the shutdown attempt can be reconstructed as +`timestamp - duration`. **Severity.** Implementations MUST set the log record severity to `WARN` -(`SeverityNumber` = `13`) when `otel.component.shutdown.result` is not -`success`, and to `INFO` (`SeverityNumber` = `9`) otherwise. - -**Nesting.** - -When an SDK component invokes the shutdown of a child component inline as -part of its own shutdown (e.g. a batching processor shutting down its -exporter), the parent's `otel.component.shutdown.duration` mechanically -includes the time spent shutting down its children. +(`SeverityNumber` = `13`) when `error.type` is present, and to `INFO` +(`SeverityNumber` = `9`) otherwise. **Attributes:** | Key | Stability | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Value Type | Description | Example Values | | --- | --- | --- | --- | --- | --- | | [`otel.component.name`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | A name uniquely identifying the instance of the OpenTelemetry component within its containing SDK instance. [1] | `otlp_grpc_span_exporter/0`; `custom-name` | -| [`otel.component.shutdown.result`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | The result of an OpenTelemetry SDK component shutdown attempt. [2] | `success`; `failed`; `timed_out` | -| [`otel.component.type`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | A name identifying the type of the OpenTelemetry component. [3] | `batching_span_processor`; `com.example.MySpanExporter` | +| [`otel.component.type`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Required` | string | The provider type. [2] | `logger_provider`; `tracer_provider`; `meter_provider` | +| [`error.type`](/docs/registry/attributes/error.md) | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | `Conditionally Required` if the shutdown was not successful. | string | Describes the class of error that caused the shutdown to fail. [3] | `timeout`; `failed` | | [`otel.component.shutdown.duration`](/docs/registry/attributes/otel.md) | ![Development](https://img.shields.io/badge/-development-blue) | `Recommended` | double | The wall-clock elapsed time of the shutdown attempt, in seconds. Combined with the event timestamp, this lets consumers compute when the shutdown attempt started. [4] | `0.015`; `30.0` | **[1] `otel.component.name`:** Implementations SHOULD ensure a low cardinality for this attribute, even across application or SDK restarts. @@ -105,41 +87,31 @@ With this implementation, for example the first Batching Span Processor would ha as `otel.component.name`, the second one `batching_span_processor/1` and so on. These values will therefore be reused in the case of an application restart. -**[2] `otel.component.shutdown.result`:** `timed_out` takes precedence over `failed` when both are observed for the same -shutdown attempt (e.g. when an exporter request is abandoned because the -shutdown timeout expired). - -`success` MUST only be reported when the shutdown completed within the -configured time budget AND no required shutdown step reported a failure. - -If no shutdown timeout/deadline applies to the component, implementations MUST -NOT report `timed_out` unless the underlying shutdown API explicitly reports a -timeout condition. +**[2] `otel.component.type`:** If none of the standardized values apply, implementations SHOULD use the language-defined name of the type. +E.g. for Java the fully qualified classname SHOULD be used in this case. -Implementations MUST set `otel.component.shutdown.result` to one of the -well-known values defined in this convention. The three values are intended -to be exhaustive: any shutdown attempt that did not complete cleanly is -either `failed` or `timed_out`. Custom values MUST NOT be used. +**[3] `error.type`:** `timeout` takes precedence over `failed` when both conditions are +observed (e.g. the shutdown budget expired while a child component +was still flushing). -**[3] `otel.component.type`:** If none of the standardized values apply, implementations SHOULD use the language-defined name of the type. -E.g. for Java the fully qualified classname SHOULD be used in this case. +Documented values for this event: -**[4] `otel.component.shutdown.duration`:** Measured from the moment the component's shutdown operation started to the -moment the shutdown attempt ended (whether by completing, failing, or being -abandoned). MUST be a non-negative value expressed in seconds. +| Value | Description | +|---|---| +| `timeout` | The configured shutdown budget expired before all child components completed. | +| `failed` | One or more child components reported failure within the time budget. | -This attribute is informational and SHOULD NOT affect the severity of the -enclosing event. +**[4] `otel.component.shutdown.duration`:** Measured from the moment the shutdown operation started to the moment +it ended (whether by completing, failing, or timing out). MUST be a +non-negative value expressed in seconds. --- -`otel.component.shutdown.result` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. +`error.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. | Value | Description | Stability | | --- | --- | --- | -| `failed` | The shutdown attempt ended within the configured time budget but one or more required shutdown steps failed (e.g. an exporter rejected the final batch, or a cleanup step threw). | ![Development](https://img.shields.io/badge/-development-blue) | -| `success` | The shutdown attempt completed within the configured time budget and confirmed processing/delivery of all telemetry the component owned at the time shutdown was initiated. | ![Development](https://img.shields.io/badge/-development-blue) | -| `timed_out` | The shutdown attempt was abandoned because the configured shutdown timeout, deadline, or equivalent time budget expired. | ![Development](https://img.shields.io/badge/-development-blue) | +| `_OTHER` | A fallback error value to be used when the instrumentation doesn't define a custom value. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | --- @@ -149,6 +121,8 @@ enclosing event. | --- | --- | --- | | `batching_log_processor` | The builtin SDK batching log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `batching_span_processor` | The builtin SDK batching span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `logger_provider` | The builtin SDK LoggerProvider | ![Development](https://img.shields.io/badge/-development-blue) | +| `meter_provider` | The builtin SDK MeterProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_log_exporter` | OTLP log record exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_metric_exporter` | OTLP metric exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_span_exporter` | OTLP span exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | @@ -162,6 +136,7 @@ enclosing event. | `prometheus_http_text_metric_exporter` | Prometheus metric exporter over HTTP with the default text-based format | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_log_processor` | The builtin SDK simple log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_span_processor` | The builtin SDK simple span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `tracer_provider` | The builtin SDK TracerProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `zipkin_http_span_exporter` | Zipkin span exporter over HTTP | ![Development](https://img.shields.io/badge/-development-blue) | diff --git a/docs/otel/sdk-metrics.md b/docs/otel/sdk-metrics.md index 6d2b7594d5..14f5be92ea 100644 --- a/docs/otel/sdk-metrics.md +++ b/docs/otel/sdk-metrics.md @@ -164,6 +164,8 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. | --- | --- | --- | | `batching_log_processor` | The builtin SDK batching log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `batching_span_processor` | The builtin SDK batching span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `logger_provider` | The builtin SDK LoggerProvider | ![Development](https://img.shields.io/badge/-development-blue) | +| `meter_provider` | The builtin SDK MeterProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_log_exporter` | OTLP log record exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_metric_exporter` | OTLP metric exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_span_exporter` | OTLP span exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | @@ -177,6 +179,7 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. | `prometheus_http_text_metric_exporter` | Prometheus metric exporter over HTTP with the default text-based format | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_log_processor` | The builtin SDK simple log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_span_processor` | The builtin SDK simple span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `tracer_provider` | The builtin SDK TracerProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `zipkin_http_span_exporter` | Zipkin span exporter over HTTP | ![Development](https://img.shields.io/badge/-development-blue) | @@ -230,6 +233,8 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. | --- | --- | --- | | `batching_log_processor` | The builtin SDK batching log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `batching_span_processor` | The builtin SDK batching span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `logger_provider` | The builtin SDK LoggerProvider | ![Development](https://img.shields.io/badge/-development-blue) | +| `meter_provider` | The builtin SDK MeterProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_log_exporter` | OTLP log record exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_metric_exporter` | OTLP metric exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_span_exporter` | OTLP span exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | @@ -243,6 +248,7 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. | `prometheus_http_text_metric_exporter` | Prometheus metric exporter over HTTP with the default text-based format | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_log_processor` | The builtin SDK simple log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_span_processor` | The builtin SDK simple span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `tracer_provider` | The builtin SDK TracerProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `zipkin_http_span_exporter` | Zipkin span exporter over HTTP | ![Development](https://img.shields.io/badge/-development-blue) | @@ -334,6 +340,8 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. | --- | --- | --- | | `batching_log_processor` | The builtin SDK batching log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `batching_span_processor` | The builtin SDK batching span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `logger_provider` | The builtin SDK LoggerProvider | ![Development](https://img.shields.io/badge/-development-blue) | +| `meter_provider` | The builtin SDK MeterProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_log_exporter` | OTLP log record exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_metric_exporter` | OTLP metric exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_span_exporter` | OTLP span exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | @@ -347,6 +355,7 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. | `prometheus_http_text_metric_exporter` | Prometheus metric exporter over HTTP with the default text-based format | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_log_processor` | The builtin SDK simple log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_span_processor` | The builtin SDK simple span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `tracer_provider` | The builtin SDK TracerProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `zipkin_http_span_exporter` | Zipkin span exporter over HTTP | ![Development](https://img.shields.io/badge/-development-blue) | @@ -407,6 +416,8 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. | --- | --- | --- | | `batching_log_processor` | The builtin SDK batching log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `batching_span_processor` | The builtin SDK batching span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `logger_provider` | The builtin SDK LoggerProvider | ![Development](https://img.shields.io/badge/-development-blue) | +| `meter_provider` | The builtin SDK MeterProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_log_exporter` | OTLP log record exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_metric_exporter` | OTLP metric exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_span_exporter` | OTLP span exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | @@ -420,6 +431,7 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. | `prometheus_http_text_metric_exporter` | Prometheus metric exporter over HTTP with the default text-based format | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_log_processor` | The builtin SDK simple log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_span_processor` | The builtin SDK simple span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `tracer_provider` | The builtin SDK TracerProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `zipkin_http_span_exporter` | Zipkin span exporter over HTTP | ![Development](https://img.shields.io/badge/-development-blue) | @@ -519,6 +531,8 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. | --- | --- | --- | | `batching_log_processor` | The builtin SDK batching log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `batching_span_processor` | The builtin SDK batching span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `logger_provider` | The builtin SDK LoggerProvider | ![Development](https://img.shields.io/badge/-development-blue) | +| `meter_provider` | The builtin SDK MeterProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_log_exporter` | OTLP log record exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_metric_exporter` | OTLP metric exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_span_exporter` | OTLP span exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | @@ -532,6 +546,7 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. | `prometheus_http_text_metric_exporter` | Prometheus metric exporter over HTTP with the default text-based format | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_log_processor` | The builtin SDK simple log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_span_processor` | The builtin SDK simple span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `tracer_provider` | The builtin SDK TracerProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `zipkin_http_span_exporter` | Zipkin span exporter over HTTP | ![Development](https://img.shields.io/badge/-development-blue) | @@ -604,6 +619,8 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. | --- | --- | --- | | `batching_log_processor` | The builtin SDK batching log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `batching_span_processor` | The builtin SDK batching span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `logger_provider` | The builtin SDK LoggerProvider | ![Development](https://img.shields.io/badge/-development-blue) | +| `meter_provider` | The builtin SDK MeterProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_log_exporter` | OTLP log record exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_metric_exporter` | OTLP metric exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_span_exporter` | OTLP span exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | @@ -617,6 +634,7 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. | `prometheus_http_text_metric_exporter` | Prometheus metric exporter over HTTP with the default text-based format | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_log_processor` | The builtin SDK simple log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_span_processor` | The builtin SDK simple span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `tracer_provider` | The builtin SDK TracerProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `zipkin_http_span_exporter` | Zipkin span exporter over HTTP | ![Development](https://img.shields.io/badge/-development-blue) | @@ -670,6 +688,8 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. | --- | --- | --- | | `batching_log_processor` | The builtin SDK batching log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `batching_span_processor` | The builtin SDK batching span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `logger_provider` | The builtin SDK LoggerProvider | ![Development](https://img.shields.io/badge/-development-blue) | +| `meter_provider` | The builtin SDK MeterProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_log_exporter` | OTLP log record exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_metric_exporter` | OTLP metric exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_span_exporter` | OTLP span exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | @@ -683,6 +703,7 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. | `prometheus_http_text_metric_exporter` | Prometheus metric exporter over HTTP with the default text-based format | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_log_processor` | The builtin SDK simple log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_span_processor` | The builtin SDK simple span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `tracer_provider` | The builtin SDK TracerProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `zipkin_http_span_exporter` | Zipkin span exporter over HTTP | ![Development](https://img.shields.io/badge/-development-blue) | @@ -775,6 +796,8 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. | --- | --- | --- | | `batching_log_processor` | The builtin SDK batching log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `batching_span_processor` | The builtin SDK batching span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `logger_provider` | The builtin SDK LoggerProvider | ![Development](https://img.shields.io/badge/-development-blue) | +| `meter_provider` | The builtin SDK MeterProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_log_exporter` | OTLP log record exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_metric_exporter` | OTLP metric exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_span_exporter` | OTLP span exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | @@ -788,6 +811,7 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. | `prometheus_http_text_metric_exporter` | Prometheus metric exporter over HTTP with the default text-based format | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_log_processor` | The builtin SDK simple log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_span_processor` | The builtin SDK simple span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `tracer_provider` | The builtin SDK TracerProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `zipkin_http_span_exporter` | Zipkin span exporter over HTTP | ![Development](https://img.shields.io/badge/-development-blue) | @@ -848,6 +872,8 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. | --- | --- | --- | | `batching_log_processor` | The builtin SDK batching log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `batching_span_processor` | The builtin SDK batching span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `logger_provider` | The builtin SDK LoggerProvider | ![Development](https://img.shields.io/badge/-development-blue) | +| `meter_provider` | The builtin SDK MeterProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_log_exporter` | OTLP log record exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_metric_exporter` | OTLP metric exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_span_exporter` | OTLP span exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | @@ -861,6 +887,7 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. | `prometheus_http_text_metric_exporter` | Prometheus metric exporter over HTTP with the default text-based format | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_log_processor` | The builtin SDK simple log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_span_processor` | The builtin SDK simple span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `tracer_provider` | The builtin SDK TracerProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `zipkin_http_span_exporter` | Zipkin span exporter over HTTP | ![Development](https://img.shields.io/badge/-development-blue) | @@ -960,6 +987,8 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. | --- | --- | --- | | `batching_log_processor` | The builtin SDK batching log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `batching_span_processor` | The builtin SDK batching span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `logger_provider` | The builtin SDK LoggerProvider | ![Development](https://img.shields.io/badge/-development-blue) | +| `meter_provider` | The builtin SDK MeterProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_log_exporter` | OTLP log record exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_metric_exporter` | OTLP metric exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_span_exporter` | OTLP span exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | @@ -973,6 +1002,7 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. | `prometheus_http_text_metric_exporter` | Prometheus metric exporter over HTTP with the default text-based format | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_log_processor` | The builtin SDK simple log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_span_processor` | The builtin SDK simple span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `tracer_provider` | The builtin SDK TracerProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `zipkin_http_span_exporter` | Zipkin span exporter over HTTP | ![Development](https://img.shields.io/badge/-development-blue) | @@ -1035,6 +1065,8 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. | --- | --- | --- | | `batching_log_processor` | The builtin SDK batching log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `batching_span_processor` | The builtin SDK batching span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `logger_provider` | The builtin SDK LoggerProvider | ![Development](https://img.shields.io/badge/-development-blue) | +| `meter_provider` | The builtin SDK MeterProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_log_exporter` | OTLP log record exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_metric_exporter` | OTLP metric exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_span_exporter` | OTLP span exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | @@ -1048,6 +1080,7 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. | `prometheus_http_text_metric_exporter` | Prometheus metric exporter over HTTP with the default text-based format | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_log_processor` | The builtin SDK simple log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_span_processor` | The builtin SDK simple span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `tracer_provider` | The builtin SDK TracerProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `zipkin_http_span_exporter` | Zipkin span exporter over HTTP | ![Development](https://img.shields.io/badge/-development-blue) | @@ -1147,6 +1180,8 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. | --- | --- | --- | | `batching_log_processor` | The builtin SDK batching log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `batching_span_processor` | The builtin SDK batching span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `logger_provider` | The builtin SDK LoggerProvider | ![Development](https://img.shields.io/badge/-development-blue) | +| `meter_provider` | The builtin SDK MeterProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_log_exporter` | OTLP log record exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_metric_exporter` | OTLP metric exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_span_exporter` | OTLP span exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | @@ -1160,6 +1195,7 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. | `prometheus_http_text_metric_exporter` | Prometheus metric exporter over HTTP with the default text-based format | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_log_processor` | The builtin SDK simple log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_span_processor` | The builtin SDK simple span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `tracer_provider` | The builtin SDK TracerProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `zipkin_http_span_exporter` | Zipkin span exporter over HTTP | ![Development](https://img.shields.io/badge/-development-blue) | @@ -1253,6 +1289,8 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. | --- | --- | --- | | `batching_log_processor` | The builtin SDK batching log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `batching_span_processor` | The builtin SDK batching span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `logger_provider` | The builtin SDK LoggerProvider | ![Development](https://img.shields.io/badge/-development-blue) | +| `meter_provider` | The builtin SDK MeterProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_log_exporter` | OTLP log record exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_metric_exporter` | OTLP metric exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_span_exporter` | OTLP span exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | @@ -1266,6 +1304,7 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. | `prometheus_http_text_metric_exporter` | Prometheus metric exporter over HTTP with the default text-based format | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_log_processor` | The builtin SDK simple log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_span_processor` | The builtin SDK simple span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `tracer_provider` | The builtin SDK TracerProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `zipkin_http_span_exporter` | Zipkin span exporter over HTTP | ![Development](https://img.shields.io/badge/-development-blue) | @@ -1372,6 +1411,8 @@ Semantic conventions for individual RPC frameworks SHOULD document what `rpc.res | --- | --- | --- | | `batching_log_processor` | The builtin SDK batching log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `batching_span_processor` | The builtin SDK batching span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `logger_provider` | The builtin SDK LoggerProvider | ![Development](https://img.shields.io/badge/-development-blue) | +| `meter_provider` | The builtin SDK MeterProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_log_exporter` | OTLP log record exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_metric_exporter` | OTLP metric exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_span_exporter` | OTLP span exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | @@ -1385,6 +1426,7 @@ Semantic conventions for individual RPC frameworks SHOULD document what `rpc.res | `prometheus_http_text_metric_exporter` | Prometheus metric exporter over HTTP with the default text-based format | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_log_processor` | The builtin SDK simple log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_span_processor` | The builtin SDK simple span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `tracer_provider` | The builtin SDK TracerProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `zipkin_http_span_exporter` | Zipkin span exporter over HTTP | ![Development](https://img.shields.io/badge/-development-blue) | diff --git a/docs/registry/attributes/otel.md b/docs/registry/attributes/otel.md index e325b12acd..287d1fb2ae 100644 --- a/docs/registry/attributes/otel.md +++ b/docs/registry/attributes/otel.md @@ -60,9 +60,8 @@ Attributes used for OpenTelemetry component self-monitoring | Key | Stability | Value Type | Description | Example Values | | --- | --- | --- | --- | --- | | `otel.component.name` | ![Development](https://img.shields.io/badge/-development-blue) | string | A name uniquely identifying the instance of the OpenTelemetry component within its containing SDK instance. [1] | `otlp_grpc_span_exporter/0`; `custom-name` | -| `otel.component.shutdown.duration` | ![Development](https://img.shields.io/badge/-development-blue) | double | The wall-clock elapsed time of the component's shutdown attempt, in seconds. [2] | `0.015`; `30.0` | -| `otel.component.shutdown.result` | ![Development](https://img.shields.io/badge/-development-blue) | string | The result of an OpenTelemetry SDK component shutdown attempt. [3] | `success`; `failed`; `timed_out` | -| `otel.component.type` | ![Development](https://img.shields.io/badge/-development-blue) | string | A name identifying the type of the OpenTelemetry component. [4] | `batching_span_processor`; `com.example.MySpanExporter` | +| `otel.component.shutdown.duration` | ![Development](https://img.shields.io/badge/-development-blue) | double | The wall-clock elapsed time of a shutdown attempt, in seconds. [2] | `0.015`; `30.0` | +| `otel.component.type` | ![Development](https://img.shields.io/badge/-development-blue) | string | A name identifying the type of the OpenTelemetry component. [3] | `batching_span_processor`; `com.example.MySpanExporter` | **[1] `otel.component.name`:** Implementations SHOULD ensure a low cardinality for this attribute, even across application or SDK restarts. E.g. implementations MUST NOT use UUIDs as values for this attribute. @@ -78,50 +77,23 @@ With this implementation, for example the first Batching Span Processor would ha as `otel.component.name`, the second one `batching_span_processor/1` and so on. These values will therefore be reused in the case of an application restart. -**[2] `otel.component.shutdown.duration`:** Measured from the moment the component's shutdown operation started to the -moment the shutdown attempt ended (whether by completing, failing, or being -abandoned). MUST be a non-negative value expressed in seconds. +**[2] `otel.component.shutdown.duration`:** Measured from the moment the shutdown operation started to the moment +it ended (whether by completing, failing, or timing out). MUST be a +non-negative value expressed in seconds. -This attribute is informational and SHOULD NOT affect the severity of the -enclosing event. - -**[3] `otel.component.shutdown.result`:** `timed_out` takes precedence over `failed` when both are observed for the same -shutdown attempt (e.g. when an exporter request is abandoned because the -shutdown timeout expired). - -`success` MUST only be reported when the shutdown completed within the -configured time budget AND no required shutdown step reported a failure. - -If no shutdown timeout/deadline applies to the component, implementations MUST -NOT report `timed_out` unless the underlying shutdown API explicitly reports a -timeout condition. - -Implementations MUST set `otel.component.shutdown.result` to one of the -well-known values defined in this convention. The three values are intended -to be exhaustive: any shutdown attempt that did not complete cleanly is -either `failed` or `timed_out`. Custom values MUST NOT be used. - -**[4] `otel.component.type`:** If none of the standardized values apply, implementations SHOULD use the language-defined name of the type. +**[3] `otel.component.type`:** If none of the standardized values apply, implementations SHOULD use the language-defined name of the type. E.g. for Java the fully qualified classname SHOULD be used in this case. --- -`otel.component.shutdown.result` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. - -| Value | Description | Stability | -| --- | --- | --- | -| `failed` | The shutdown attempt ended within the configured time budget but one or more required shutdown steps failed (e.g. an exporter rejected the final batch, or a cleanup step threw). | ![Development](https://img.shields.io/badge/-development-blue) | -| `success` | The shutdown attempt completed within the configured time budget and confirmed processing/delivery of all telemetry the component owned at the time shutdown was initiated. | ![Development](https://img.shields.io/badge/-development-blue) | -| `timed_out` | The shutdown attempt was abandoned because the configured shutdown timeout, deadline, or equivalent time budget expired. | ![Development](https://img.shields.io/badge/-development-blue) | - ---- - `otel.component.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. | Value | Description | Stability | | --- | --- | --- | | `batching_log_processor` | The builtin SDK batching log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `batching_span_processor` | The builtin SDK batching span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `logger_provider` | The builtin SDK LoggerProvider | ![Development](https://img.shields.io/badge/-development-blue) | +| `meter_provider` | The builtin SDK MeterProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_log_exporter` | OTLP log record exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_metric_exporter` | OTLP metric exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | | `otlp_grpc_span_exporter` | OTLP span exporter over gRPC with protobuf serialization | ![Development](https://img.shields.io/badge/-development-blue) | @@ -135,6 +107,7 @@ E.g. for Java the fully qualified classname SHOULD be used in this case. | `prometheus_http_text_metric_exporter` | Prometheus metric exporter over HTTP with the default text-based format | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_log_processor` | The builtin SDK simple log record processor | ![Development](https://img.shields.io/badge/-development-blue) | | `simple_span_processor` | The builtin SDK simple span processor | ![Development](https://img.shields.io/badge/-development-blue) | +| `tracer_provider` | The builtin SDK TracerProvider | ![Development](https://img.shields.io/badge/-development-blue) | | `zipkin_http_span_exporter` | Zipkin span exporter over HTTP | ![Development](https://img.shields.io/badge/-development-blue) | ## OTel Event Attributes @@ -145,9 +118,9 @@ Attributes used by non-OTLP exporters to represent OpenTelemetry Event's concept | Key | Stability | Value Type | Description | Example Values | | --- | --- | --- | --- | --- | -| `otel.event.name` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | string | Identifies the class / type of event. [5] | `browser.mouse.click`; `device.app.lifecycle` | +| `otel.event.name` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | string | Identifies the class / type of event. [4] | `browser.mouse.click`; `device.app.lifecycle` | -**[5] `otel.event.name`:** This attribute SHOULD be used by non-OTLP exporters when destination does not support `EventName` or equivalent field. This attribute MAY be used by applications using existing logging libraries so that it can be used to set the `EventName` field by Collector or SDK components. +**[4] `otel.event.name`:** This attribute SHOULD be used by non-OTLP exporters when destination does not support `EventName` or equivalent field. This attribute MAY be used by applications using existing logging libraries so that it can be used to set the `EventName` field by Collector or SDK components. ## OTel Scope Attributes diff --git a/model/otel/events.yaml b/model/otel/events.yaml index 6bba11a043..924938e631 100644 --- a/model/otel/events.yaml +++ b/model/otel/events.yaml @@ -4,64 +4,64 @@ groups: name: otel.sdk.component.shutdown stability: development brief: > - Indicates that an OpenTelemetry SDK component's shutdown attempt has ended, - whether by completing successfully, failing, or being abandoned (e.g. on timeout). + Indicates that an OpenTelemetry SDK provider's shutdown attempt has ended, + whether by completing successfully, failing, or timing out. note: | **Applicability.** - This event SHOULD be emitted by each SDK component instance that has an - explicit `Shutdown` operation and that owns telemetry processing, buffering, - reading, or exporting state. This includes span processors, log record - processors, metric readers, span exporters, log record exporters, and metric - exporters, as well as custom implementations of any of these categories. See - the well-known values of - [`otel.component.type`](/docs/registry/attributes/otel.md) for the full list of - built-in types. - - Providers (e.g. `TracerProvider`, `LoggerProvider`, `MeterProvider`) are not - expected to emit this event. A provider's shutdown is already covered by the - events emitted by its child components, and a higher-level provider event would - carry no information beyond what those child events already convey. A future - revision of this convention may define provider-level shutdown events if a need - emerges. + This event SHOULD be emitted by each SDK provider instance + (`TracerProvider`, `LoggerProvider`, `MeterProvider`) when its shutdown + operation completes. **Emission rules.** - At most one `otel.sdk.component.shutdown` event is emitted per component - instance per process lifetime, reporting the result of that one shutdown. + At most one `otel.sdk.component.shutdown` event is emitted per provider + instance per process lifetime. - If the process terminates without invoking the component's shutdown operation - (e.g. a crash, `SIGKILL`, container eviction, or immediate process termination), - no event is expected. Consumers MUST NOT interpret the absence of this event as - evidence of a clean shutdown. + If the process terminates without invoking the provider's shutdown + (e.g. a crash, `SIGKILL`, container eviction, or immediate process + termination), no event is expected. Consumers MUST NOT interpret the + absence of this event as evidence of a clean shutdown. - The event timestamp SHOULD reflect the time at which the shutdown attempt ended - (whether by completing, failing, or being abandoned). Combined with - `otel.component.shutdown.duration`, the start of the shutdown attempt can be - reconstructed as `timestamp - duration`. + The event timestamp SHOULD reflect the time at which the provider fully + completed the shutdown process, including shutting down all child + components. Combined with the `otel.component.shutdown.duration` + attribute, the start of the shutdown attempt can be reconstructed as + `timestamp - duration`. **Severity.** Implementations MUST set the log record severity to `WARN` - (`SeverityNumber` = `13`) when `otel.component.shutdown.result` is not - `success`, and to `INFO` (`SeverityNumber` = `9`) otherwise. - - **Nesting.** - - When an SDK component invokes the shutdown of a child component inline as - part of its own shutdown (e.g. a batching processor shutting down its - exporter), the parent's `otel.component.shutdown.duration` mechanically - includes the time spent shutting down its children. + (`SeverityNumber` = `13`) when `error.type` is present, and to `INFO` + (`SeverityNumber` = `9`) otherwise. attributes: - ref: otel.component.type requirement_level: required + brief: > + The provider type. + examples: ["logger_provider", "tracer_provider", "meter_provider"] - ref: otel.component.name requirement_level: required - - ref: otel.component.shutdown.result - requirement_level: required + - ref: error.type + requirement_level: + conditionally_required: if the shutdown was not successful. + brief: > + Describes the class of error that caused the shutdown to fail. + note: | + `timeout` takes precedence over `failed` when both conditions are + observed (e.g. the shutdown budget expired while a child component + was still flushing). + + Documented values for this event: + + | Value | Description | + |---|---| + | `timeout` | The configured shutdown budget expired before all child components completed. | + | `failed` | One or more child components reported failure within the time budget. | + examples: ["timeout", "failed"] - ref: otel.component.shutdown.duration requirement_level: recommended brief: > - The wall-clock elapsed time of the shutdown attempt, in seconds. Combined with - the event timestamp, this lets consumers compute when the shutdown attempt - started. + The wall-clock elapsed time of the shutdown attempt, in seconds. + Combined with the event timestamp, this lets consumers compute when + the shutdown attempt started. diff --git a/model/otel/registry.yaml b/model/otel/registry.yaml index 666e0aa1c2..d791a98cc7 100644 --- a/model/otel/registry.yaml +++ b/model/otel/registry.yaml @@ -181,6 +181,21 @@ groups: brief: > Prometheus metric exporter over HTTP with the default text-based format stability: development + - id: logger_provider + value: "logger_provider" + brief: > + The builtin SDK LoggerProvider + stability: development + - id: tracer_provider + value: "tracer_provider" + brief: > + The builtin SDK TracerProvider + stability: development + - id: meter_provider + value: "meter_provider" + brief: > + The builtin SDK MeterProvider + stability: development stability: development brief: > A name identifying the type of the OpenTelemetry component. @@ -208,54 +223,13 @@ groups: as `otel.component.name`, the second one `batching_span_processor/1` and so on. These values will therefore be reused in the case of an application restart. examples: ["otlp_grpc_span_exporter/0", "custom-name"] - - id: otel.component.shutdown.result - type: - members: - - id: success - value: "success" - brief: > - The shutdown attempt completed within the configured time budget and confirmed processing/delivery of all telemetry the component owned at the time shutdown was initiated. - stability: development - - id: failed - value: "failed" - brief: > - The shutdown attempt ended within the configured time budget but one or more required shutdown steps failed (e.g. an exporter rejected the final batch, or a cleanup step threw). - stability: development - - id: timed_out - value: "timed_out" - brief: > - The shutdown attempt was abandoned because the configured shutdown timeout, deadline, or equivalent time budget expired. - stability: development - stability: development - brief: > - The result of an OpenTelemetry SDK component shutdown attempt. - note: | - `timed_out` takes precedence over `failed` when both are observed for the same - shutdown attempt (e.g. when an exporter request is abandoned because the - shutdown timeout expired). - - `success` MUST only be reported when the shutdown completed within the - configured time budget AND no required shutdown step reported a failure. - - If no shutdown timeout/deadline applies to the component, implementations MUST - NOT report `timed_out` unless the underlying shutdown API explicitly reports a - timeout condition. - - Implementations MUST set `otel.component.shutdown.result` to one of the - well-known values defined in this convention. The three values are intended - to be exhaustive: any shutdown attempt that did not complete cleanly is - either `failed` or `timed_out`. Custom values MUST NOT be used. - examples: ["success", "failed", "timed_out"] - id: otel.component.shutdown.duration type: double stability: development brief: > - The wall-clock elapsed time of the component's shutdown attempt, in seconds. + The wall-clock elapsed time of a shutdown attempt, in seconds. note: | - Measured from the moment the component's shutdown operation started to the - moment the shutdown attempt ended (whether by completing, failing, or being - abandoned). MUST be a non-negative value expressed in seconds. - - This attribute is informational and SHOULD NOT affect the severity of the - enclosing event. + Measured from the moment the shutdown operation started to the moment + it ended (whether by completing, failing, or timing out). MUST be a + non-negative value expressed in seconds. examples: [0.015, 30.0] From de366f222659cc3a9c2ead3d96a04a83de405866 Mon Sep 17 00:00:00 2001 From: cijothomas Date: Fri, 26 Jun 2026 20:07:38 +0530 Subject: [PATCH 22/24] fix: markdownlint table spacing in error.type note --- docs/otel/sdk-events.md | 2 +- model/otel/events.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/otel/sdk-events.md b/docs/otel/sdk-events.md index 8a5d43618a..f7d2a985ee 100644 --- a/docs/otel/sdk-events.md +++ b/docs/otel/sdk-events.md @@ -97,7 +97,7 @@ was still flushing). Documented values for this event: | Value | Description | -|---|---| +| --- | --- | | `timeout` | The configured shutdown budget expired before all child components completed. | | `failed` | One or more child components reported failure within the time budget. | diff --git a/model/otel/events.yaml b/model/otel/events.yaml index 924938e631..ca34535743 100644 --- a/model/otel/events.yaml +++ b/model/otel/events.yaml @@ -55,7 +55,7 @@ groups: Documented values for this event: | Value | Description | - |---|---| + | --- | --- | | `timeout` | The configured shutdown budget expired before all child components completed. | | `failed` | One or more child components reported failure within the time budget. | examples: ["timeout", "failed"] From e043777c1a0b13ae80631bf24e1904346b5886f9 Mon Sep 17 00:00:00 2001 From: cijothomas Date: Fri, 26 Jun 2026 21:50:23 +0530 Subject: [PATCH 23/24] fix: make event brief generic (component, not provider-specific) --- docs/otel/sdk-events.md | 2 +- model/otel/events.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/otel/sdk-events.md b/docs/otel/sdk-events.md index f7d2a985ee..4110abef1e 100644 --- a/docs/otel/sdk-events.md +++ b/docs/otel/sdk-events.md @@ -34,7 +34,7 @@ confirmation of lifecycle transitions, such as whether shutdown completed cleanl The event name MUST be `otel.sdk.component.shutdown`. -Indicates that an OpenTelemetry SDK provider's shutdown attempt has ended, whether by completing successfully, failing, or timing out. +Indicates that an OpenTelemetry SDK component's shutdown attempt has ended, whether by completing successfully, failing, or timing out. **Applicability.** diff --git a/model/otel/events.yaml b/model/otel/events.yaml index ca34535743..82f63093e9 100644 --- a/model/otel/events.yaml +++ b/model/otel/events.yaml @@ -4,7 +4,7 @@ groups: name: otel.sdk.component.shutdown stability: development brief: > - Indicates that an OpenTelemetry SDK provider's shutdown attempt has ended, + Indicates that an OpenTelemetry SDK component's shutdown attempt has ended, whether by completing successfully, failing, or timing out. note: | **Applicability.** From 5a8f9505216b563c1398a9f8c35aec3c37142009 Mon Sep 17 00:00:00 2001 From: cijothomas Date: Thu, 2 Jul 2026 09:28:48 +0530 Subject: [PATCH 24/24] fix: remove stale per-component examples from closing paragraph --- docs/otel/sdk-events.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/otel/sdk-events.md b/docs/otel/sdk-events.md index 4110abef1e..e3c9ac3237 100644 --- a/docs/otel/sdk-events.md +++ b/docs/otel/sdk-events.md @@ -145,7 +145,7 @@ non-negative value expressed in seconds. The component being shut down is identified by the existing [`otel.component.*`](/docs/registry/attributes/otel.md#otel-component-attributes) attributes, -not encoded in the event name. This keeps the event name stable across all SDK component types -(span processors, log processors, metric readers, exporters, etc.). +not encoded in the event name. This keeps the event name stable and reusable +as the set of emitting components grows. [DocumentStatus]: https://opentelemetry.io/docs/specs/otel/document-status