diff --git a/CHANGELOG.md b/CHANGELOG.md index dfc9179da34..be959297c2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,6 +57,8 @@ can cause a deadlock to occur over `logging._lock` in some cases ([#4636](https: ([#4669](https://github.com/open-telemetry/opentelemetry-python/pull/4669)) - Set expected User-Agent in HTTP headers for grpc OTLP exporter ([#4658](https://github.com/open-telemetry/opentelemetry-python/pull/4658)) +- Remove LogData and extend SDK LogRecord to have instrumentation scope + ([#4676](https://github.com/open-telemetry/opentelemetry-python/pull/4676)) ## Version 1.34.0/0.55b0 (2025-06-04) diff --git a/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/_log_encoder/__init__.py b/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/_log_encoder/__init__.py index 000e56ed8bf..bd84e67f1a3 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/_log_encoder/__init__.py +++ b/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/_log_encoder/__init__.py @@ -30,47 +30,47 @@ ResourceLogs, ScopeLogs, ) -from opentelemetry.sdk._logs import LogData +from opentelemetry.sdk._logs import SDKLogRecord -def encode_logs(batch: Sequence[LogData]) -> ExportLogsServiceRequest: +def encode_logs(batch: Sequence[SDKLogRecord]) -> ExportLogsServiceRequest: return ExportLogsServiceRequest(resource_logs=_encode_resource_logs(batch)) -def _encode_log(log_data: LogData) -> PB2LogRecord: +def _encode_log(sdk_log_record: SDKLogRecord) -> PB2LogRecord: span_id = ( None - if log_data.log_record.span_id == 0 - else _encode_span_id(log_data.log_record.span_id) + if sdk_log_record.log_record.span_id == 0 + else _encode_span_id(sdk_log_record.log_record.span_id) ) trace_id = ( None - if log_data.log_record.trace_id == 0 - else _encode_trace_id(log_data.log_record.trace_id) + if sdk_log_record.log_record.trace_id == 0 + else _encode_trace_id(sdk_log_record.log_record.trace_id) ) - body = log_data.log_record.body + body = sdk_log_record.log_record.body return PB2LogRecord( - time_unix_nano=log_data.log_record.timestamp, - observed_time_unix_nano=log_data.log_record.observed_timestamp, + time_unix_nano=sdk_log_record.log_record.timestamp, + observed_time_unix_nano=sdk_log_record.log_record.observed_timestamp, span_id=span_id, trace_id=trace_id, - flags=int(log_data.log_record.trace_flags), + flags=int(sdk_log_record.log_record.trace_flags), body=_encode_value(body, allow_null=True), - severity_text=log_data.log_record.severity_text, + severity_text=sdk_log_record.log_record.severity_text, attributes=_encode_attributes( - log_data.log_record.attributes, allow_null=True + sdk_log_record.log_record.attributes, allow_null=True ), - dropped_attributes_count=log_data.log_record.dropped_attributes, - severity_number=log_data.log_record.severity_number.value, - event_name=log_data.log_record.event_name, + dropped_attributes_count=sdk_log_record.dropped_attributes, + severity_number=sdk_log_record.log_record.severity_number.value, + event_name=sdk_log_record.log_record.event_name, ) -def _encode_resource_logs(batch: Sequence[LogData]) -> List[ResourceLogs]: +def _encode_resource_logs(batch: Sequence[SDKLogRecord]) -> List[ResourceLogs]: sdk_resource_logs = defaultdict(lambda: defaultdict(list)) for sdk_log in batch: - sdk_resource = sdk_log.log_record.resource + sdk_resource = sdk_log.resource sdk_instrumentation = sdk_log.instrumentation_scope or None pb2_log = _encode_log(sdk_log) 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 5407d9f1bca..c86cd74a918 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 @@ -15,7 +15,7 @@ import unittest from typing import List, Tuple -from opentelemetry._logs import SeverityNumber +from opentelemetry._logs import LogRecord, SeverityNumber from opentelemetry.exporter.otlp.proto.common._internal import ( _encode_attributes, _encode_span_id, @@ -45,8 +45,7 @@ from opentelemetry.proto.resource.v1.resource_pb2 import ( Resource as PB2Resource, ) -from opentelemetry.sdk._logs import LogData, LogLimits -from opentelemetry.sdk._logs import LogRecord as SDKLogRecord +from opentelemetry.sdk._logs import LogLimits, SDKLogRecord from opentelemetry.sdk.resources import Resource as SDKResource from opentelemetry.sdk.util.instrumentation import InstrumentationScope from opentelemetry.trace import ( @@ -77,7 +76,7 @@ def test_encode_no_body(self): def test_dropped_attributes_count(self): sdk_logs = self._get_test_logs_dropped_attributes() encoded_logs = encode_logs(sdk_logs) - self.assertTrue(hasattr(sdk_logs[0].log_record, "dropped_attributes")) + self.assertTrue(hasattr(sdk_logs[0], "dropped_attributes")) self.assertEqual( # pylint:disable=no-member encoded_logs.resource_logs[0] @@ -88,7 +87,7 @@ def test_dropped_attributes_count(self): ) @staticmethod - def _get_sdk_log_data() -> List[LogData]: + def _get_sdk_log_data() -> List[SDKLogRecord]: ctx_log1 = set_span_in_context( NonRecordingSpan( SpanContext( @@ -99,35 +98,35 @@ def _get_sdk_log_data() -> List[LogData]: ) ) ) - log1 = LogData( - log_record=SDKLogRecord( + log1 = SDKLogRecord( + LogRecord( timestamp=1644650195189786880, observed_timestamp=1644650195189786881, context=ctx_log1, severity_text="WARN", severity_number=SeverityNumber.WARN, body="Do not go gentle into that good night. Rage, rage against the dying of the light", - resource=SDKResource( - {"first_resource": "value"}, - "resource_schema_url", - ), attributes={"a": 1, "b": "c"}, ), + resource=SDKResource( + {"first_resource": "value"}, + "resource_schema_url", + ), instrumentation_scope=InstrumentationScope( "first_name", "first_version" ), ) - log2 = LogData( - log_record=SDKLogRecord( + log2 = SDKLogRecord( + LogRecord( timestamp=1644650249738562048, observed_timestamp=1644650249738562049, severity_text="WARN", severity_number=SeverityNumber.WARN, body="Cooper, this is no time for caution!", - resource=SDKResource({"second_resource": "CASE"}), attributes={}, ), + resource=SDKResource({"second_resource": "CASE"}), instrumentation_scope=InstrumentationScope( "second_name", "second_version" ), @@ -143,17 +142,17 @@ def _get_sdk_log_data() -> List[LogData]: ) ) ) - log3 = LogData( - log_record=SDKLogRecord( + log3 = SDKLogRecord( + LogRecord( timestamp=1644650427658989056, observed_timestamp=1644650427658989057, context=ctx_log3, severity_text="DEBUG", severity_number=SeverityNumber.DEBUG, body="To our galaxy", - resource=SDKResource({"second_resource": "CASE"}), attributes={"a": 1, "b": "c"}, ), + resource=SDKResource({"second_resource": "CASE"}), instrumentation_scope=None, ) @@ -167,20 +166,20 @@ def _get_sdk_log_data() -> List[LogData]: ) ) ) - log4 = LogData( - log_record=SDKLogRecord( + log4 = SDKLogRecord( + LogRecord( timestamp=1644650584292683008, observed_timestamp=1644650584292683009, context=ctx_log4, severity_text="INFO", severity_number=SeverityNumber.INFO, body="Love is the one thing that transcends time and space", - resource=SDKResource( - {"first_resource": "value"}, - "resource_schema_url", - ), attributes={"filename": "model.py", "func_name": "run_method"}, ), + resource=SDKResource( + {"first_resource": "value"}, + "resource_schema_url", + ), instrumentation_scope=InstrumentationScope( "another_name", "another_version" ), @@ -196,17 +195,17 @@ def _get_sdk_log_data() -> List[LogData]: ) ) ) - log5 = LogData( - log_record=SDKLogRecord( + log5 = SDKLogRecord( + LogRecord( timestamp=1644650584292683009, observed_timestamp=1644650584292683010, context=ctx_log5, severity_text="INFO", severity_number=SeverityNumber.INFO, body={"error": None, "array_with_nones": [1, None, 2]}, - resource=SDKResource({}), attributes={}, ), + resource=SDKResource({}), instrumentation_scope=InstrumentationScope( "last_name", "last_version" ), @@ -222,20 +221,20 @@ def _get_sdk_log_data() -> List[LogData]: ) ) ) - log6 = LogData( - log_record=SDKLogRecord( + log6 = SDKLogRecord( + LogRecord( timestamp=1644650584292683022, observed_timestamp=1644650584292683022, context=ctx_log6, severity_text="ERROR", severity_number=SeverityNumber.ERROR, body="This instrumentation scope has a schema url", - resource=SDKResource( - {"first_resource": "value"}, - "resource_schema_url", - ), attributes={"filename": "model.py", "func_name": "run_method"}, ), + resource=SDKResource( + {"first_resource": "value"}, + "resource_schema_url", + ), instrumentation_scope=InstrumentationScope( "scope_with_url", "scope_with_url_version", @@ -253,20 +252,20 @@ def _get_sdk_log_data() -> List[LogData]: ) ) ) - log7 = LogData( - log_record=SDKLogRecord( + log7 = SDKLogRecord( + LogRecord( timestamp=1644650584292683033, observed_timestamp=1644650584292683033, context=ctx_log7, severity_text="FATAL", severity_number=SeverityNumber.FATAL, body="This instrumentation scope has a schema url and attributes", - resource=SDKResource( - {"first_resource": "value"}, - "resource_schema_url", - ), attributes={"filename": "model.py", "func_name": "run_method"}, ), + resource=SDKResource( + {"first_resource": "value"}, + "resource_schema_url", + ), instrumentation_scope=InstrumentationScope( "scope_with_attributes", "scope_with_attributes_version", @@ -285,21 +284,21 @@ def _get_sdk_log_data() -> List[LogData]: ) ) ) - log8 = LogData( - log_record=SDKLogRecord( + log8 = SDKLogRecord( + LogRecord( timestamp=1644650584292683044, observed_timestamp=1644650584292683044, context=ctx_log8, severity_text="INFO", severity_number=SeverityNumber.INFO, body="Test export of extended attributes", - resource=SDKResource({}), attributes={ "extended": { "sequence": [{"inner": "mapping", "none": None}] } }, ), + resource=SDKResource({}), instrumentation_scope=InstrumentationScope( "extended_name", "extended_version" ), @@ -601,7 +600,7 @@ def get_test_logs( return sdk_logs, pb2_service_request @staticmethod - def _get_test_logs_dropped_attributes() -> List[LogData]: + def _get_test_logs_dropped_attributes() -> List[SDKLogRecord]: ctx_log1 = set_span_in_context( NonRecordingSpan( SpanContext( @@ -612,17 +611,17 @@ def _get_test_logs_dropped_attributes() -> List[LogData]: ) ) ) - log1 = LogData( - log_record=SDKLogRecord( + log1 = SDKLogRecord( + LogRecord( timestamp=1644650195189786880, context=ctx_log1, severity_text="WARN", severity_number=SeverityNumber.WARN, body="Do not go gentle into that good night. Rage, rage against the dying of the light", - resource=SDKResource({"first_resource": "value"}), attributes={"a": 1, "b": "c", "user_id": "B121092"}, - limits=LogLimits(max_attributes=1), ), + resource=SDKResource({"first_resource": "value"}), + limits=LogLimits(max_attributes=1), instrumentation_scope=InstrumentationScope( "first_name", "first_version" ), @@ -630,16 +629,16 @@ def _get_test_logs_dropped_attributes() -> List[LogData]: ctx_log2 = set_span_in_context( NonRecordingSpan(SpanContext(0, 0, False)) ) - log2 = LogData( - log_record=SDKLogRecord( + log2 = SDKLogRecord( + LogRecord( timestamp=1644650249738562048, context=ctx_log2, severity_text="WARN", severity_number=SeverityNumber.WARN, body="Cooper, this is no time for caution!", - resource=SDKResource({"second_resource": "CASE"}), attributes={}, ), + resource=SDKResource({"second_resource": "CASE"}), instrumentation_scope=InstrumentationScope( "second_name", "second_version" ), diff --git a/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/_log_exporter/__init__.py b/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/_log_exporter/__init__.py index 70f3df444a4..1989a254fa0 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/_log_exporter/__init__.py +++ b/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/_log_exporter/__init__.py @@ -28,8 +28,7 @@ from opentelemetry.proto.collector.logs.v1.logs_service_pb2_grpc import ( LogsServiceStub, ) -from opentelemetry.sdk._logs import LogData -from opentelemetry.sdk._logs import LogRecord as SDKLogRecord +from opentelemetry.sdk._logs import SDKLogRecord from opentelemetry.sdk._logs.export import LogExporter, LogExportResult from opentelemetry.sdk.environment_variables import ( OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE, @@ -105,11 +104,11 @@ def __init__( ) def _translate_data( - self, data: Sequence[LogData] + self, data: Sequence[SDKLogRecord] ) -> ExportLogsServiceRequest: return encode_logs(data) - def export(self, batch: Sequence[LogData]) -> LogExportResult: + def export(self, batch: Sequence[SDKLogRecord]) -> LogExportResult: return self._export(batch) def shutdown(self, timeout_millis: float = 30_000, **kwargs) -> None: 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 a8e015e8216..c963cffb87c 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 @@ -22,7 +22,7 @@ from google.protobuf.json_format import MessageToDict from grpc import ChannelCredentials, Compression -from opentelemetry._logs import SeverityNumber +from opentelemetry._logs import LogRecord, SeverityNumber from opentelemetry.exporter.otlp.proto.common._internal import _encode_value from opentelemetry.exporter.otlp.proto.grpc._log_exporter import ( OTLPLogExporter, @@ -39,7 +39,7 @@ from opentelemetry.proto.resource.v1.resource_pb2 import ( Resource as OTLPResource, ) -from opentelemetry.sdk._logs import LogData, LogRecord +from opentelemetry.sdk._logs import SDKLogRecord from opentelemetry.sdk.environment_variables import ( OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE, OTEL_EXPORTER_OTLP_LOGS_CLIENT_CERTIFICATE, @@ -74,16 +74,16 @@ def setUp(self): ) ) ) - self.log_data_1 = LogData( - log_record=LogRecord( + self.log_data_1 = SDKLogRecord( + LogRecord( timestamp=int(time.time() * 1e9), context=ctx_log_data_1, severity_text="WARNING", severity_number=SeverityNumber.WARN, body="Zhengzhou, We have a heaviest rains in 1000 years", - resource=SDKResource({"key": "value"}), attributes={"a": 1, "b": "c"}, ), + resource=SDKResource({"key": "value"}), instrumentation_scope=InstrumentationScope( "first_name", "first_version" ), @@ -98,16 +98,16 @@ def setUp(self): ) ) ) - self.log_data_2 = LogData( - log_record=LogRecord( + self.log_data_2 = SDKLogRecord( + LogRecord( timestamp=int(time.time() * 1e9), context=ctx_log_data_2, severity_text="INFO", severity_number=SeverityNumber.INFO2, body="Sydney, Opera House is closed", - resource=SDKResource({"key": "value"}), attributes={"custom_attr": [1, 2, 3]}, ), + resource=SDKResource({"key": "value"}), instrumentation_scope=InstrumentationScope( "second_name", "second_version" ), @@ -122,15 +122,15 @@ def setUp(self): ) ) ) - self.log_data_3 = LogData( - log_record=LogRecord( + self.log_data_3 = SDKLogRecord( + LogRecord( timestamp=int(time.time() * 1e9), context=ctx_log_data_3, severity_text="ERROR", severity_number=SeverityNumber.WARN, body="Mumbai, Boil water before drinking", - resource=SDKResource({"service": "myapp"}), ), + resource=SDKResource({"service": "myapp"}), instrumentation_scope=InstrumentationScope( "third_name", "third_version" ), @@ -140,15 +140,15 @@ def setUp(self): SpanContext(0, 5213367945872657629, False, TraceFlags(0x01)) ) ) - self.log_data_4 = LogData( - log_record=LogRecord( + self.log_data_4 = SDKLogRecord( + LogRecord( timestamp=int(time.time() * 1e9), context=ctx_log_data_4, severity_text="ERROR", severity_number=SeverityNumber.WARN, body="Invalid trace id check", - resource=SDKResource({"service": "myapp"}), ), + resource=SDKResource({"service": "myapp"}), instrumentation_scope=InstrumentationScope( "fourth_name", "fourth_version" ), @@ -163,15 +163,15 @@ def setUp(self): ) ) ) - self.log_data_5 = LogData( - log_record=LogRecord( + self.log_data_5 = SDKLogRecord( + LogRecord( timestamp=int(time.time() * 1e9), context=ctx_log_data_5, severity_text="ERROR", severity_number=SeverityNumber.WARN, body="Invalid span id check", - resource=SDKResource({"service": "myapp"}), ), + resource=SDKResource({"service": "myapp"}), instrumentation_scope=InstrumentationScope( "fifth_name", "fifth_version" ), diff --git a/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/_log_exporter/__init__.py b/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/_log_exporter/__init__.py index 765bc5c7f5b..ef02bb45739 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/_log_exporter/__init__.py +++ b/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/_log_exporter/__init__.py @@ -33,7 +33,7 @@ from opentelemetry.exporter.otlp.proto.http._common import ( _is_retryable, ) -from opentelemetry.sdk._logs import LogData +from opentelemetry.sdk._logs import SDKLogRecord from opentelemetry.sdk._logs.export import ( LogExporter, LogExportResult, @@ -163,7 +163,7 @@ def _export( ) return resp - def export(self, batch: Sequence[LogData]) -> LogExportResult: + def export(self, batch: Sequence[SDKLogRecord]) -> LogExportResult: if self._shutdown: _logger.warning("Exporter already shutdown, ignoring batch") return LogExportResult.FAILURE 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 19183029edc..5106b2957d0 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 @@ -26,7 +26,7 @@ from requests import Session from requests.models import Response -from opentelemetry._logs import SeverityNumber +from opentelemetry._logs import LogRecord, SeverityNumber from opentelemetry.exporter.otlp.proto.http import Compression from opentelemetry.exporter.otlp.proto.http._log_exporter import ( DEFAULT_COMPRESSION, @@ -39,8 +39,7 @@ from opentelemetry.proto.collector.logs.v1.logs_service_pb2 import ( ExportLogsServiceRequest, ) -from opentelemetry.sdk._logs import LogData -from opentelemetry.sdk._logs import LogRecord as SDKLogRecord +from opentelemetry.sdk._logs import SDKLogRecord from opentelemetry.sdk._logs.export import LogExportResult from opentelemetry.sdk.environment_variables import ( OTEL_EXPORTER_OTLP_CERTIFICATE, @@ -233,16 +232,16 @@ def test_exported_log_without_trace_id(self): ) ) ) - log = LogData( - log_record=SDKLogRecord( + log = SDKLogRecord( + LogRecord( timestamp=1644650195189786182, context=ctx, severity_text="WARN", severity_number=SeverityNumber.WARN, body="Invalid trace id check", - resource=SDKResource({"first_resource": "value"}), attributes={"a": 1, "b": "c"}, ), + resource=SDKResource({"first_resource": "value"}), instrumentation_scope=InstrumentationScope("name", "version"), ) log_records = TestOTLPHTTPLogExporter.export_log_and_deserialize(log) @@ -269,16 +268,16 @@ def test_exported_log_without_span_id(self): ) ) - log = LogData( - log_record=SDKLogRecord( + log = SDKLogRecord( + LogRecord( timestamp=1644650195189786360, context=ctx, severity_text="WARN", severity_number=SeverityNumber.WARN, body="Invalid span id check", - resource=SDKResource({"first_resource": "value"}), attributes={"a": 1, "b": "c"}, ), + resource=SDKResource({"first_resource": "value"}), instrumentation_scope=InstrumentationScope("name", "version"), ) log_records = TestOTLPHTTPLogExporter.export_log_and_deserialize(log) @@ -294,7 +293,7 @@ def test_exported_log_without_span_id(self): self.fail("No log records found") @staticmethod - def _get_sdk_log_data() -> List[LogData]: + def _get_sdk_log_data() -> List[SDKLogRecord]: ctx_log1 = set_span_in_context( NonRecordingSpan( SpanContext( @@ -305,16 +304,16 @@ def _get_sdk_log_data() -> List[LogData]: ) ) ) - log1 = LogData( - log_record=SDKLogRecord( + log1 = SDKLogRecord( + LogRecord( timestamp=1644650195189786880, context=ctx_log1, severity_text="WARN", severity_number=SeverityNumber.WARN, body="Do not go gentle into that good night. Rage, rage against the dying of the light", - resource=SDKResource({"first_resource": "value"}), attributes={"a": 1, "b": "c"}, ), + resource=SDKResource({"first_resource": "value"}), instrumentation_scope=InstrumentationScope( "first_name", "first_version" ), @@ -329,16 +328,16 @@ def _get_sdk_log_data() -> List[LogData]: ) ) ) - log2 = LogData( - log_record=SDKLogRecord( + log2 = SDKLogRecord( + LogRecord( timestamp=1644650249738562048, context=ctx_log2, severity_text="WARN", severity_number=SeverityNumber.WARN, body="Cooper, this is no time for caution!", - resource=SDKResource({"second_resource": "CASE"}), attributes={}, ), + resource=SDKResource({"second_resource": "CASE"}), instrumentation_scope=InstrumentationScope( "second_name", "second_version" ), @@ -353,16 +352,16 @@ def _get_sdk_log_data() -> List[LogData]: ) ) ) - log3 = LogData( - log_record=SDKLogRecord( + log3 = SDKLogRecord( + LogRecord( timestamp=1644650427658989056, context=ctx_log3, severity_text="DEBUG", severity_number=SeverityNumber.DEBUG, body="To our galaxy", - resource=SDKResource({"second_resource": "CASE"}), attributes={"a": 1, "b": "c"}, ), + resource=SDKResource({"second_resource": "CASE"}), instrumentation_scope=None, ) ctx_log4 = set_span_in_context( @@ -375,16 +374,16 @@ def _get_sdk_log_data() -> List[LogData]: ) ) ) - log4 = LogData( - log_record=SDKLogRecord( + log4 = SDKLogRecord( + LogRecord( timestamp=1644650584292683008, context=ctx_log4, severity_text="INFO", severity_number=SeverityNumber.INFO, body="Love is the one thing that transcends time and space", - resource=SDKResource({"first_resource": "value"}), attributes={"filename": "model.py", "func_name": "run_method"}, ), + resource=SDKResource({"first_resource": "value"}), instrumentation_scope=InstrumentationScope( "another_name", "another_version" ), diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_events/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_events/__init__.py index c427a48e2f8..8a09497cac0 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_events/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_events/__init__.py @@ -15,12 +15,16 @@ 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.sdk._logs import Logger, LoggerProvider, LogRecord +from opentelemetry._logs import ( + LogRecord, + NoOpLogger, + SeverityNumber, + get_logger_provider, +) +from opentelemetry.sdk._logs import Logger, LoggerProvider, SDKLogRecord from opentelemetry.util.types import _ExtendedAttributes _logger = logging.getLogger(__name__) @@ -49,18 +53,16 @@ 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, - severity_text=None, - severity_number=event.severity_number or SeverityNumber.INFO, - body=event.body, + log_record = SDKLogRecord( + LogRecord( + timestamp=event.timestamp or time_ns(), + observed_timestamp=None, + severity_text=None, + severity_number=event.severity_number or SeverityNumber.INFO, + body=event.body, + attributes=event.attributes, + ), resource=getattr(self._logger, "resource", None), - attributes=event.attributes, ) self._logger.emit(log_record) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py index dbb108b7dba..ffcb02b1061 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py @@ -14,25 +14,21 @@ from opentelemetry.sdk._logs._internal import ( - LogData, - LogDeprecatedInitWarning, LogDroppedAttributesWarning, Logger, LoggerProvider, LoggingHandler, LogLimits, - LogRecord, LogRecordProcessor, + SDKLogRecord, ) __all__ = [ - "LogData", "Logger", "LoggerProvider", "LoggingHandler", "LogLimits", - "LogRecord", "LogRecordProcessor", - "LogDeprecatedInitWarning", "LogDroppedAttributesWarning", + "SDKLogRecord", ] diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py index 505904839b8..5507f035e43 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py @@ -27,12 +27,10 @@ from time import time_ns from typing import Any, Callable, Tuple, Union, cast, overload # noqa -from typing_extensions import deprecated - from opentelemetry._logs import Logger as APILogger from opentelemetry._logs import LoggerProvider as APILoggerProvider -from opentelemetry._logs import LogRecord as APILogRecord from opentelemetry._logs import ( + LogRecord, NoOpLogger, SeverityNumber, get_logger, @@ -40,7 +38,6 @@ ) from opentelemetry.attributes import _VALID_ANY_VALUE_TYPES, BoundedAttributes from opentelemetry.context import get_current -from opentelemetry.context.context import Context from opentelemetry.sdk.environment_variables import ( OTEL_ATTRIBUTE_COUNT_LIMIT, OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT, @@ -54,12 +51,8 @@ from opentelemetry.trace import ( format_span_id, format_trace_id, - get_current_span, ) -from opentelemetry.trace.span import TraceFlags -from opentelemetry.util.types import AnyValue, _ExtendedAttributes - -_logger = logging.getLogger(__name__) +from opentelemetry.util.types import _ExtendedAttributes _DEFAULT_OTEL_ATTRIBUTE_COUNT_LIMIT = 128 _ENV_VALUE_UNSET = "" @@ -84,18 +77,6 @@ class LogDroppedAttributesWarning(UserWarning): warnings.simplefilter("once", LogDroppedAttributesWarning) -class LogDeprecatedInitWarning(UserWarning): - """Custom warning to indicate deprecated LogRecord init was used. - - This class is used to filter and handle these specific warnings separately - from other warnings, ensuring that they are only shown once without - interfering with default user warnings. - """ - - -warnings.simplefilter("once", LogDeprecatedInitWarning) - - class LogLimits: """This class is based on a SpanLimits class in the Tracing module. @@ -187,10 +168,10 @@ def _from_env_if_absent( ) -class LogRecord(APILogRecord): - """A LogRecord instance represents an event being logged. +class SDKLogRecord: + """A SDKLogRecord instance represents an event being logged. - LogRecord instances are created and emitted via `Logger` + SDKLogRecord instances are created and emitted via `Logger` every time something is logged. They contain all the information pertinent to the event being logged. """ @@ -198,90 +179,31 @@ class LogRecord(APILogRecord): @overload def __init__( self, - timestamp: int | None = None, - observed_timestamp: int | None = None, - context: Context | None = None, - severity_text: str | None = None, - severity_number: SeverityNumber | None = None, - body: AnyValue | None = None, + log_record: LogRecord, resource: Resource | None = None, - attributes: _ExtendedAttributes | None = None, limits: LogLimits | None = _UnsetLogLimits, - event_name: str | None = None, ): ... - @overload - @deprecated( - "LogRecord init with `trace_id`, `span_id`, and/or `trace_flags` is deprecated since 1.35.0. Use `context` instead." # noqa: E501 - ) 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, - severity_text: str | None = None, - severity_number: SeverityNumber | None = None, - body: AnyValue | None = None, - resource: Resource | None = None, - attributes: _ExtendedAttributes | None = None, - limits: LogLimits | None = _UnsetLogLimits, - ): ... - - def __init__( # pylint:disable=too-many-locals - self, - timestamp: int | None = None, - observed_timestamp: int | None = None, - context: Context | None = None, - trace_id: int | None = None, - span_id: int | None = None, - trace_flags: TraceFlags | None = None, - severity_text: str | None = None, - severity_number: SeverityNumber | None = None, - body: AnyValue | None = None, + log_record: LogRecord, resource: Resource | None = None, - attributes: _ExtendedAttributes | None = None, limits: LogLimits | None = _UnsetLogLimits, - event_name: str | None = None, + instrumentation_scope: InstrumentationScope | None = None, ): - if trace_id or span_id or trace_flags: - warnings.warn( - "LogRecord init with `trace_id`, `span_id`, and/or `trace_flags` is deprecated since 1.35.0. Use `context` instead.", - LogDeprecatedInitWarning, - stacklevel=2, - ) - - if not context: - context = get_current() - - span = get_current_span(context) - span_context = span.get_span_context() - - super().__init__( - **{ - "timestamp": timestamp, - "observed_timestamp": observed_timestamp, - "context": context, - "trace_id": trace_id or span_context.trace_id, - "span_id": span_id or span_context.span_id, - "trace_flags": trace_flags or span_context.trace_flags, - "severity_text": severity_text, - "severity_number": severity_number, - "body": body, - "attributes": BoundedAttributes( - maxlen=limits.max_attributes, - attributes=attributes if bool(attributes) else None, - immutable=False, - max_value_len=limits.max_attribute_length, - extended_attributes=True, - ), - "event_name": event_name, - } - ) - self.resource = ( - resource if isinstance(resource, Resource) else Resource.create({}) + self.log_record = log_record + self.log_record.attributes = BoundedAttributes( + maxlen=limits.max_attributes, + attributes=self.log_record.attributes + if self.log_record.attributes + else None, + immutable=False, + max_value_len=limits.max_attribute_length, + extended_attributes=True, ) + + self.resource = resource if resource else Resource.create({}) + self.instrumentation_scope = instrumentation_scope if self.dropped_attributes > 0: warnings.warn( "Log record attributes were dropped due to limits", @@ -290,37 +212,41 @@ def __init__( # pylint:disable=too-many-locals ) def __eq__(self, other: object) -> bool: - if not isinstance(other, LogRecord): + if not isinstance(other, SDKLogRecord): return NotImplemented return self.__dict__ == other.__dict__ def to_json(self, indent: int | None = 4) -> str: return json.dumps( { - "body": self.body, - "severity_number": self.severity_number.value - if self.severity_number is not None + "body": self.log_record.body, + "severity_number": self.log_record.severity_number.value + if self.log_record.severity_number is not None else None, - "severity_text": self.severity_text, + "severity_text": self.log_record.severity_text, "attributes": ( - dict(self.attributes) if bool(self.attributes) else None + dict(self.log_record.attributes) + if bool(self.log_record.attributes) + else None ), "dropped_attributes": self.dropped_attributes, - "timestamp": ns_to_iso_str(self.timestamp), - "observed_timestamp": ns_to_iso_str(self.observed_timestamp), + "timestamp": ns_to_iso_str(self.log_record.timestamp), + "observed_timestamp": ns_to_iso_str( + self.log_record.observed_timestamp + ), "trace_id": ( - f"0x{format_trace_id(self.trace_id)}" - if self.trace_id is not None + f"0x{format_trace_id(self.log_record.trace_id)}" + if self.log_record.trace_id is not None else "" ), "span_id": ( - f"0x{format_span_id(self.span_id)}" - if self.span_id is not None + f"0x{format_span_id(self.log_record.span_id)}" + if self.log_record.span_id is not None else "" ), - "trace_flags": self.trace_flags, + "trace_flags": self.log_record.trace_flags, "resource": json.loads(self.resource.to_json()), - "event_name": self.event_name if self.event_name else "", + "event_name": self.log_record.event_name or "", }, indent=indent, cls=BytesEncoder, @@ -328,26 +254,11 @@ def to_json(self, indent: int | None = 4) -> str: @property def dropped_attributes(self) -> int: - attributes: BoundedAttributes = cast( - BoundedAttributes, self.attributes - ) - if attributes: - return attributes.dropped + if isinstance(self.log_record.attributes, BoundedAttributes): + return self.log_record.attributes.dropped return 0 -class LogData: - """Readable LogRecord data plus associated InstrumentationLibrary.""" - - def __init__( - self, - log_record: LogRecord, - instrumentation_scope: InstrumentationScope, - ): - self.log_record = log_record - self.instrumentation_scope = instrumentation_scope - - class LogRecordProcessor(abc.ABC): """Interface to hook the log record emitting action. @@ -357,8 +268,8 @@ class LogRecordProcessor(abc.ABC): """ @abc.abstractmethod - def on_emit(self, log_data: LogData): - """Emits the `LogData`""" + def on_emit(self, log_record: SDKLogRecord): + """Emits the `SDKLogRecord`""" @abc.abstractmethod def shutdown(self): @@ -401,9 +312,9 @@ def add_log_record_processor( with self._lock: self._log_record_processors += (log_record_processor,) - def on_emit(self, log_data: LogData) -> None: + def on_emit(self, log_record: SDKLogRecord) -> None: for lp in self._log_record_processors: - lp.on_emit(log_data) + lp.on_emit(log_record) def shutdown(self) -> None: """Shutdown the log processors one by one""" @@ -475,8 +386,8 @@ def _submit_and_wait( for future in futures: future.result() - def on_emit(self, log_data: LogData): - self._submit_and_wait(lambda lp: lp.on_emit, log_data) + def on_emit(self, log_record: SDKLogRecord): + self._submit_and_wait(lambda lp: lp.on_emit, log_record) def shutdown(self): self._submit_and_wait(lambda lp: lp.shutdown) @@ -619,7 +530,6 @@ def _translate(self, record: logging.LogRecord) -> LogRecord: "WARN" if record.levelname == "WARNING" else record.levelname ) - logger = get_logger(record.name, logger_provider=self._logger_provider) return LogRecord( timestamp=timestamp, observed_timestamp=observered_timestamp, @@ -627,7 +537,6 @@ def _translate(self, record: logging.LogRecord) -> LogRecord: severity_text=level_name, severity_number=severity_number, body=body, - resource=logger.resource, attributes=attributes, ) @@ -679,11 +588,15 @@ def resource(self): return self._resource def emit(self, record: LogRecord): - """Emits the :class:`LogData` by associating :class:`LogRecord` - and instrumentation info. + """Emits the :class:`SDKLogRecord` by setting instrumentation scope + and forwarding to the processor. """ - log_data = LogData(record, self._instrumentation_scope) - self._multi_log_record_processor.on_emit(log_data) + sdk_log_record = SDKLogRecord( + log_record=record, + resource=self._resource, + instrumentation_scope=self._instrumentation_scope, + ) + self._multi_log_record_processor.on_emit(sdk_log_record) class LoggerProvider(APILoggerProvider): diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py index ec629221b86..4946d9b9162 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py @@ -26,7 +26,7 @@ detach, set_value, ) -from opentelemetry.sdk._logs import LogData, LogRecord, LogRecordProcessor +from opentelemetry.sdk._logs import LogRecordProcessor, SDKLogRecord from opentelemetry.sdk._shared_internal import BatchProcessor from opentelemetry.sdk.environment_variables import ( OTEL_BLRP_EXPORT_TIMEOUT, @@ -59,10 +59,10 @@ class LogExporter(abc.ABC): """ @abc.abstractmethod - def export(self, batch: Sequence[LogData]): + def export(self, batch: Sequence[SDKLogRecord]): """Exports a batch of logs. Args: - batch: The list of `LogData` objects to be exported + batch: The list of `SDKLogRecord` objects to be exported Returns: The result of the export """ @@ -86,15 +86,16 @@ class ConsoleLogExporter(LogExporter): def __init__( self, out: IO = sys.stdout, - formatter: Callable[[LogRecord], str] = lambda record: record.to_json() - + linesep, + formatter: Callable[ + [SDKLogRecord], str + ] = lambda record: record.to_json() + linesep, ): self.out = out self.formatter = formatter - def export(self, batch: Sequence[LogData]): - for data in batch: - self.out.write(self.formatter(data.log_record)) + def export(self, batch: Sequence[SDKLogRecord]): + for log_record in batch: + self.out.write(self.formatter(log_record)) self.out.flush() return LogExportResult.SUCCESS @@ -104,21 +105,20 @@ def shutdown(self): class SimpleLogRecordProcessor(LogRecordProcessor): """This is an implementation of LogRecordProcessor which passes - received logs in the export-friendly LogData representation to the - configured LogExporter, as soon as they are emitted. + received logs directly to the configured LogExporter, as soon as they are emitted. """ def __init__(self, exporter: LogExporter): self._exporter = exporter self._shutdown = False - def on_emit(self, log_data: LogData): + def on_emit(self, log_record: SDKLogRecord): if self._shutdown: _logger.warning("Processor is already shutdown, ignoring call") return token = attach(set_value(_SUPPRESS_INSTRUMENTATION_KEY, True)) try: - self._exporter.export((log_data,)) + self._exporter.export((log_record,)) except Exception: # pylint: disable=broad-exception-caught _logger.exception("Exception while exporting logs.") detach(token) @@ -133,8 +133,7 @@ def force_flush(self, timeout_millis: int = 30000) -> bool: # pylint: disable=n class BatchLogRecordProcessor(LogRecordProcessor): """This is an implementation of LogRecordProcessor which creates batches of - received logs in the export-friendly LogData representation and - send to the configured LogExporter, as soon as they are emitted. + received logs and sends them to the configured LogExporter. `BatchLogRecordProcessor` is configurable with the following environment variables which correspond to constructor parameters: @@ -186,8 +185,8 @@ def __init__( "Log", ) - def on_emit(self, log_data: LogData) -> None: - return self._batch_processor.emit(log_data) + def on_emit(self, log_record: SDKLogRecord) -> None: + return self._batch_processor.emit(log_record) def shutdown(self): return self._batch_processor.shutdown() diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/in_memory_log_exporter.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/in_memory_log_exporter.py index 68cb6b7389a..c947995d045 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/in_memory_log_exporter.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/in_memory_log_exporter.py @@ -15,7 +15,7 @@ import threading import typing -from opentelemetry.sdk._logs import LogData +from opentelemetry.sdk._logs import SDKLogRecord from opentelemetry.sdk._logs.export import LogExporter, LogExportResult @@ -36,11 +36,11 @@ def clear(self) -> None: with self._lock: self._logs.clear() - def get_finished_logs(self) -> typing.Tuple[LogData, ...]: + def get_finished_logs(self) -> typing.Tuple[SDKLogRecord, ...]: with self._lock: return tuple(self._logs) - def export(self, batch: typing.Sequence[LogData]) -> LogExportResult: + def export(self, batch: typing.Sequence[SDKLogRecord]) -> LogExportResult: if self._stopped: return LogExportResult.FAILURE with self._lock: diff --git a/opentelemetry-sdk/tests/events/test_events.py b/opentelemetry-sdk/tests/events/test_events.py index 7b8d42ff316..c21acb4c568 100644 --- a/opentelemetry-sdk/tests/events/test_events.py +++ b/opentelemetry-sdk/tests/events/test_events.py @@ -107,7 +107,7 @@ def test_event_logger(self, logger_mock): "name", "version", "schema_url", {"key": "value"} ) - @patch("opentelemetry.sdk._events.LogRecord") + @patch("opentelemetry.sdk._events.SDKLogRecord") @patch("opentelemetry.sdk._logs._internal.LoggerProvider.get_logger") def test_event_logger_emit(self, logger_mock, log_record_mock): logger_provider = LoggerProvider() @@ -143,25 +143,9 @@ def test_event_logger_emit(self, logger_mock, log_record_mock): log_record_mock_inst = Mock() log_record_mock.return_value = log_record_mock_inst event_logger.emit(event) - log_record_mock.assert_called_once_with( - timestamp=now, - observed_timestamp=None, - trace_id=trace_id, - span_id=span_id, - trace_flags=trace_flags, - severity_text=None, - severity_number=SeverityNumber.ERROR, - body="test body", - resource=event_logger._logger.resource, - attributes={ - "key": "val", - "foo": "bar", - "event.name": "test_event", - }, - ) logger_mock_inst.emit.assert_called_once_with(log_record_mock_inst) - @patch("opentelemetry.sdk._events.LogRecord") + @patch("opentelemetry.sdk._events.SDKLogRecord") @patch("opentelemetry.sdk._logs._internal.LoggerProvider.get_logger") def test_event_logger_emit_sdk_disabled( self, logger_mock, log_record_mock diff --git a/opentelemetry-sdk/tests/logs/test_export.py b/opentelemetry-sdk/tests/logs/test_export.py index 4b8d98693c5..e4ef5760b98 100644 --- a/opentelemetry-sdk/tests/logs/test_export.py +++ b/opentelemetry-sdk/tests/logs/test_export.py @@ -23,13 +23,12 @@ from pytest import mark -from opentelemetry._logs import SeverityNumber +from opentelemetry._logs import LogRecord, SeverityNumber from opentelemetry.sdk import trace from opentelemetry.sdk._logs import ( - LogData, LoggerProvider, LoggingHandler, - LogRecord, + SDKLogRecord, ) from opentelemetry.sdk._logs._internal.export import _logger from opentelemetry.sdk._logs.export import ( @@ -54,7 +53,7 @@ ) from opentelemetry.trace.span import INVALID_SPAN_CONTEXT -EMPTY_LOG = LogData( +EMPTY_LOG = SDKLogRecord( log_record=LogRecord(), instrumentation_scope=InstrumentationScope("example", "example"), ) @@ -76,11 +75,13 @@ def test_simple_log_record_processor_default_level(self): logger.warning("Something is wrong") finished_logs = exporter.get_finished_logs() self.assertEqual(len(finished_logs), 1) - warning_log_record = finished_logs[0].log_record - self.assertEqual(warning_log_record.body, "Something is wrong") - self.assertEqual(warning_log_record.severity_text, "WARN") + warning_log_record = finished_logs[0] self.assertEqual( - warning_log_record.severity_number, SeverityNumber.WARN + warning_log_record.log_record.body, "Something is wrong" + ) + self.assertEqual(warning_log_record.log_record.severity_text, "WARN") + self.assertEqual( + warning_log_record.log_record.severity_number, SeverityNumber.WARN ) self.assertEqual( finished_logs[0].instrumentation_scope.name, "default_level" @@ -106,17 +107,18 @@ def test_simple_log_record_processor_custom_level(self): finished_logs = exporter.get_finished_logs() # Make sure only level >= logging.CRITICAL logs are recorded self.assertEqual(len(finished_logs), 2) - critical_log_record = finished_logs[0].log_record - fatal_log_record = finished_logs[1].log_record - self.assertEqual(critical_log_record.body, "Error message") - self.assertEqual(critical_log_record.severity_text, "ERROR") + critical_log_record = finished_logs[0] + fatal_log_record = finished_logs[1] + self.assertEqual(critical_log_record.log_record.body, "Error message") + self.assertEqual(critical_log_record.log_record.severity_text, "ERROR") self.assertEqual( - critical_log_record.severity_number, SeverityNumber.ERROR + critical_log_record.log_record.severity_number, + SeverityNumber.ERROR, ) - self.assertEqual(fatal_log_record.body, "Critical message") - self.assertEqual(fatal_log_record.severity_text, "CRITICAL") + self.assertEqual(fatal_log_record.log_record.body, "Critical message") + self.assertEqual(fatal_log_record.log_record.severity_text, "CRITICAL") self.assertEqual( - fatal_log_record.severity_number, SeverityNumber.FATAL + fatal_log_record.log_record.severity_number, SeverityNumber.FATAL ) self.assertEqual( finished_logs[0].instrumentation_scope.name, "custom_level" @@ -140,14 +142,20 @@ def test_simple_log_record_processor_trace_correlation(self): logger.warning("Warning message") finished_logs = exporter.get_finished_logs() self.assertEqual(len(finished_logs), 1) - log_record = finished_logs[0].log_record - self.assertEqual(log_record.body, "Warning message") - self.assertEqual(log_record.severity_text, "WARN") - self.assertEqual(log_record.severity_number, SeverityNumber.WARN) - self.assertEqual(log_record.trace_id, INVALID_SPAN_CONTEXT.trace_id) - self.assertEqual(log_record.span_id, INVALID_SPAN_CONTEXT.span_id) + sdk_record = finished_logs[0] + self.assertEqual(sdk_record.log_record.body, "Warning message") + self.assertEqual(sdk_record.log_record.severity_text, "WARN") + self.assertEqual( + sdk_record.log_record.severity_number, SeverityNumber.WARN + ) + self.assertEqual( + sdk_record.log_record.trace_id, INVALID_SPAN_CONTEXT.trace_id + ) + self.assertEqual( + sdk_record.log_record.span_id, INVALID_SPAN_CONTEXT.span_id + ) self.assertEqual( - log_record.trace_flags, INVALID_SPAN_CONTEXT.trace_flags + sdk_record.log_record.trace_flags, INVALID_SPAN_CONTEXT.trace_flags ) self.assertEqual( finished_logs[0].instrumentation_scope.name, "trace_correlation" @@ -159,18 +167,28 @@ def test_simple_log_record_processor_trace_correlation(self): logger.critical("Critical message within span") finished_logs = exporter.get_finished_logs() - log_record = finished_logs[0].log_record - self.assertEqual(log_record.body, "Critical message within span") - self.assertEqual(log_record.severity_text, "CRITICAL") - self.assertEqual(log_record.severity_number, SeverityNumber.FATAL) + sdk_record = finished_logs[0] + self.assertEqual( + sdk_record.log_record.body, "Critical message within span" + ) + self.assertEqual(sdk_record.log_record.severity_text, "CRITICAL") + self.assertEqual( + sdk_record.log_record.severity_number, SeverityNumber.FATAL + ) self.assertEqual( finished_logs[0].instrumentation_scope.name, "trace_correlation", ) span_context = span.get_span_context() - self.assertEqual(log_record.trace_id, span_context.trace_id) - self.assertEqual(log_record.span_id, span_context.span_id) - self.assertEqual(log_record.trace_flags, span_context.trace_flags) + self.assertEqual( + sdk_record.log_record.trace_id, span_context.trace_id + ) + self.assertEqual( + sdk_record.log_record.span_id, span_context.span_id + ) + self.assertEqual( + sdk_record.log_record.trace_flags, span_context.trace_flags + ) def test_simple_log_record_processor_shutdown(self): exporter = InMemoryLogExporter() @@ -187,11 +205,13 @@ def test_simple_log_record_processor_shutdown(self): logger.warning("Something is wrong") finished_logs = exporter.get_finished_logs() self.assertEqual(len(finished_logs), 1) - warning_log_record = finished_logs[0].log_record - self.assertEqual(warning_log_record.body, "Something is wrong") - self.assertEqual(warning_log_record.severity_text, "WARN") + warning_log_record = finished_logs[0] + self.assertEqual( + warning_log_record.log_record.body, "Something is wrong" + ) + self.assertEqual(warning_log_record.log_record.severity_text, "WARN") self.assertEqual( - warning_log_record.severity_number, SeverityNumber.WARN + warning_log_record.log_record.severity_number, SeverityNumber.WARN ) self.assertEqual( finished_logs[0].instrumentation_scope.name, "shutdown" @@ -608,16 +628,16 @@ def test_export(self): # pylint: disable=no-self-use ) ) ) - log_data = LogData( - log_record=LogRecord( + log_record = SDKLogRecord( + LogRecord( timestamp=int(time.time() * 1e9), context=ctx, severity_text="WARN", severity_number=SeverityNumber.WARN, body="Zhengzhou, We have a heaviest rains in 1000 years", - resource=SDKResource({"key": "value"}), attributes={"a": 1, "b": "c"}, ), + resource=SDKResource({"key": "value"}), instrumentation_scope=InstrumentationScope( "first_name", "first_version" ), @@ -627,9 +647,9 @@ def test_export(self): # pylint: disable=no-self-use # the exporter instance instead. with patch.object(exporter, "out") as mock_stdout: - exporter.export([log_data]) + exporter.export([log_record]) mock_stdout.write.assert_called_once_with( - log_data.log_record.to_json() + os.linesep + log_record.to_json() + os.linesep ) self.assertEqual(mock_stdout.write.call_count, 1) diff --git a/opentelemetry-sdk/tests/logs/test_handler.py b/opentelemetry-sdk/tests/logs/test_handler.py index 55526dc2b6a..22e68dbe27a 100644 --- a/opentelemetry-sdk/tests/logs/test_handler.py +++ b/opentelemetry-sdk/tests/logs/test_handler.py @@ -22,10 +22,10 @@ from opentelemetry.attributes import BoundedAttributes from opentelemetry.sdk import trace from opentelemetry.sdk._logs import ( - LogData, LoggerProvider, LoggingHandler, LogRecordProcessor, + SDKLogRecord, ) from opentelemetry.semconv._incubating.attributes import code_attributes from opentelemetry.semconv.attributes import exception_attributes @@ -99,13 +99,18 @@ def test_log_record_no_span_context(self): with self.assertLogs(level=logging.WARNING): logger.warning("Warning message") - log_record = processor.get_log_record(0) + sdk_log_record = processor.get_log_record(0) - self.assertIsNotNone(log_record) - self.assertEqual(log_record.trace_id, INVALID_SPAN_CONTEXT.trace_id) - self.assertEqual(log_record.span_id, INVALID_SPAN_CONTEXT.span_id) + self.assertIsNotNone(sdk_log_record) self.assertEqual( - log_record.trace_flags, INVALID_SPAN_CONTEXT.trace_flags + sdk_log_record.log_record.trace_id, INVALID_SPAN_CONTEXT.trace_id + ) + self.assertEqual( + sdk_log_record.log_record.span_id, INVALID_SPAN_CONTEXT.span_id + ) + self.assertEqual( + sdk_log_record.log_record.trace_flags, + INVALID_SPAN_CONTEXT.trace_flags, ) def test_log_record_observed_timestamp(self): @@ -114,37 +119,44 @@ def test_log_record_observed_timestamp(self): with self.assertLogs(level=logging.WARNING): logger.warning("Warning message") - log_record = processor.get_log_record(0) - self.assertIsNotNone(log_record.observed_timestamp) + sdk_log_record = processor.get_log_record(0) + self.assertIsNotNone(sdk_log_record.log_record.observed_timestamp) def test_log_record_user_attributes(self): - """Attributes can be injected into logs by adding them to the LogRecord""" + """Attributes can be injected into logs by adding them to the SDKLogRecord""" processor, logger = set_up_test_logging(logging.WARNING) # Assert emit gets called for warning message with self.assertLogs(level=logging.WARNING): logger.warning("Warning message", extra={"http.status_code": 200}) - log_record = processor.get_log_record(0) + sdk_log_record = processor.get_log_record(0) - self.assertIsNotNone(log_record) - self.assertEqual(len(log_record.attributes), 4) - self.assertEqual(log_record.attributes["http.status_code"], 200) + self.assertIsNotNone(sdk_log_record) + self.assertEqual(len(sdk_log_record.log_record.attributes), 4) + self.assertEqual( + sdk_log_record.log_record.attributes["http.status_code"], 200 + ) self.assertTrue( - log_record.attributes[code_attributes.CODE_FILE_PATH].endswith( - "test_handler.py" - ) + sdk_log_record.log_record.attributes[ + code_attributes.CODE_FILE_PATH + ].endswith("test_handler.py") ) self.assertEqual( - log_record.attributes[code_attributes.CODE_FUNCTION_NAME], + sdk_log_record.log_record.attributes[ + code_attributes.CODE_FUNCTION_NAME + ], "test_log_record_user_attributes", ) # The line of the log statement is not a constant (changing tests may change that), # so only check that the attribute is present. self.assertTrue( - code_attributes.CODE_LINE_NUMBER in log_record.attributes + code_attributes.CODE_LINE_NUMBER + in sdk_log_record.log_record.attributes + ) + self.assertTrue( + isinstance(sdk_log_record.log_record.attributes, BoundedAttributes) ) - self.assertTrue(isinstance(log_record.attributes, BoundedAttributes)) def test_log_record_exception(self): """Exception information will be included in attributes""" @@ -156,20 +168,24 @@ def test_log_record_exception(self): with self.assertLogs(level=logging.ERROR): logger.exception("Zero Division Error") - log_record = processor.get_log_record(0) + sdk_log_record = processor.get_log_record(0) - self.assertIsNotNone(log_record) - self.assertTrue(isinstance(log_record.body, str)) - self.assertEqual(log_record.body, "Zero Division Error") + self.assertIsNotNone(sdk_log_record) + self.assertTrue(isinstance(sdk_log_record.log_record.body, str)) + self.assertEqual(sdk_log_record.log_record.body, "Zero Division Error") self.assertEqual( - log_record.attributes[exception_attributes.EXCEPTION_TYPE], + sdk_log_record.log_record.attributes[ + exception_attributes.EXCEPTION_TYPE + ], ZeroDivisionError.__name__, ) self.assertEqual( - log_record.attributes[exception_attributes.EXCEPTION_MESSAGE], + sdk_log_record.log_record.attributes[ + exception_attributes.EXCEPTION_MESSAGE + ], "division by zero", ) - stack_trace = log_record.attributes[ + stack_trace = sdk_log_record.log_record.attributes[ exception_attributes.EXCEPTION_STACKTRACE ] self.assertIsInstance(stack_trace, str) @@ -190,19 +206,23 @@ def test_log_record_recursive_exception(self): with self.assertLogs(level=logging.ERROR): logger.exception("Zero Division Error") - log_record = processor.get_log_record(0) + sdk_log_record = processor.get_log_record(0) - self.assertIsNotNone(log_record) - self.assertEqual(log_record.body, "Zero Division Error") + self.assertIsNotNone(sdk_log_record) + self.assertEqual(sdk_log_record.log_record.body, "Zero Division Error") self.assertEqual( - log_record.attributes[exception_attributes.EXCEPTION_TYPE], + sdk_log_record.log_record.attributes[ + exception_attributes.EXCEPTION_TYPE + ], ZeroDivisionError.__name__, ) self.assertEqual( - log_record.attributes[exception_attributes.EXCEPTION_MESSAGE], + sdk_log_record.log_record.attributes[ + exception_attributes.EXCEPTION_MESSAGE + ], "division by zero", ) - stack_trace = log_record.attributes[ + stack_trace = sdk_log_record.log_record.attributes[ exception_attributes.EXCEPTION_STACKTRACE ] self.assertIsInstance(stack_trace, str) @@ -221,18 +241,21 @@ def test_log_exc_info_false(self): with self.assertLogs(level=logging.ERROR): logger.error("Zero Division Error", exc_info=False) - log_record = processor.get_log_record(0) + sdk_log_record = processor.get_log_record(0) - self.assertIsNotNone(log_record) - self.assertEqual(log_record.body, "Zero Division Error") + self.assertIsNotNone(sdk_log_record) + self.assertEqual(sdk_log_record.log_record.body, "Zero Division Error") self.assertNotIn( - exception_attributes.EXCEPTION_TYPE, log_record.attributes + exception_attributes.EXCEPTION_TYPE, + sdk_log_record.log_record.attributes, ) self.assertNotIn( - exception_attributes.EXCEPTION_MESSAGE, log_record.attributes + exception_attributes.EXCEPTION_MESSAGE, + sdk_log_record.log_record.attributes, ) self.assertNotIn( - exception_attributes.EXCEPTION_STACKTRACE, log_record.attributes + exception_attributes.EXCEPTION_STACKTRACE, + sdk_log_record.log_record.attributes, ) def test_log_record_exception_with_object_payload(self): @@ -248,20 +271,26 @@ def __str__(self): with self.assertLogs(level=logging.ERROR): logger.exception(exception) - log_record = processor.get_log_record(0) + sdk_log_record = processor.get_log_record(0) - self.assertIsNotNone(log_record) - self.assertTrue(isinstance(log_record.body, str)) - self.assertEqual(log_record.body, "CustomException stringified") + self.assertIsNotNone(sdk_log_record) + self.assertTrue(isinstance(sdk_log_record.log_record.body, str)) + self.assertEqual( + sdk_log_record.log_record.body, "CustomException stringified" + ) self.assertEqual( - log_record.attributes[exception_attributes.EXCEPTION_TYPE], + sdk_log_record.log_record.attributes[ + exception_attributes.EXCEPTION_TYPE + ], CustomException.__name__, ) self.assertEqual( - log_record.attributes[exception_attributes.EXCEPTION_MESSAGE], + sdk_log_record.log_record.attributes[ + exception_attributes.EXCEPTION_MESSAGE + ], "CustomException message", ) - stack_trace = log_record.attributes[ + stack_trace = sdk_log_record.log_record.attributes[ exception_attributes.EXCEPTION_STACKTRACE ] self.assertIsInstance(stack_trace, str) @@ -283,21 +312,32 @@ def test_log_record_trace_correlation(self): with self.assertLogs(level=logging.CRITICAL): logger.critical("Critical message within span") - log_record = processor.get_log_record(0) + sdk_log_record = processor.get_log_record(0) self.assertEqual( - log_record.body, "Critical message within span" + sdk_log_record.log_record.body, + "Critical message within span", ) - self.assertEqual(log_record.severity_text, "CRITICAL") self.assertEqual( - log_record.severity_number, SeverityNumber.FATAL + sdk_log_record.log_record.severity_text, "CRITICAL" + ) + self.assertEqual( + sdk_log_record.log_record.severity_number, + SeverityNumber.FATAL, + ) + self.assertEqual( + sdk_log_record.log_record.context, mock_context ) - self.assertEqual(log_record.context, mock_context) span_context = span.get_span_context() - self.assertEqual(log_record.trace_id, span_context.trace_id) - self.assertEqual(log_record.span_id, span_context.span_id) self.assertEqual( - log_record.trace_flags, span_context.trace_flags + sdk_log_record.log_record.trace_id, span_context.trace_id + ) + self.assertEqual( + sdk_log_record.log_record.span_id, span_context.span_id + ) + self.assertEqual( + sdk_log_record.log_record.trace_flags, + span_context.trace_flags, ) def test_log_record_trace_correlation_deprecated(self): @@ -308,29 +348,41 @@ def test_log_record_trace_correlation_deprecated(self): with self.assertLogs(level=logging.CRITICAL): logger.critical("Critical message within span") - log_record = processor.get_log_record(0) + sdk_log_record = processor.get_log_record(0) - self.assertEqual(log_record.body, "Critical message within span") - self.assertEqual(log_record.severity_text, "CRITICAL") - self.assertEqual(log_record.severity_number, SeverityNumber.FATAL) + self.assertEqual( + sdk_log_record.log_record.body, "Critical message within span" + ) + self.assertEqual( + sdk_log_record.log_record.severity_text, "CRITICAL" + ) + self.assertEqual( + sdk_log_record.log_record.severity_number, SeverityNumber.FATAL + ) span_context = span.get_span_context() - self.assertEqual(log_record.trace_id, span_context.trace_id) - self.assertEqual(log_record.span_id, span_context.span_id) - self.assertEqual(log_record.trace_flags, span_context.trace_flags) + self.assertEqual( + sdk_log_record.log_record.trace_id, span_context.trace_id + ) + self.assertEqual( + sdk_log_record.log_record.span_id, span_context.span_id + ) + self.assertEqual( + sdk_log_record.log_record.trace_flags, span_context.trace_flags + ) def test_warning_without_formatter(self): processor, logger = set_up_test_logging(logging.WARNING) logger.warning("Test message") - log_record = processor.get_log_record(0) - self.assertEqual(log_record.body, "Test message") + sdk_log_record = processor.get_log_record(0) + self.assertEqual(sdk_log_record.log_record.body, "Test message") def test_exception_without_formatter(self): processor, logger = set_up_test_logging(logging.WARNING) logger.exception("Test exception") - log_record = processor.get_log_record(0) - self.assertEqual(log_record.body, "Test exception") + sdk_log_record = processor.get_log_record(0) + self.assertEqual(sdk_log_record.log_record.body, "Test exception") def test_warning_with_formatter(self): processor, logger = set_up_test_logging( @@ -341,8 +393,10 @@ def test_warning_with_formatter(self): ) logger.warning("Test message") - log_record = processor.get_log_record(0) - self.assertEqual(log_record.body, "foo - WARNING - Test message") + sdk_log_record = processor.get_log_record(0) + self.assertEqual( + sdk_log_record.log_record.body, "foo - WARNING - Test message" + ) def test_log_body_is_always_string_with_formatter(self): processor, logger = set_up_test_logging( @@ -353,8 +407,8 @@ def test_log_body_is_always_string_with_formatter(self): ) logger.warning(["something", "of", "note"]) - log_record = processor.get_log_record(0) - self.assertIsInstance(log_record.body, str) + sdk_log_record = processor.get_log_record(0) + self.assertIsInstance(sdk_log_record.log_record.body, str) @patch.dict(os.environ, {"OTEL_SDK_DISABLED": "true"}) def test_handler_root_logger_with_disabled_sdk_does_not_go_into_recursion_error( @@ -384,8 +438,8 @@ class FakeProcessor(LogRecordProcessor): def __init__(self): self.log_data_emitted = [] - def on_emit(self, log_data: LogData): - self.log_data_emitted.append(log_data) + def on_emit(self, log_record: SDKLogRecord): + self.log_data_emitted.append(log_record) def shutdown(self): pass @@ -397,4 +451,4 @@ def emit_count(self): return len(self.log_data_emitted) def get_log_record(self, i): - return self.log_data_emitted[i].log_record + return self.log_data_emitted[i] diff --git a/opentelemetry-sdk/tests/logs/test_log_record.py b/opentelemetry-sdk/tests/logs/test_log_record.py index dc9c0aab103..7d360e4a751 100644 --- a/opentelemetry-sdk/tests/logs/test_log_record.py +++ b/opentelemetry-sdk/tests/logs/test_log_record.py @@ -16,33 +16,32 @@ import unittest import warnings -from opentelemetry._logs.severity import SeverityNumber +from opentelemetry._logs import LogRecord, SeverityNumber from opentelemetry.attributes import BoundedAttributes -from opentelemetry.context import get_current from opentelemetry.sdk._logs import ( - LogDeprecatedInitWarning, LogDroppedAttributesWarning, LogLimits, - LogRecord, + SDKLogRecord, ) from opentelemetry.sdk.resources import Resource -from opentelemetry.trace.span import TraceFlags class TestLogRecord(unittest.TestCase): def test_log_record_to_json(self): - log_record = LogRecord( - timestamp=0, - observed_timestamp=0, - body={"key": "logLine", "bytes": b"123"}, + log_record = SDKLogRecord( + LogRecord( + timestamp=0, + observed_timestamp=0, + body={"key": "logLine", "bytes": b"123"}, + attributes={ + "mapping": {"key": "value"}, + "none": None, + "sequence": [1, 2], + "str": "string", + }, + event_name="a.event", + ), resource=Resource({"service.name": "foo"}), - attributes={ - "mapping": {"key": "value"}, - "none": None, - "sequence": [1, 2], - "str": "string", - }, - event_name="a.event", ) self.assertEqual( @@ -51,11 +50,13 @@ def test_log_record_to_json(self): ) def test_log_record_to_json_serializes_severity_number_as_int(self): - actual = LogRecord( - timestamp=0, - severity_number=SeverityNumber.WARN, - observed_timestamp=0, - body="a log line", + actual = SDKLogRecord( + LogRecord( + timestamp=0, + severity_number=SeverityNumber.WARN, + observed_timestamp=0, + body="a log line", + ), resource=Resource({"service.name": "foo"}), ) @@ -65,14 +66,20 @@ def test_log_record_to_json_serializes_severity_number_as_int(self): def test_log_record_bounded_attributes(self): attr = {"key": "value"} - result = LogRecord(timestamp=0, body="a log line", attributes=attr) + result = SDKLogRecord( + LogRecord(timestamp=0, body="a log line", attributes=attr) + ) - self.assertTrue(isinstance(result.attributes, BoundedAttributes)) + self.assertTrue( + isinstance(result.log_record.attributes, BoundedAttributes) + ) def test_log_record_dropped_attributes_empty_limits(self): attr = {"key": "value"} - result = LogRecord(timestamp=0, body="a log line", attributes=attr) + result = SDKLogRecord( + LogRecord(timestamp=0, body="a log line", attributes=attr) + ) self.assertTrue(result.dropped_attributes == 0) @@ -82,8 +89,9 @@ def test_log_record_dropped_attributes_set_limits_max_attribute(self): max_attributes=1, ) - result = LogRecord( - timestamp=0, body="a log line", attributes=attr, limits=limits + result = SDKLogRecord( + LogRecord(timestamp=0, body="a log line", attributes=attr), + limits=limits, ) self.assertTrue(result.dropped_attributes == 1) @@ -96,11 +104,16 @@ def test_log_record_dropped_attributes_set_limits_max_attribute_length( max_attribute_length=1, ) - result = LogRecord( - timestamp=0, body="a log line", attributes=attr, limits=limits + result = SDKLogRecord( + LogRecord( + timestamp=0, + body="a log line", + attributes=attr, + ), + limits=limits, ) self.assertTrue(result.dropped_attributes == 0) - self.assertEqual(expected, result.attributes) + self.assertEqual(expected, result.log_record.attributes) def test_log_record_dropped_attributes_set_limits(self): attr = {"key": "value", "key2": "value2"} @@ -110,11 +123,16 @@ def test_log_record_dropped_attributes_set_limits(self): max_attribute_length=1, ) - result = LogRecord( - timestamp=0, body="a log line", attributes=attr, limits=limits + result = SDKLogRecord( + LogRecord( + timestamp=0, + body="a log line", + attributes=attr, + ), + limits=limits, ) self.assertTrue(result.dropped_attributes == 1) - self.assertEqual(expected, result.attributes) + self.assertEqual(expected, result.log_record.attributes) def test_log_record_dropped_attributes_set_limits_warning_once(self): attr = {"key1": "value1", "key2": "value2"} @@ -125,10 +143,12 @@ def test_log_record_dropped_attributes_set_limits_warning_once(self): with warnings.catch_warnings(record=True) as cw: for _ in range(10): - LogRecord( - timestamp=0, - body="a log line", - attributes=attr, + SDKLogRecord( + LogRecord( + timestamp=0, + body="a log line", + attributes=attr, + ), limits=limits, ) self.assertEqual(len(cw), 1) @@ -142,33 +162,13 @@ def test_log_record_dropped_attributes_unset_limits(self): attr = {"key": "value", "key2": "value2"} limits = LogLimits() - result = LogRecord( - timestamp=0, body="a log line", attributes=attr, limits=limits + result = SDKLogRecord( + LogRecord( + timestamp=0, + body="a log line", + attributes=attr, + ), + limits=limits, ) self.assertTrue(result.dropped_attributes == 0) - self.assertEqual(attr, result.attributes) - - def test_log_record_deprecated_init_warning(self): - test_cases = [ - {"trace_id": 123}, - {"span_id": 123}, - {"trace_flags": TraceFlags(0x01)}, - ] - - for params in test_cases: - with self.subTest(params=params): - with warnings.catch_warnings(record=True) as cw: - for _ in range(10): - LogRecord(**params) - - self.assertEqual(len(cw), 1) - self.assertIsInstance(cw[-1].message, LogDeprecatedInitWarning) - self.assertIn( - "LogRecord init with `trace_id`, `span_id`, and/or `trace_flags` is deprecated since 1.35.0. Use `context` instead.", - str(cw[-1].message), - ) - - with warnings.catch_warnings(record=True) as cw: - for _ in range(10): - LogRecord(context=get_current()) - self.assertEqual(len(cw), 0) + self.assertEqual(attr, result.log_record.attributes) diff --git a/opentelemetry-sdk/tests/logs/test_multi_log_processor.py b/opentelemetry-sdk/tests/logs/test_multi_log_processor.py index e121f136223..623ee03a73b 100644 --- a/opentelemetry-sdk/tests/logs/test_multi_log_processor.py +++ b/opentelemetry-sdk/tests/logs/test_multi_log_processor.py @@ -21,13 +21,13 @@ from abc import ABC, abstractmethod from unittest.mock import Mock -from opentelemetry._logs import SeverityNumber +from opentelemetry._logs import LogRecord, SeverityNumber from opentelemetry.sdk._logs._internal import ( ConcurrentMultiLogRecordProcessor, LoggerProvider, LoggingHandler, - LogRecord, LogRecordProcessor, + SDKLogRecord, SynchronousMultiLogRecordProcessor, ) @@ -38,11 +38,11 @@ def __init__(self, exporter, logs_list): self._log_list = logs_list self._closed = False - def on_emit(self, log_data): + def on_emit(self, log_record: SDKLogRecord): if self._closed: return self._log_list.append( - (log_data.log_record.body, log_data.log_record.severity_text) + (log_record.log_record.body, log_record.log_record.severity_text) ) def shutdown(self): @@ -105,11 +105,13 @@ def _get_multi_log_record_processor(self): pass def make_record(self): - return LogRecord( - timestamp=1622300111608942000, - severity_text="WARN", - severity_number=SeverityNumber.WARN, - body="Warning message", + return SDKLogRecord( + LogRecord( + timestamp=1622300111608942000, + severity_text="WARN", + severity_number=SeverityNumber.WARN, + body="Warning message", + ) ) def test_on_emit(self): diff --git a/opentelemetry-sdk/tests/shared_internal/test_batch_processor.py b/opentelemetry-sdk/tests/shared_internal/test_batch_processor.py index 541d27c880a..6bc7d1ea2cd 100644 --- a/opentelemetry-sdk/tests/shared_internal/test_batch_processor.py +++ b/opentelemetry-sdk/tests/shared_internal/test_batch_processor.py @@ -26,10 +26,12 @@ import pytest -from opentelemetry.sdk._logs import ( - LogData, +from opentelemetry._logs import ( LogRecord, ) +from opentelemetry.sdk._logs import ( + SDKLogRecord, +) from opentelemetry.sdk._logs.export import ( BatchLogRecordProcessor, ) @@ -37,7 +39,7 @@ from opentelemetry.sdk.trace.export import BatchSpanProcessor from opentelemetry.sdk.util.instrumentation import InstrumentationScope -EMPTY_LOG = LogData( +EMPTY_LOG = SDKLogRecord( log_record=LogRecord(), instrumentation_scope=InstrumentationScope("example", "example"), )