diff --git a/CHANGELOG.md b/CHANGELOG.md index 81e52e6d409..ac491c2d51f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Overwrite logging.config.fileConfig and logging.config.dictConfig to ensure the OTLP `LogHandler` remains attached to the root logger. Fix a bug that can cause a deadlock to occur over `logging._lock` in some cases ([#4636](https://github.com/open-telemetry/opentelemetry-python/pull/4636)). +- events: use optional `context` for initialiation instead of (`trace_id`, `span_id`, `trace_flag`) + ([#4690](https://github.com/open-telemetry/opentelemetry-python/pull/4636)) ## Version 1.35.0/0.56b0 (2025-07-11) @@ -31,7 +33,7 @@ can cause a deadlock to occur over `logging._lock` in some cases ([#4636](https: - Update logger level to NOTSET in logs example ([#4637](https://github.com/open-telemetry/opentelemetry-python/pull/4637)) - Logging API accepts optional `context`; deprecates `trace_id`, `span_id`, `trace_flags`. - ([#4597](https://github.com/open-telemetry/opentelemetry-python/pull/4597)) and + ([#4597](https://github.com/open-telemetry/opentelemetry-python/pull/4597)) and ([#4668](https://github.com/open-telemetry/opentelemetry-python/pull/4668)) - sdk: use context instead of trace_id,span_id for initializing LogRecord ([#4653](https://github.com/open-telemetry/opentelemetry-python/pull/4653)) diff --git a/opentelemetry-api/src/opentelemetry/_events/__init__.py b/opentelemetry-api/src/opentelemetry/_events/__init__.py index f073b223345..1b52a145731 100644 --- a/opentelemetry-api/src/opentelemetry/_events/__init__.py +++ b/opentelemetry-api/src/opentelemetry/_events/__init__.py @@ -19,10 +19,10 @@ from opentelemetry._logs import LogRecord from opentelemetry._logs.severity import SeverityNumber +from opentelemetry.context import Context from opentelemetry.environment_variables import ( _OTEL_PYTHON_EVENT_LOGGER_PROVIDER, ) -from opentelemetry.trace.span import TraceFlags from opentelemetry.util._once import Once from opentelemetry.util._providers import _load_provider from opentelemetry.util.types import AnyValue, _ExtendedAttributes @@ -35,9 +35,7 @@ def __init__( self, name: str, timestamp: Optional[int] = None, - trace_id: Optional[int] = None, - span_id: Optional[int] = None, - trace_flags: Optional["TraceFlags"] = None, + context: Optional[Context] = None, body: Optional[AnyValue] = None, severity_number: Optional[SeverityNumber] = None, attributes: Optional[_ExtendedAttributes] = None, @@ -49,9 +47,7 @@ def __init__( } super().__init__( timestamp=timestamp, - trace_id=trace_id, - span_id=span_id, - trace_flags=trace_flags, + context=context, body=body, severity_number=severity_number, attributes=event_attributes, diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_events/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_events/__init__.py index c427a48e2f8..5a3736ac966 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_events/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_events/__init__.py @@ -15,11 +15,11 @@ from time import time_ns from typing import Optional -from opentelemetry import trace from opentelemetry._events import Event from opentelemetry._events import EventLogger as APIEventLogger from opentelemetry._events import EventLoggerProvider as APIEventLoggerProvider from opentelemetry._logs import NoOpLogger, SeverityNumber, get_logger_provider +from opentelemetry.context import get_current from opentelemetry.sdk._logs import Logger, LoggerProvider, LogRecord from opentelemetry.util.types import _ExtendedAttributes @@ -49,13 +49,10 @@ 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() 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=event.context or get_current(), 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 7b8d42ff316..847a2473990 100644 --- a/opentelemetry-sdk/tests/events/test_events.py +++ b/opentelemetry-sdk/tests/events/test_events.py @@ -17,11 +17,13 @@ import unittest from unittest.mock import Mock, patch +from opentelemetry import trace as trace_api from opentelemetry._events import Event -from opentelemetry._logs import SeverityNumber, set_logger_provider +from opentelemetry._logs import NoOpLogger, SeverityNumber, set_logger_provider +from opentelemetry.context import get_current from opentelemetry.sdk._events import EventLoggerProvider from opentelemetry.sdk._logs import LoggerProvider -from opentelemetry.sdk._logs._internal import Logger, NoOpLogger +from opentelemetry.sdk._logs._internal import Logger from opentelemetry.sdk.environment_variables import OTEL_SDK_DISABLED @@ -123,15 +125,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={ @@ -146,9 +142,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=get_current(), severity_text=None, severity_number=SeverityNumber.ERROR, body="test body", @@ -179,15 +173,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={ @@ -200,3 +188,92 @@ def test_event_logger_emit_sdk_disabled( log_record_mock.return_value = log_record_mock_inst event_logger.emit(event) logger_mock_inst.emit.assert_not_called() + + @patch("opentelemetry.sdk._events.LogRecord") + @patch("opentelemetry.sdk._logs._internal.LoggerProvider.get_logger") + def test_event_logger_emit_with_context( + self, logger_mock, log_record_mock + ): + logger_provider = LoggerProvider() + logger_mock_inst = Mock() + logger_mock.return_value = logger_mock_inst + event_logger = EventLoggerProvider(logger_provider).get_event_logger( + "name", + version="version", + schema_url="schema_url", + attributes={"key": "value"}, + ) + logger_mock.assert_called_once_with( + "name", "version", "schema_url", {"key": "value"} + ) + + span = trace_api.NonRecordingSpan( + trace_api.SpanContext( + 2604504634922341076776623263868986797, + 5213367945872657620, + False, + trace_api.TraceFlags(0x01), + ) + ) + ctx = trace_api.set_span_in_context(span) + + now = Mock() + event = Event( + name="test_event", + timestamp=now, + body="test body", + severity_number=SeverityNumber.ERROR, + attributes={ + "key": "val", + "foo": "bar", + "event.name": "not this one", + }, + ) + log_record_mock_inst = Mock() + log_record_mock.return_value = log_record_mock_inst + with trace_api.use_span(span): + event_logger.emit(event) + log_record_mock.assert_called_with( + timestamp=now, + observed_timestamp=None, + context=ctx, + severity_text=None, + severity_number=SeverityNumber.ERROR, + body="test body", + resource=event_logger._logger.resource, + attributes={ + "key": "val", + "foo": "bar", + "event.name": "test_event", + }, + ) + + another_event = Event( + name="another_event", + timestamp=now, + context=ctx, + body="another body", + severity_number=SeverityNumber.ERROR, + attributes={ + "key": "val", + "foo": "bar", + "event.name": "not this one", + }, + ) + event_logger.emit(another_event) + log_record_mock.assert_called_with( + timestamp=now, + observed_timestamp=None, + context=ctx, + severity_text=None, + severity_number=SeverityNumber.ERROR, + body="another body", + resource=event_logger._logger.resource, + attributes={ + "key": "val", + "foo": "bar", + "event.name": "another_event", + }, + ) + + self.assertEqual(log_record_mock.call_count, 2)