From a37b6f2938e3dc64816d8eed38c60291962bc289 Mon Sep 17 00:00:00 2001 From: June Kim Date: Sat, 9 May 2026 10:12:38 -0700 Subject: [PATCH 1/2] fix(sdk): use context instead of trace_id/span_id/trace_flags in EventLogger.emit EventLogger.emit() was constructing LogRecord with explicit trace_id, span_id, and trace_flags parameters, which triggers a deprecation warning since 1.35.0. Switch to passing context to LogRecord. When the Event carries explicit trace_id/span_id/trace_flags that differ from its captured context, wrap them in a NonRecordingSpan so LogRecord picks them up from context without the deprecated kwargs. Fixes #4687 Assisted-by: Claude Opus 4.6 --- .../src/opentelemetry/sdk/_events/__init__.py | 28 +++++++-- opentelemetry-sdk/tests/events/test_events.py | 61 ++++++++++++++----- 2 files changed, 70 insertions(+), 19 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_events/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_events/__init__.py index 5ec8d864039..89e6799b588 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_events/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_events/__init__.py @@ -49,14 +49,34 @@ def emit(self, event: Event) -> None: if isinstance(self._logger, NoOpLogger): # Do nothing if SDK is disabled return - span_context = trace.get_current_span().get_span_context() + + # Build a context that carries the event's trace correlation. + # If the Event was constructed with explicit trace_id/span_id, + # wrap them in a NonRecordingSpan so LogRecord picks them up + # from context instead of requiring the deprecated kwargs. + context = event.context + span_context = trace.get_current_span(context).get_span_context() + if ( + event.trace_id != span_context.trace_id + or event.span_id != span_context.span_id + or event.trace_flags != span_context.trace_flags + ): + context = trace.set_span_in_context( + trace.NonRecordingSpan( + trace.SpanContext( + trace_id=event.trace_id, + span_id=event.span_id, + is_remote=False, + trace_flags=event.trace_flags, + ) + ), + context, + ) log_record = LogRecord( timestamp=event.timestamp or time_ns(), observed_timestamp=None, - trace_id=event.trace_id or span_context.trace_id, - span_id=event.span_id or span_context.span_id, - trace_flags=event.trace_flags or span_context.trace_flags, + context=context, severity_text=None, severity_number=event.severity_number or SeverityNumber.INFO, body=event.body, diff --git a/opentelemetry-sdk/tests/events/test_events.py b/opentelemetry-sdk/tests/events/test_events.py index 1fb9c3c5147..8ecc3c697d7 100644 --- a/opentelemetry-sdk/tests/events/test_events.py +++ b/opentelemetry-sdk/tests/events/test_events.py @@ -4,8 +4,10 @@ # pylint: disable=protected-access,no-self-use import unittest +import warnings from unittest.mock import Mock, patch +from opentelemetry import trace from opentelemetry._events import Event from opentelemetry._logs import SeverityNumber, set_logger_provider from opentelemetry.sdk._events import EventLoggerProvider @@ -112,15 +114,9 @@ def test_event_logger_emit(self, logger_mock, log_record_mock): "name", "version", "schema_url", {"key": "value"} ) now = Mock() - trace_id = Mock() - span_id = Mock() - trace_flags = Mock() event = Event( name="test_event", timestamp=now, - trace_id=trace_id, - span_id=span_id, - trace_flags=trace_flags, body="test body", severity_number=SeverityNumber.ERROR, attributes={ @@ -135,9 +131,7 @@ def test_event_logger_emit(self, logger_mock, log_record_mock): log_record_mock.assert_called_once_with( timestamp=now, observed_timestamp=None, - trace_id=trace_id, - span_id=span_id, - trace_flags=trace_flags, + context=event.context, severity_text=None, severity_number=SeverityNumber.ERROR, body="test body", @@ -149,6 +143,49 @@ def test_event_logger_emit(self, logger_mock, log_record_mock): ) logger_mock_inst.emit.assert_called_once_with(log_record_mock_inst) + @patch("opentelemetry.sdk._logs._internal.LoggerProvider.get_logger") + def test_event_logger_emit_explicit_trace_ids(self, logger_mock): + """Explicit trace_id/span_id on Event are preserved without deprecation warning.""" + logger_provider = LoggerProvider() + logger_mock_inst = Mock() + logger_mock.return_value = logger_mock_inst + event_logger = EventLoggerProvider(logger_provider).get_event_logger( + "name", + ) + explicit_trace_id = 0x1234567890ABCDEF1234567890ABCDEF + explicit_span_id = 0x1234567890ABCDEF + explicit_trace_flags = trace.TraceFlags(trace.TraceFlags.SAMPLED) + event = Event( + name="test_event", + timestamp=1000, + trace_id=explicit_trace_id, + span_id=explicit_span_id, + trace_flags=explicit_trace_flags, + body="test body", + ) + # Emit should not trigger LogDeprecatedInitWarning + with warnings.catch_warnings(record=True) as caught: + warnings.simplefilter("always") + event_logger.emit(event) + deprecated_init_warnings = [ + w + for w in caught + if "LogRecord" in str(w.message) + and "deprecated" in str(w.message).lower() + and "trace_id" in str(w.message) + ] + self.assertEqual( + len(deprecated_init_warnings), + 0, + f"Unexpected deprecation warnings: {deprecated_init_warnings}", + ) + # Verify the emitted LogRecord has the explicit trace data + logger_mock_inst.emit.assert_called_once() + emitted_record = logger_mock_inst.emit.call_args[0][0] + self.assertEqual(emitted_record.trace_id, explicit_trace_id) + self.assertEqual(emitted_record.span_id, explicit_span_id) + self.assertEqual(emitted_record.trace_flags, explicit_trace_flags) + @patch("opentelemetry.sdk._events.LogRecord") @patch("opentelemetry.sdk._logs._internal.LoggerProvider.get_logger") def test_event_logger_emit_sdk_disabled( @@ -167,15 +204,9 @@ def test_event_logger_emit_sdk_disabled( "name", "version", "schema_url", {"key": "value"} ) now = Mock() - trace_id = Mock() - span_id = Mock() - trace_flags = Mock() event = Event( name="test_event", timestamp=now, - trace_id=trace_id, - span_id=span_id, - trace_flags=trace_flags, body="test body", severity_number=SeverityNumber.ERROR, attributes={ From cd113cf3ec0cf4d770eaa435935fcf8a82eb05c4 Mon Sep 17 00:00:00 2001 From: June Kim Date: Tue, 12 May 2026 21:10:09 -0700 Subject: [PATCH 2/2] docs: use Towncrier fragment for changelog per review --- .changelog/5199.fixed | 1 + 1 file changed, 1 insertion(+) create mode 100644 .changelog/5199.fixed diff --git a/.changelog/5199.fixed b/.changelog/5199.fixed new file mode 100644 index 00000000000..94601d8cd74 --- /dev/null +++ b/.changelog/5199.fixed @@ -0,0 +1 @@ +`opentelemetry-sdk`: use context parameter instead of deprecated trace_id/span_id/trace_flags kwargs in EventLogger.emit