Skip to content

Add otel.sdk.component.shutdown self-observability event#3723

Open
cijothomas wants to merge 25 commits into
open-telemetry:mainfrom
cijothomas:cijothomas/sdk-component-shutdown-event
Open

Add otel.sdk.component.shutdown self-observability event#3723
cijothomas wants to merge 25 commits into
open-telemetry:mainfrom
cijothomas:cijothomas/sdk-component-shutdown-event

Conversation

@cijothomas

@cijothomas cijothomas commented May 15, 2026

Copy link
Copy Markdown
Member

Resolves #3718.

Adds otel.sdk.component.shutdown -- a self-observability event emitted once per SDK provider instance when its shutdown attempt completes. Validated via POC implementations in Rust and .NET.

Event shape

Attribute Req Notes
otel.component.type required logger_provider / tracer_provider / meter_provider
otel.component.name required e.g. logger_provider/0
error.type conditionally required (if shutdown not successful) timeout or failed
otel.component.shutdown.duration recommended Wall-clock seconds (total, includes child components)

Severity: INFO when successful (no error.type), WARN when failed (error.type present).

Design decisions

Provider-level, not per-component. One event per provider gives operators a single "did my pipeline shut down cleanly?" signal at INFO level. Per-component detail (processors, exporters) can follow in a future PR if operators need more granularity.

error.type for failure classification. Uses the canonical semconv pattern: absence = success, presence = failure class. Operators already know how to alert on error.type IS NOT NULL across HTTP, DB, messaging -- this event gets that for free.

Event, not span. The shutdown event flows through the logging pipeline, not the tracing pipeline. TracerProvider is typically shut down first; emitting a span through a TracerProvider that is itself shutting down creates ordering problems.

Deferred from the original proposal (#3718)

Dropped count -- unknowable on timeout; per-operation metrics (otel.sdk.processor.*.processed{error.type=queue_full}) provide continuous accounting.

Per-component events -- can be added in a follow-up if operators need to know which specific processor/exporter failed.

@github-actions github-actions Bot added enhancement New feature or request area:otel labels May 15, 2026
Comment thread model/otel/registry.yaml Outdated
Comment thread model/otel/registry.yaml Outdated
@github-actions

github-actions Bot commented Jun 1, 2026

Copy link
Copy Markdown

This PR has been labeled as stale due to lack of activity. It will be automatically closed if there is no further activity over the next 7 days.

@github-actions github-actions Bot added the Stale label Jun 1, 2026
cijothomas added a commit to cijothomas/semantic-conventions that referenced this pull request Jun 5, 2026
Per open-telemetry#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 open-telemetry#3723.
@cijothomas
cijothomas force-pushed the cijothomas/sdk-component-shutdown-event branch from 7b0c6d8 to 2330b52 Compare June 5, 2026 20:45
cijothomas added a commit to cijothomas/semantic-conventions that referenced this pull request Jun 5, 2026
The '_count' suffix is redundant for an int attribute named 'dropped'.
Aligns with @thompson-tomo review feedback on open-telemetry#3723.
@github-actions github-actions Bot removed the Stale label Jun 6, 2026
cijothomas added 15 commits June 8, 2026 17:44
Per open-telemetry#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 open-telemetry#3723.
The '_count' suffix is redundant for an int attribute named 'dropped'.
Aligns with @thompson-tomo review feedback on open-telemetry#3723.
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.
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).
@cijothomas
cijothomas force-pushed the cijothomas/sdk-component-shutdown-event branch from 8cf502d to ee52ee7 Compare June 9, 2026 00:44
- 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

@Dipanshusinghh Dipanshusinghh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two things worth fixing:

  1. [BLOCKER] TonicLogsClient maps all errors to failed
    timed_out case is missing. Match on OTelSdkError::Timeout(_)
    like BatchLogProcessor does, otherwise the POC doesn't fully
    validate the spec.

  2. [NIT] cfg_attr on component_name will need manual update
    when a third feature uses it. Allocating it always is simpler.

Rest looks good for a POC.

@cijothomas

Copy link
Copy Markdown
Member Author

Two things worth fixing:

  1. [BLOCKER] TonicLogsClient maps all errors to failed
    timed_out case is missing. Match on OTelSdkError::Timeout(_)
    like BatchLogProcessor does, otherwise the POC doesn't fully
    validate the spec.
  2. [NIT] cfg_attr on component_name will need manual update
    when a third feature uses it. Allocating it always is simpler.

Rest looks good for a POC.

In case of OTel Rust, timeout is not respected today, so it won't ever produce timed_out. Once OTel Rust is fixed, it can be addressed.

@lmolkova lmolkova left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Look great! the only important comment I have is adding error.type instead of result attribute.

[UPDATE] Added another comment on modeling it as a span

Comment thread docs/otel/sdk-events.md Outdated
Comment thread docs/otel/sdk-events.md Outdated
Comment thread docs/otel/sdk-events.md Outdated
Comment thread model/otel/events.yaml Outdated
Comment thread model/otel/events.yaml Outdated
Comment thread model/otel/events.yaml Outdated
Comment thread model/otel/events.yaml
@cijothomas

cijothomas commented Jun 26, 2026

Copy link
Copy Markdown
Member Author

Thanks for the thorough review!

Thinking about the severity/granularity feedback -- would it be simpler to start with a provider-level event (one per TracerProvider/LoggerProvider/MeterProvider) and expand to per-component events later based on need? That way the event is naturally INFO (it's the summary signal), avoids the nesting complexity, and per-component detail can follow as a DEBUG-level refinement if operators ask for it.

On modeling as a span: I chose an event specifically so it flows through the logging pipeline, not the tracing pipeline. The inevitable shutdown ordering makes it challenging to ensure a shutdown-span can flow -- TracerProvider is typically the first to be shut down, and logging the last.

Thoughts?

Edit: After another round of analysis, I am inclined to start with provider-level Event to begin with. Will update the PR with that shortly. Marking draft temporarily.
Edit2: This is done, and ready for another review. POCs updated to match the new Event.

@cijothomas
cijothomas marked this pull request as draft June 26, 2026 13:07
- 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.
@cijothomas
cijothomas marked this pull request as ready for review June 26, 2026 14:47
@cijothomas

Copy link
Copy Markdown
Member Author

@open-telemetry/semconv-sdk-health-approvers Could you take a look ? This is the first Event we are attempting for SDK's own self-observability and and want to get the direction agreed by all, so that subsequent Event additions would be relatively smooth.

I've POCs linked, and plan to update OTel-Demo project to also showcase this.

@github-actions

Copy link
Copy Markdown

This PR has been labeled as stale due to lack of activity. It will be automatically closed if there is no further activity over the next 7 days.

@github-actions github-actions Bot added the Stale label Jul 16, 2026
@cijothomas

Copy link
Copy Markdown
Member Author

This PR has been labeled as stale due to lack of activity. It will be automatically closed if there is no further activity over the next 7 days.

Not stale. Waiting for reviews only.

@github-actions github-actions Bot removed the Stale label Jul 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:otel enhancement New feature or request

Projects

Status: In progress

Development

Successfully merging this pull request may close these issues.

Define a self-observability Event for SDK component shutdown (starting with BatchSpanProcessor)

4 participants