Add OTEL_SEMCONV_EXCEPTION_SIGNAL_OPT_IN support to record_exception#5323
Add OTEL_SEMCONV_EXCEPTION_SIGNAL_OPT_IN support to record_exception#5323RKest wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Pull request overview
Adds opt-in support for recording exceptions as logs (and optionally duplicating to span events) in the SDK’s Span.record_exception, enabling migration away from span events per the exception-as-logs semantic conventions and the span-event deprecation plan.
Changes:
- Update
Span.record_exceptionto honorOTEL_SEMCONV_EXCEPTION_SIGNAL_OPT_INand emit an exceptionLogRecordcorrelated with the span when configured. - Add end-to-end unit tests covering unset/unrecognized/logs/logs-dup behaviors, correlation, scope usage, and attribute mapping.
- Add a changelog entry documenting the new opt-in behavior.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| opentelemetry-sdk/src/opentelemetry/sdk/trace/init.py | Adds env-var gated branching in record_exception and a helper to emit correlated exception logs. |
| opentelemetry-sdk/tests/trace/test_record_exception_logs.py | New tests validating exception-as-logs behavior across all opt-in modes. |
| .changelog/5318.added | Notes the new env-var controlled behavior for Span.record_exception. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
828822d to
e039edd
Compare
`Span.record_exception` now honors the `OTEL_SEMCONV_EXCEPTION_SIGNAL_OPT_IN` environment variable, per the semantic conventions for exceptions in logs (https://opentelemetry.io/docs/specs/semconv/exceptions/exceptions-logs/): - unset: record exceptions as span events only (unchanged default) - `logs`: record exceptions as logs only - `logs/dup`: record exceptions as both logs and span events Exception logs are emitted at ERROR severity, correlated with the originating span's context, and use the span's instrumentation scope.
e039edd to
01425f1
Compare
| @@ -1074,6 +1099,19 @@ def record_exception( | |||
| if module and module != "builtins" | |||
| else qualname | |||
| ) | |||
|
|
|||
| signal = _exception_signal_opt_in() | |||
| if signal in (_EXCEPTION_SIGNAL_LOGS, _EXCEPTION_SIGNAL_LOGS_DUP): | |||
| self._record_exception_log( | |||
| exception_type=exception_type, | |||
There was a problem hiding this comment.
I'm thinking the _check_span_ended for exception logs is not necessary.
The check is likely for spans, because an ended span, might already be exported, so modifying it (through adding span events for example) should not be allowed.
Same constraint is not present in logs.
There was a problem hiding this comment.
your reasoning makes sense to me
| LogRecord( | ||
| timestamp=timestamp if timestamp is not None else time_ns(), | ||
| context=trace_api.set_span_in_context(self), | ||
| event_name="exception", |
There was a problem hiding this comment.
https://opentelemetry.io/docs/specs/semconv/exceptions/exceptions-logs/#event-name -- should we allow an event name to be passed through here via record_exception ?
There was a problem hiding this comment.
Same question about severity: https://opentelemetry.io/docs/specs/semconv/exceptions/exceptions-logs/#severity
Description
Span.record_exceptioncurrently always records exceptions as spanevents. The semantic conventions for
exceptions in logs
and the span-event API deprecation plan
(OTEP 4430,
see also the
Deprecating Span Events
blog post) introduce the
OTEL_SEMCONV_EXCEPTION_SIGNAL_OPT_INenvironmentvariable so instrumentations can migrate exceptions from span events to logs.
This PR makes the SDK's
Span.record_exception(and therefore the__exit__/use_spanpaths that call it) honorOTEL_SEMCONV_EXCEPTION_SIGNAL_OPT_IN:logslogs/dupAny unrecognized value is treated as unset, preserving today's behavior.
Implementation notes:
LoggerProvider, correlatedwith the originating span's context (
trace_id/span_id), atERRORseverity, with
event_name="exception".exception.type,exception.messageandexception.stacktrace. The deprecatedexception.escapedattribute isintentionally omitted from the log representation; it is still set on the
span event when one is recorded (
logs/dupor default).OTEL_SEMCONV_EXCEPTION_SIGNAL_OPT_INis an experimental, transitionalopt-in, so it is kept private to
opentelemetry.sdk.tracerather thanexported from
opentelemetry.sdk.environment_variables.The default behavior is unchanged, so this is fully backwards compatible and
opt-in.
Type of change
How Has This Been Tested?
A new test module
opentelemetry-sdk/tests/trace/test_record_exception_logs.pycovers all modes end to end using an in-memory span exporter and a captured
logger:
logsrecords a log only (no span event)logs/duprecords both a log and a span event(
trace_id/span_id)exception.type/exception.message/exception.stacktracearepopulated and extra
attributesare forwardedexception.escapedattribute is not set on the logThe existing
record_exceptiontests inopentelemetry-sdk/tests/trace/test_trace.pycontinue to pass unchanged.Does This PR Require a Contrib Repo Change?
record_exceptionsignature is unchanged; the new behavior isgated behind an environment variable and defaults to today's behavior.
Checklist:
ruff check/ruff format).changelog/5318.added— rename to matchthe assigned PR number when opening the PR)
record_exceptiondocstring)