diff --git a/CHANGELOG.md b/CHANGELOG.md index 001fbf28a58..e633a12b10e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ([#4593](https://github.com/open-telemetry/opentelemetry-python/pull/4593)) - opentelemetry-test-utils: assert explicit bucket boundaries in histogram metrics ([#4595](https://github.com/open-telemetry/opentelemetry-python/pull/4595)) +- Logging API and Events API accept SpanContext instead of trace_id, span_id, trace_flags + ([#4584](https://github.com/open-telemetry/opentelemetry-python/pull/4584)) ## Version 1.33.0/0.54b0 (2025-05-09) diff --git a/exporter/opentelemetry-exporter-otlp-proto-common/tests/test_log_encoder.py b/exporter/opentelemetry-exporter-otlp-proto-common/tests/test_log_encoder.py index 4c2b54aad2b..0a3256cef46 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-common/tests/test_log_encoder.py +++ b/exporter/opentelemetry-exporter-otlp-proto-common/tests/test_log_encoder.py @@ -50,6 +50,7 @@ from opentelemetry.sdk.resources import Resource as SDKResource from opentelemetry.sdk.util.instrumentation import InstrumentationScope from opentelemetry.trace import TraceFlags +from opentelemetry.trace.span import SpanContext class TestOTLPLogEncoder(unittest.TestCase): @@ -88,9 +89,12 @@ def _get_sdk_log_data() -> List[LogData]: log_record=SDKLogRecord( timestamp=1644650195189786880, observed_timestamp=1644650195189786881, - trace_id=89564621134313219400156819398935297684, - span_id=1312458408527513268, - trace_flags=TraceFlags(0x01), + span_context=SpanContext( + 89564621134313219400156819398935297684, + 1312458408527513268, + True, + TraceFlags(0x01), + ), severity_text="WARN", severity_number=SeverityNumber.WARN, body="Do not go gentle into that good night. Rage, rage against the dying of the light", @@ -109,9 +113,12 @@ def _get_sdk_log_data() -> List[LogData]: log_record=SDKLogRecord( timestamp=1644650249738562048, observed_timestamp=1644650249738562049, - trace_id=0, - span_id=0, - trace_flags=TraceFlags.DEFAULT, + span_context=SpanContext( + 0, + 0, + True, + TraceFlags.DEFAULT, + ), severity_text="WARN", severity_number=SeverityNumber.WARN, body="Cooper, this is no time for caution!", @@ -127,9 +134,12 @@ def _get_sdk_log_data() -> List[LogData]: log_record=SDKLogRecord( timestamp=1644650427658989056, observed_timestamp=1644650427658989057, - trace_id=271615924622795969659406376515024083555, - span_id=4242561578944770265, - trace_flags=TraceFlags(0x01), + span_context=SpanContext( + 271615924622795969659406376515024083555, + 4242561578944770265, + True, + TraceFlags(0x01), + ), severity_text="DEBUG", severity_number=SeverityNumber.DEBUG, body="To our galaxy", @@ -143,9 +153,12 @@ def _get_sdk_log_data() -> List[LogData]: log_record=SDKLogRecord( timestamp=1644650584292683008, observed_timestamp=1644650584292683009, - trace_id=212592107417388365804938480559624925555, - span_id=6077757853989569223, - trace_flags=TraceFlags(0x01), + span_context=SpanContext( + 212592107417388365804938480559624925555, + 6077757853989569223, + True, + TraceFlags(0x01), + ), severity_text="INFO", severity_number=SeverityNumber.INFO, body="Love is the one thing that transcends time and space", @@ -164,9 +177,12 @@ def _get_sdk_log_data() -> List[LogData]: log_record=SDKLogRecord( timestamp=1644650584292683009, observed_timestamp=1644650584292683010, - trace_id=212592107417388365804938480559624925555, - span_id=6077757853989569445, - trace_flags=TraceFlags(0x01), + span_context=SpanContext( + 212592107417388365804938480559624925555, + 6077757853989569445, + True, + TraceFlags(0x01), + ), severity_text="INFO", severity_number=SeverityNumber.INFO, body={"error": None, "array_with_nones": [1, None, 2]}, @@ -182,9 +198,12 @@ def _get_sdk_log_data() -> List[LogData]: log_record=SDKLogRecord( timestamp=1644650584292683022, observed_timestamp=1644650584292683022, - trace_id=212592107417388365804938480559624925522, - span_id=6077757853989569222, - trace_flags=TraceFlags(0x01), + span_context=SpanContext( + 212592107417388365804938480559624925522, + 6077757853989569222, + True, + TraceFlags(0x01), + ), severity_text="ERROR", severity_number=SeverityNumber.ERROR, body="This instrumentation scope has a schema url", @@ -205,9 +224,12 @@ def _get_sdk_log_data() -> List[LogData]: log_record=SDKLogRecord( timestamp=1644650584292683033, observed_timestamp=1644650584292683033, - trace_id=212592107417388365804938480559624925533, - span_id=6077757853989569233, - trace_flags=TraceFlags(0x01), + span_context=SpanContext( + 212592107417388365804938480559624925533, + 6077757853989569233, + True, + TraceFlags(0x01), + ), severity_text="FATAL", severity_number=SeverityNumber.FATAL, body="This instrumentation scope has a schema url and attributes", @@ -229,9 +251,12 @@ def _get_sdk_log_data() -> List[LogData]: log_record=SDKLogRecord( timestamp=1644650584292683044, observed_timestamp=1644650584292683044, - trace_id=212592107417388365804938480559624925566, - span_id=6077757853989569466, - trace_flags=TraceFlags(0x01), + span_context=SpanContext( + 212592107417388365804938480559624925566, + 6077757853989569466, + True, + TraceFlags(0x01), + ), severity_text="INFO", severity_number=SeverityNumber.INFO, body="Test export of extended attributes", @@ -547,9 +572,12 @@ def _get_test_logs_dropped_attributes() -> List[LogData]: log1 = LogData( log_record=SDKLogRecord( timestamp=1644650195189786880, - trace_id=89564621134313219400156819398935297684, - span_id=1312458408527513268, - trace_flags=TraceFlags(0x01), + span_context=SpanContext( + 89564621134313219400156819398935297684, + 1312458408527513268, + True, + TraceFlags(0x01), + ), severity_text="WARN", severity_number=SeverityNumber.WARN, body="Do not go gentle into that good night. Rage, rage against the dying of the light", @@ -565,9 +593,12 @@ def _get_test_logs_dropped_attributes() -> List[LogData]: log2 = LogData( log_record=SDKLogRecord( timestamp=1644650249738562048, - trace_id=0, - span_id=0, - trace_flags=TraceFlags.DEFAULT, + span_context=SpanContext( + 0, + 0, + True, + TraceFlags.DEFAULT, + ), severity_text="WARN", severity_number=SeverityNumber.WARN, body="Cooper, this is no time for caution!", diff --git a/exporter/opentelemetry-exporter-otlp-proto-grpc/tests/logs/test_otlp_logs_exporter.py b/exporter/opentelemetry-exporter-otlp-proto-grpc/tests/logs/test_otlp_logs_exporter.py index 8f3677784b1..eae26d0ec42 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-grpc/tests/logs/test_otlp_logs_exporter.py +++ b/exporter/opentelemetry-exporter-otlp-proto-grpc/tests/logs/test_otlp_logs_exporter.py @@ -52,6 +52,7 @@ from opentelemetry.sdk.resources import Resource as SDKResource from opentelemetry.sdk.util.instrumentation import InstrumentationScope from opentelemetry.trace import TraceFlags +from opentelemetry.trace.span import SpanContext THIS_DIR = dirname(__file__) @@ -62,9 +63,12 @@ def setUp(self): self.log_data_1 = LogData( log_record=LogRecord( timestamp=int(time.time() * 1e9), - trace_id=2604504634922341076776623263868986797, - span_id=5213367945872657620, - trace_flags=TraceFlags(0x01), + span_context=SpanContext( + 2604504634922341076776623263868986797, + 5213367945872657620, + True, + TraceFlags(0x01), + ), severity_text="WARNING", severity_number=SeverityNumber.WARN, body="Zhengzhou, We have a heaviest rains in 1000 years", @@ -78,9 +82,12 @@ def setUp(self): self.log_data_2 = LogData( log_record=LogRecord( timestamp=int(time.time() * 1e9), - trace_id=2604504634922341076776623263868986799, - span_id=5213367945872657623, - trace_flags=TraceFlags(0x01), + span_context=SpanContext( + 2604504634922341076776623263868986799, + 5213367945872657623, + True, + TraceFlags(0x01), + ), severity_text="INFO", severity_number=SeverityNumber.INFO2, body="Sydney, Opera House is closed", @@ -94,9 +101,12 @@ def setUp(self): self.log_data_3 = LogData( log_record=LogRecord( timestamp=int(time.time() * 1e9), - trace_id=2604504634922341076776623263868986800, - span_id=5213367945872657628, - trace_flags=TraceFlags(0x01), + span_context=SpanContext( + 2604504634922341076776623263868986800, + 5213367945872657628, + True, + TraceFlags(0x01), + ), severity_text="ERROR", severity_number=SeverityNumber.WARN, body="Mumbai, Boil water before drinking", @@ -109,9 +119,12 @@ def setUp(self): self.log_data_4 = LogData( log_record=LogRecord( timestamp=int(time.time() * 1e9), - trace_id=0, - span_id=5213367945872657629, - trace_flags=TraceFlags(0x01), + span_context=SpanContext( + 0, + 213367945872657629, + True, + TraceFlags(0x01), + ), severity_text="ERROR", severity_number=SeverityNumber.WARN, body="Invalid trace id check", @@ -124,9 +137,12 @@ def setUp(self): self.log_data_5 = LogData( log_record=LogRecord( timestamp=int(time.time() * 1e9), - trace_id=2604504634922341076776623263868986801, - span_id=0, - trace_flags=TraceFlags(0x01), + span_context=SpanContext( + 2604504634922341076776623263868986801, + 0, + True, + TraceFlags(0x01), + ), severity_text="ERROR", severity_number=SeverityNumber.WARN, body="Invalid span id check", diff --git a/exporter/opentelemetry-exporter-otlp-proto-http/tests/test_proto_log_exporter.py b/exporter/opentelemetry-exporter-otlp-proto-http/tests/test_proto_log_exporter.py index 66b0f890d76..5f81ef69955 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-http/tests/test_proto_log_exporter.py +++ b/exporter/opentelemetry-exporter-otlp-proto-http/tests/test_proto_log_exporter.py @@ -57,6 +57,7 @@ from opentelemetry.sdk.resources import Resource as SDKResource from opentelemetry.sdk.util.instrumentation import InstrumentationScope from opentelemetry.trace import TraceFlags +from opentelemetry.trace.span import SpanContext ENV_ENDPOINT = "http://localhost.env:8080/" ENV_CERTIFICATE = "/etc/base.crt" @@ -217,9 +218,12 @@ def test_exported_log_without_trace_id(self): log = LogData( log_record=SDKLogRecord( timestamp=1644650195189786182, - trace_id=0, - span_id=1312458408527513292, - trace_flags=TraceFlags(0x01), + span_context=SpanContext( + 0, + 1312458408527513292, + True, + TraceFlags(0x01), + ), severity_text="WARN", severity_number=SeverityNumber.WARN, body="Invalid trace id check", @@ -244,9 +248,12 @@ def test_exported_log_without_span_id(self): log = LogData( log_record=SDKLogRecord( timestamp=1644650195189786360, - trace_id=89564621134313219400156819398935297696, - span_id=0, - trace_flags=TraceFlags(0x01), + span_context=SpanContext( + 89564621134313219400156819398935297696, + 0, + True, + TraceFlags(0x01), + ), severity_text="WARN", severity_number=SeverityNumber.WARN, body="Invalid span id check", @@ -291,9 +298,12 @@ def _get_sdk_log_data() -> List[LogData]: log1 = LogData( log_record=SDKLogRecord( timestamp=1644650195189786880, - trace_id=89564621134313219400156819398935297684, - span_id=1312458408527513268, - trace_flags=TraceFlags(0x01), + span_context=SpanContext( + 89564621134313219400156819398935297684, + 1312458408527513268, + True, + TraceFlags(0x01), + ), severity_text="WARN", severity_number=SeverityNumber.WARN, body="Do not go gentle into that good night. Rage, rage against the dying of the light", @@ -308,9 +318,12 @@ def _get_sdk_log_data() -> List[LogData]: log2 = LogData( log_record=SDKLogRecord( timestamp=1644650249738562048, - trace_id=0, - span_id=0, - trace_flags=TraceFlags.DEFAULT, + span_context=SpanContext( + 0, + 0, + True, + TraceFlags.DEFAULT, + ), severity_text="WARN", severity_number=SeverityNumber.WARN, body="Cooper, this is no time for caution!", @@ -325,9 +338,12 @@ def _get_sdk_log_data() -> List[LogData]: log3 = LogData( log_record=SDKLogRecord( timestamp=1644650427658989056, - trace_id=271615924622795969659406376515024083555, - span_id=4242561578944770265, - trace_flags=TraceFlags(0x01), + span_context=SpanContext( + 271615924622795969659406376515024083555, + 4242561578944770265, + True, + TraceFlags(0x01), + ), severity_text="DEBUG", severity_number=SeverityNumber.DEBUG, body="To our galaxy", @@ -340,9 +356,12 @@ def _get_sdk_log_data() -> List[LogData]: log4 = LogData( log_record=SDKLogRecord( timestamp=1644650584292683008, - trace_id=212592107417388365804938480559624925555, - span_id=6077757853989569223, - trace_flags=TraceFlags(0x01), + span_context=SpanContext( + 212592107417388365804938480559624925555, + 6077757853989569223, + True, + TraceFlags(0x01), + ), severity_text="INFO", severity_number=SeverityNumber.INFO, body="Love is the one thing that transcends time and space", diff --git a/opentelemetry-api/src/opentelemetry/_events/__init__.py b/opentelemetry-api/src/opentelemetry/_events/__init__.py index f073b223345..be4f972ec0a 100644 --- a/opentelemetry-api/src/opentelemetry/_events/__init__.py +++ b/opentelemetry-api/src/opentelemetry/_events/__init__.py @@ -22,7 +22,7 @@ from opentelemetry.environment_variables import ( _OTEL_PYTHON_EVENT_LOGGER_PROVIDER, ) -from opentelemetry.trace.span import TraceFlags +from opentelemetry.trace.span import SpanContext 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, + span_context: Optional[SpanContext] = 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, + span_context=span_context, body=body, severity_number=severity_number, attributes=event_attributes, diff --git a/opentelemetry-api/src/opentelemetry/_logs/_internal/__init__.py b/opentelemetry-api/src/opentelemetry/_logs/_internal/__init__.py index f969f7db730..45a4008e5e1 100644 --- a/opentelemetry-api/src/opentelemetry/_logs/_internal/__init__.py +++ b/opentelemetry-api/src/opentelemetry/_logs/_internal/__init__.py @@ -41,7 +41,7 @@ from opentelemetry._logs.severity import SeverityNumber from opentelemetry.environment_variables import _OTEL_PYTHON_LOGGER_PROVIDER -from opentelemetry.trace.span import TraceFlags +from opentelemetry.trace.span import SpanContext from opentelemetry.util._once import Once from opentelemetry.util._providers import _load_provider from opentelemetry.util.types import AnyValue, _ExtendedAttributes @@ -61,9 +61,7 @@ def __init__( self, timestamp: Optional[int] = None, observed_timestamp: Optional[int] = None, - trace_id: Optional[int] = None, - span_id: Optional[int] = None, - trace_flags: Optional["TraceFlags"] = None, + span_context: Optional[SpanContext] = None, severity_text: Optional[str] = None, severity_number: Optional[SeverityNumber] = None, body: AnyValue = None, @@ -73,9 +71,12 @@ def __init__( if observed_timestamp is None: observed_timestamp = time_ns() self.observed_timestamp = observed_timestamp - self.trace_id = trace_id - self.span_id = span_id - self.trace_flags = trace_flags + self.span_context = span_context + self.trace_id = self.span_id = self.trace_flags = None + if span_context: + self.trace_id = span_context.trace_id + self.span_id = span_context.span_id + self.trace_flags = span_context.trace_flags self.severity_text = severity_text self.severity_number = severity_number self.body = body diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_events/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_events/__init__.py index c427a48e2f8..9f8cfa96b44 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_events/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_events/__init__.py @@ -53,9 +53,7 @@ def emit(self, event: Event) -> None: 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, + span_context=event.span_context or span_context, severity_text=None, severity_number=event.severity_number or SeverityNumber.INFO, body=event.body, diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py index 9060e49aac4..b533dd1d5f4 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py @@ -24,7 +24,7 @@ from os import environ from threading import Lock from time import time_ns -from typing import Any, Callable, Tuple, Union, cast # noqa +from typing import Any, Callable, Optional, Tuple, Union, cast # noqa from opentelemetry._logs import Logger as APILogger from opentelemetry._logs import LoggerProvider as APILoggerProvider @@ -52,7 +52,7 @@ format_trace_id, get_current_span, ) -from opentelemetry.trace.span import TraceFlags +from opentelemetry.trace.span import SpanContext from opentelemetry.util.types import AnyValue, _ExtendedAttributes _logger = logging.getLogger(__name__) @@ -176,9 +176,7 @@ def __init__( self, timestamp: int | None = None, observed_timestamp: int | None = None, - trace_id: int | None = None, - span_id: int | None = None, - trace_flags: TraceFlags | None = None, + span_context: Optional[SpanContext] = None, severity_text: str | None = None, severity_number: SeverityNumber | None = None, body: AnyValue | None = None, @@ -190,9 +188,7 @@ def __init__( **{ "timestamp": timestamp, "observed_timestamp": observed_timestamp, - "trace_id": trace_id, - "span_id": span_id, - "trace_flags": trace_flags, + "span_context": span_context, "severity_text": severity_text, "severity_number": severity_number, "body": body, @@ -548,9 +544,7 @@ def _translate(self, record: logging.LogRecord) -> LogRecord: return LogRecord( timestamp=timestamp, observed_timestamp=observered_timestamp, - trace_id=span_context.trace_id, - span_id=span_context.span_id, - trace_flags=span_context.trace_flags, + span_context=span_context, severity_text=level_name, severity_number=severity_number, body=body, diff --git a/opentelemetry-sdk/tests/events/test_events.py b/opentelemetry-sdk/tests/events/test_events.py index 7b8d42ff316..8660358b1ed 100644 --- a/opentelemetry-sdk/tests/events/test_events.py +++ b/opentelemetry-sdk/tests/events/test_events.py @@ -23,6 +23,8 @@ from opentelemetry.sdk._logs import LoggerProvider from opentelemetry.sdk._logs._internal import Logger, NoOpLogger from opentelemetry.sdk.environment_variables import OTEL_SDK_DISABLED +from opentelemetry.trace import TraceFlags +from opentelemetry.trace.span import SpanContext class TestEventLoggerProvider(unittest.TestCase): @@ -123,15 +125,17 @@ 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() + trace_flags = TraceFlags(0x01) + span_context = SpanContext( + 2604504634922341076776623263868986797, + 5213367945872657620, + True, + trace_flags, + ) event = Event( name="test_event", timestamp=now, - trace_id=trace_id, - span_id=span_id, - trace_flags=trace_flags, + span_context=span_context, body="test body", severity_number=SeverityNumber.ERROR, attributes={ @@ -146,9 +150,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, + span_context=span_context, severity_text=None, severity_number=SeverityNumber.ERROR, body="test body", @@ -179,15 +181,16 @@ def test_event_logger_emit_sdk_disabled( "name", "version", "schema_url", {"key": "value"} ) now = Mock() - trace_id = Mock() - span_id = Mock() - trace_flags = Mock() + span_context = SpanContext( + 2604504634922341076776623263868986797, + 5213367945872657620, + True, + Mock(), + ) event = Event( name="test_event", timestamp=now, - trace_id=trace_id, - span_id=span_id, - trace_flags=trace_flags, + span_context=span_context, body="test body", severity_number=SeverityNumber.ERROR, attributes={ diff --git a/opentelemetry-sdk/tests/logs/test_export.py b/opentelemetry-sdk/tests/logs/test_export.py index 30a8c724b26..6b109753f3b 100644 --- a/opentelemetry-sdk/tests/logs/test_export.py +++ b/opentelemetry-sdk/tests/logs/test_export.py @@ -46,7 +46,10 @@ from opentelemetry.sdk.resources import Resource as SDKResource from opentelemetry.sdk.util.instrumentation import InstrumentationScope from opentelemetry.trace import TraceFlags -from opentelemetry.trace.span import INVALID_SPAN_CONTEXT +from opentelemetry.trace.span import ( + INVALID_SPAN_CONTEXT, + SpanContext, +) EMPTY_LOG = LogData( log_record=LogRecord(), @@ -560,9 +563,12 @@ def test_export(self): # pylint: disable=no-self-use log_data = LogData( log_record=LogRecord( timestamp=int(time.time() * 1e9), - trace_id=2604504634922341076776623263868986797, - span_id=5213367945872657620, - trace_flags=TraceFlags(0x01), + span_context=SpanContext( + 2604504634922341076776623263868986797, + 5213367945872657620, + True, + TraceFlags(0x01), + ), severity_text="WARN", severity_number=SeverityNumber.WARN, body="Zhengzhou, We have a heaviest rains in 1000 years",