From f22d25de15eb1b91552534f201e07c9a9b255ca9 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Fri, 6 Dec 2024 22:14:29 -0800 Subject: [PATCH] remove LogData --- .../common/_internal/_log_encoder/__init__.py | 35 ++++--- .../tests/test_log_encoder.py | 72 ++++++-------- .../otlp/proto/grpc/_log_exporter/__init__.py | 5 +- .../tests/logs/test_otlp_logs_exporter.py | 95 +++++++++---------- .../otlp/proto/http/_log_exporter/__init__.py | 5 +- .../tests/test_proto_log_exporter.py | 63 +++++------- .../src/opentelemetry/sdk/_logs/__init__.py | 2 - .../sdk/_logs/_internal/__init__.py | 32 +++---- .../sdk/_logs/_internal/export/__init__.py | 28 +++--- .../export/in_memory_log_exporter.py | 6 +- opentelemetry-sdk/tests/logs/test_export.py | 45 ++++----- opentelemetry-sdk/tests/logs/test_handler.py | 8 +- .../tests/logs/test_log_record.py | 17 +++- .../tests/logs/test_multi_log_processor.py | 4 +- 14 files changed, 191 insertions(+), 226 deletions(-) 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 7213f89d4a0..747b789700d 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,44 +30,43 @@ ResourceLogs, ScopeLogs, ) -from opentelemetry.sdk._logs import LogData - -def encode_logs(batch: Sequence[LogData]) -> ExportLogsServiceRequest: +from opentelemetry.sdk._logs import LogRecord as SDKLogRecord +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(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 log_record.span_id == 0 + else _encode_span_id(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 log_record.trace_id == 0 + else _encode_trace_id(log_record.trace_id) ) - body = log_data.log_record.body + body = 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=log_record.timestamp, + observed_time_unix_nano=log_record.observed_timestamp, span_id=span_id, trace_id=trace_id, - flags=int(log_data.log_record.trace_flags), + flags=int(log_record.trace_flags), body=_encode_value(body) if body is not None else None, - severity_text=log_data.log_record.severity_text, - attributes=_encode_attributes(log_data.log_record.attributes), - dropped_attributes_count=log_data.log_record.dropped_attributes, - severity_number=log_data.log_record.severity_number.value, + severity_text=log_record.severity_text, + attributes=_encode_attributes(log_record.attributes), + dropped_attributes_count=log_record.dropped_attributes, + severity_number=log_record.severity_number.value, ) -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 70f4c821c9e..5695a3e4564 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 @@ -39,7 +39,7 @@ from opentelemetry.proto.resource.v1.resource_pb2 import ( Resource as PB2Resource, ) -from opentelemetry.sdk._logs import LogData, LogLimits +from opentelemetry.sdk._logs import LogLimits from opentelemetry.sdk._logs import LogRecord as SDKLogRecord from opentelemetry.sdk.resources import Resource as SDKResource from opentelemetry.sdk.util.instrumentation import InstrumentationScope @@ -54,7 +54,7 @@ def test_encode(self): def test_encode_no_body(self): sdk_logs, expected_encoding = self.get_test_logs() for log in sdk_logs: - log.log_record.body = None + log.body = None for resource_log in expected_encoding.resource_logs: for scope_log in resource_log.scope_logs: @@ -66,7 +66,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] @@ -77,9 +77,8 @@ def test_dropped_attributes_count(self): ) @staticmethod - def _get_sdk_log_data() -> List[LogData]: - log1 = LogData( - log_record=SDKLogRecord( + def _get_sdk_log_data() -> List[SDKLogRecord]: + log1 = SDKLogRecord( timestamp=1644650195189786880, observed_timestamp=1644650195189786881, trace_id=89564621134313219400156819398935297684, @@ -93,14 +92,12 @@ def _get_sdk_log_data() -> List[LogData]: "resource_schema_url", ), attributes={"a": 1, "b": "c"}, - ), - instrumentation_scope=InstrumentationScope( - "first_name", "first_version" - ), + instrumentation_scope=InstrumentationScope( + "first_name", "first_version" + ), ) - log2 = LogData( - log_record=SDKLogRecord( + log2 = SDKLogRecord( timestamp=1644650249738562048, observed_timestamp=1644650249738562049, trace_id=0, @@ -111,14 +108,12 @@ def _get_sdk_log_data() -> List[LogData]: body="Cooper, this is no time for caution!", resource=SDKResource({"second_resource": "CASE"}), attributes={}, - ), - instrumentation_scope=InstrumentationScope( - "second_name", "second_version" - ), + instrumentation_scope=InstrumentationScope( + "second_name", "second_version" + ), ) - log3 = LogData( - log_record=SDKLogRecord( + log3 = SDKLogRecord( timestamp=1644650427658989056, observed_timestamp=1644650427658989057, trace_id=271615924622795969659406376515024083555, @@ -129,12 +124,10 @@ def _get_sdk_log_data() -> List[LogData]: body="To our galaxy", resource=SDKResource({"second_resource": "CASE"}), attributes={"a": 1, "b": "c"}, - ), - instrumentation_scope=None, - ) + instrumentation_scope=None, + ) - log4 = LogData( - log_record=SDKLogRecord( + log4 = SDKLogRecord( timestamp=1644650584292683008, observed_timestamp=1644650584292683009, trace_id=212592107417388365804938480559624925555, @@ -148,10 +141,9 @@ def _get_sdk_log_data() -> List[LogData]: "resource_schema_url", ), attributes={"filename": "model.py", "func_name": "run_method"}, - ), - instrumentation_scope=InstrumentationScope( - "another_name", "another_version" - ), + instrumentation_scope=InstrumentationScope( + "another_name", "another_version" + ), ) return [log1, log2, log3, log4] @@ -293,9 +285,8 @@ def get_test_logs( return sdk_logs, pb2_service_request @staticmethod - def _get_test_logs_dropped_attributes() -> List[LogData]: - log1 = LogData( - log_record=SDKLogRecord( + def _get_test_logs_dropped_attributes() -> List[SDKLogRecord]: + log1 = SDKLogRecord( timestamp=1644650195189786880, trace_id=89564621134313219400156819398935297684, span_id=1312458408527513268, @@ -306,14 +297,12 @@ def _get_test_logs_dropped_attributes() -> List[LogData]: resource=SDKResource({"first_resource": "value"}), attributes={"a": 1, "b": "c", "user_id": "B121092"}, limits=LogLimits(max_attributes=1), - ), - instrumentation_scope=InstrumentationScope( - "first_name", "first_version" - ), - ) + instrumentation_scope=InstrumentationScope( + "first_name", "first_version" + ), + ) - log2 = LogData( - log_record=SDKLogRecord( + log2 = SDKLogRecord( timestamp=1644650249738562048, trace_id=0, span_id=0, @@ -323,10 +312,9 @@ def _get_test_logs_dropped_attributes() -> List[LogData]: body="Cooper, this is no time for caution!", resource=SDKResource({"second_resource": "CASE"}), attributes={}, - ), - instrumentation_scope=InstrumentationScope( - "second_name", "second_version" - ), - ) + instrumentation_scope=InstrumentationScope( + "second_name", "second_version" + ), + ) return [log1, log2] 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 8f629899d77..309ba068315 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,7 +28,6 @@ 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.export import LogExporter, LogExportResult from opentelemetry.sdk.environment_variables import ( @@ -103,11 +102,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 a31679fb0d5..7c8feedd04e 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,7 +52,7 @@ from opentelemetry.proto.resource.v1.resource_pb2 import ( Resource as OTLPResource, ) -from opentelemetry.sdk._logs import LogData, LogRecord +from opentelemetry.sdk._logs import LogRecord from opentelemetry.sdk._logs.export import LogExportResult from opentelemetry.sdk.environment_variables import ( OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE, @@ -126,8 +126,7 @@ def setUp(self): self.server.start() - self.log_data_1 = LogData( - log_record=LogRecord( + self.log_data_1 = LogRecord( timestamp=int(time.time() * 1e9), trace_id=2604504634922341076776623263868986797, span_id=5213367945872657620, @@ -137,13 +136,11 @@ def setUp(self): body="Zhengzhou, We have a heaviest rains in 1000 years", resource=SDKResource({"key": "value"}), attributes={"a": 1, "b": "c"}, - ), - instrumentation_scope=InstrumentationScope( - "first_name", "first_version" - ), - ) - self.log_data_2 = LogData( - log_record=LogRecord( + instrumentation_scope=InstrumentationScope( + "first_name", "first_version" + ), + ) + self.log_data_2 = LogRecord( timestamp=int(time.time() * 1e9), trace_id=2604504634922341076776623263868986799, span_id=5213367945872657623, @@ -153,13 +150,11 @@ def setUp(self): body="Sydney, Opera House is closed", resource=SDKResource({"key": "value"}), attributes={"custom_attr": [1, 2, 3]}, - ), - instrumentation_scope=InstrumentationScope( - "second_name", "second_version" - ), - ) - self.log_data_3 = LogData( - log_record=LogRecord( + instrumentation_scope=InstrumentationScope( + "second_name", "second_version" + ), + ) + self.log_data_3 = LogRecord( timestamp=int(time.time() * 1e9), trace_id=2604504634922341076776623263868986800, span_id=5213367945872657628, @@ -168,13 +163,11 @@ def setUp(self): severity_number=SeverityNumber.WARN, body="Mumbai, Boil water before drinking", resource=SDKResource({"service": "myapp"}), - ), - instrumentation_scope=InstrumentationScope( - "third_name", "third_version" - ), - ) - self.log_data_4 = LogData( - log_record=LogRecord( + instrumentation_scope=InstrumentationScope( + "third_name", "third_version" + ), + ) + self.log_data_4 = LogRecord( timestamp=int(time.time() * 1e9), trace_id=0, span_id=5213367945872657629, @@ -183,13 +176,12 @@ def setUp(self): severity_number=SeverityNumber.WARN, body="Invalid trace id check", resource=SDKResource({"service": "myapp"}), - ), - instrumentation_scope=InstrumentationScope( - "fourth_name", "fourth_version" - ), - ) - self.log_data_5 = LogData( - log_record=LogRecord( + instrumentation_scope=InstrumentationScope( + "fourth_name", "fourth_version" + ), + ) + + self.log_data_5 = LogRecord( timestamp=int(time.time() * 1e9), trace_id=2604504634922341076776623263868986801, span_id=0, @@ -198,11 +190,10 @@ def setUp(self): severity_number=SeverityNumber.WARN, body="Invalid span id check", resource=SDKResource({"service": "myapp"}), - ), - instrumentation_scope=InstrumentationScope( - "fifth_name", "fifth_version" - ), - ) + instrumentation_scope=InstrumentationScope( + "fifth_name", "fifth_version" + ), + ) def tearDown(self): self.server.stop(None) @@ -491,9 +482,9 @@ def test_translate_log_data(self): log_records=[ PB2LogRecord( # pylint: disable=no-member - time_unix_nano=self.log_data_1.log_record.timestamp, - observed_time_unix_nano=self.log_data_1.log_record.observed_timestamp, - severity_number=self.log_data_1.log_record.severity_number.value, + time_unix_nano=self.log_data_1.timestamp, + observed_time_unix_nano=self.log_data_1.observed_timestamp, + severity_number=self.log_data_1.severity_number.value, severity_text="WARNING", span_id=int.to_bytes( 5213367945872657620, 8, "big" @@ -517,7 +508,7 @@ def test_translate_log_data(self): ), ], flags=int( - self.log_data_1.log_record.trace_flags + self.log_data_1.trace_flags ), ) ], @@ -551,9 +542,9 @@ def test_translate_multiple_logs(self): log_records=[ PB2LogRecord( # pylint: disable=no-member - time_unix_nano=self.log_data_1.log_record.timestamp, - observed_time_unix_nano=self.log_data_1.log_record.observed_timestamp, - severity_number=self.log_data_1.log_record.severity_number.value, + time_unix_nano=self.log_data_1.timestamp, + observed_time_unix_nano=self.log_data_1.observed_timestamp, + severity_number=self.log_data_1.severity_number.value, severity_text="WARNING", span_id=int.to_bytes( 5213367945872657620, 8, "big" @@ -577,7 +568,7 @@ def test_translate_multiple_logs(self): ), ], flags=int( - self.log_data_1.log_record.trace_flags + self.log_data_1.trace_flags ), ) ], @@ -589,9 +580,9 @@ def test_translate_multiple_logs(self): log_records=[ PB2LogRecord( # pylint: disable=no-member - time_unix_nano=self.log_data_2.log_record.timestamp, - observed_time_unix_nano=self.log_data_2.log_record.observed_timestamp, - severity_number=self.log_data_2.log_record.severity_number.value, + time_unix_nano=self.log_data_2.timestamp, + observed_time_unix_nano=self.log_data_2.observed_timestamp, + severity_number=self.log_data_2.severity_number.value, severity_text="INFO", span_id=int.to_bytes( 5213367945872657623, 8, "big" @@ -611,7 +602,7 @@ def test_translate_multiple_logs(self): ), ], flags=int( - self.log_data_2.log_record.trace_flags + self.log_data_2.trace_flags ), ) ], @@ -635,9 +626,9 @@ def test_translate_multiple_logs(self): log_records=[ PB2LogRecord( # pylint: disable=no-member - time_unix_nano=self.log_data_3.log_record.timestamp, - observed_time_unix_nano=self.log_data_3.log_record.observed_timestamp, - severity_number=self.log_data_3.log_record.severity_number.value, + time_unix_nano=self.log_data_3.timestamp, + observed_time_unix_nano=self.log_data_3.observed_timestamp, + severity_number=self.log_data_3.severity_number.value, severity_text="ERROR", span_id=int.to_bytes( 5213367945872657628, 8, "big" @@ -652,7 +643,7 @@ def test_translate_multiple_logs(self): ), attributes=[], flags=int( - self.log_data_3.log_record.trace_flags + self.log_data_3.trace_flags ), ) ], 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 21b877380c8..e45b399e922 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 @@ -30,7 +30,8 @@ _OTLP_HTTP_HEADERS, Compression, ) -from opentelemetry.sdk._logs import LogData + +from opentelemetry.sdk._logs import LogRecord from opentelemetry.sdk._logs.export import ( LogExporter, LogExportResult, @@ -149,7 +150,7 @@ def _retryable(resp: requests.Response) -> bool: return True return False - def export(self, batch: Sequence[LogData]) -> LogExportResult: + def export(self, batch: Sequence[LogRecord]) -> LogExportResult: # After the call to Shutdown subsequent calls to Export are # not allowed and should return a Failure result. if self._shutdown: 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..c5bcd141501 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 @@ -35,7 +35,6 @@ 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.export import LogExportResult from opentelemetry.sdk.environment_variables import ( @@ -214,8 +213,7 @@ def export_log_and_deserialize(log): return log_records def test_exported_log_without_trace_id(self): - log = LogData( - log_record=SDKLogRecord( + log = SDKLogRecord( timestamp=1644650195189786182, trace_id=0, span_id=1312458408527513292, @@ -225,9 +223,8 @@ def test_exported_log_without_trace_id(self): body="Invalid trace id check", resource=SDKResource({"first_resource": "value"}), attributes={"a": 1, "b": "c"}, - ), - instrumentation_scope=InstrumentationScope("name", "version"), - ) + instrumentation_scope=InstrumentationScope("name", "version"), + ) log_records = TestOTLPHTTPLogExporter.export_log_and_deserialize(log) if log_records: log_record = log_records[0] @@ -241,8 +238,7 @@ def test_exported_log_without_trace_id(self): self.fail("No log records found") def test_exported_log_without_span_id(self): - log = LogData( - log_record=SDKLogRecord( + log = SDKLogRecord( timestamp=1644650195189786360, trace_id=89564621134313219400156819398935297696, span_id=0, @@ -252,9 +248,8 @@ def test_exported_log_without_span_id(self): body="Invalid span id check", resource=SDKResource({"first_resource": "value"}), attributes={"a": 1, "b": "c"}, - ), - instrumentation_scope=InstrumentationScope("name", "version"), - ) + instrumentation_scope=InstrumentationScope("name", "version"), + ) log_records = TestOTLPHTTPLogExporter.export_log_and_deserialize(log) if log_records: log_record = log_records[0] @@ -287,9 +282,8 @@ def test_exponential_backoff(self, mock_sleep): ) @staticmethod - def _get_sdk_log_data() -> List[LogData]: - log1 = LogData( - log_record=SDKLogRecord( + def _get_sdk_log_data() -> List[SDKLogRecord]: + log1 = SDKLogRecord( timestamp=1644650195189786880, trace_id=89564621134313219400156819398935297684, span_id=1312458408527513268, @@ -299,14 +293,12 @@ def _get_sdk_log_data() -> List[LogData]: 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"}, - ), - instrumentation_scope=InstrumentationScope( - "first_name", "first_version" - ), - ) + instrumentation_scope=InstrumentationScope( + "first_name", "first_version" + ), + ) - log2 = LogData( - log_record=SDKLogRecord( + log2 = SDKLogRecord( timestamp=1644650249738562048, trace_id=0, span_id=0, @@ -316,14 +308,12 @@ def _get_sdk_log_data() -> List[LogData]: body="Cooper, this is no time for caution!", resource=SDKResource({"second_resource": "CASE"}), attributes={}, - ), - instrumentation_scope=InstrumentationScope( - "second_name", "second_version" - ), - ) + instrumentation_scope=InstrumentationScope( + "second_name", "second_version" + ), + ) - log3 = LogData( - log_record=SDKLogRecord( + log3 = SDKLogRecord( timestamp=1644650427658989056, trace_id=271615924622795969659406376515024083555, span_id=4242561578944770265, @@ -333,12 +323,10 @@ def _get_sdk_log_data() -> List[LogData]: body="To our galaxy", resource=SDKResource({"second_resource": "CASE"}), attributes={"a": 1, "b": "c"}, - ), - instrumentation_scope=None, - ) + instrumentation_scope=None, + ) - log4 = LogData( - log_record=SDKLogRecord( + log4 = SDKLogRecord( timestamp=1644650584292683008, trace_id=212592107417388365804938480559624925555, span_id=6077757853989569223, @@ -348,11 +336,10 @@ def _get_sdk_log_data() -> List[LogData]: body="Love is the one thing that transcends time and space", resource=SDKResource({"first_resource": "value"}), attributes={"filename": "model.py", "func_name": "run_method"}, - ), - instrumentation_scope=InstrumentationScope( - "another_name", "another_version" - ), - ) + instrumentation_scope=InstrumentationScope( + "another_name", "another_version" + ), + ) return [log1, log2, log3, log4] diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py index 0254c135e84..f9c8c218110 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py @@ -14,7 +14,6 @@ from opentelemetry.sdk._logs._internal import ( - LogData, LogDroppedAttributesWarning, Logger, LoggerProvider, @@ -25,7 +24,6 @@ ) __all__ = [ - "LogData", "Logger", "LoggerProvider", "LoggingHandler", diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py index e67e79687eb..f6e0367e6e3 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py @@ -182,6 +182,7 @@ def __init__( resource: Optional[Resource] = None, attributes: Optional[Attributes] = None, limits: Optional[LogLimits] = _UnsetLogLimits, + instrumentation_scope: Optional[InstrumentationScope] = None, ): self.event_name = event_name self.timestamp = timestamp @@ -192,6 +193,7 @@ def __init__( self.severity_text = severity_text self.severity_number = severity_number self.body = body + self.instrumentation_scope = instrumentation_scope self.attributes = BoundedAttributes( maxlen=limits.max_attributes, attributes=attributes if bool(attributes) else None, @@ -202,6 +204,7 @@ def __init__( self.resource = ( resource if isinstance(resource, Resource) else Resource.create({}) ) + if self.dropped_attributes > 0: warnings.warn( "Log record attributes were dropped due to limits", @@ -241,6 +244,7 @@ def to_json(self, indent=4) -> str: ), "trace_flags": self.trace_flags, "resource": json.loads(self.resource.to_json()), + "instrumentation_scope": json.loads(self.instrumentation_scope.to_json()), }, indent=indent, ) @@ -252,18 +256,6 @@ def dropped_attributes(self) -> int: 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. @@ -273,8 +265,8 @@ class LogRecordProcessor(abc.ABC): """ @abc.abstractmethod - def emit(self, log_data: LogData): - """Emits the `LogData`""" + def emit(self, log_data: LogRecord): + """Emits the `LogRecord`""" @abc.abstractmethod def shutdown(self): @@ -317,9 +309,9 @@ def add_log_record_processor( with self._lock: self._log_record_processors += (log_record_processor,) - def emit(self, log_data: LogData) -> None: + def emit(self, log_record: LogRecord) -> None: for lp in self._log_record_processors: - lp.emit(log_data) + lp.emit(log_record) def shutdown(self) -> None: """Shutdown the log processors one by one""" @@ -391,8 +383,8 @@ def _submit_and_wait( for future in futures: future.result() - def emit(self, log_data: LogData): - self._submit_and_wait(lambda lp: lp.emit, log_data) + def emit(self, log_record: LogRecord): + self._submit_and_wait(lambda lp: lp.emit, log_record) def shutdown(self): self._submit_and_wait(lambda lp: lp.shutdown) @@ -614,9 +606,9 @@ def emit(self, body=body, attributes=attributes, resource=self._resource, + instrumentation_scope=self._instrumentation_scope, ) - log_data = LogData(log_record, self._instrumentation_scope) - self._multi_log_record_processor.emit(log_data) + self._multi_log_record_processor.emit(log_record) class LoggerProvider(APILoggerProvider): def __init__( 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 e5669580c4b..b7b4c210cbb 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py @@ -29,7 +29,7 @@ detach, set_value, ) -from opentelemetry.sdk._logs import LogData, LogRecord, LogRecordProcessor +from opentelemetry.sdk._logs import LogRecord, LogRecordProcessor from opentelemetry.sdk.environment_variables import ( OTEL_BLRP_EXPORT_TIMEOUT, OTEL_BLRP_MAX_EXPORT_BATCH_SIZE, @@ -65,11 +65,11 @@ class LogExporter(abc.ABC): """ @abc.abstractmethod - def export(self, batch: Sequence[LogData]): + def export(self, batch: Sequence[LogRecord]): """Exports a batch of logs. Args: - batch: The list of `LogData` objects to be exported + batch: The list of `LogRecord` objects to be exported Returns: The result of the export @@ -100,9 +100,9 @@ def __init__( 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[LogRecord]): + for log_record in batch: + self.out.write(self.formatter(log_record)) self.out.flush() return LogExportResult.SUCCESS @@ -112,7 +112,7 @@ def shutdown(self): class SimpleLogRecordProcessor(LogRecordProcessor): """This is an implementation of LogRecordProcessor which passes - received logs in the export-friendly LogData representation to the + received logs in the export-friendly LogRecord representation to the configured LogExporter, as soon as they are emitted. """ @@ -120,13 +120,13 @@ def __init__(self, exporter: LogExporter): self._exporter = exporter self._shutdown = False - def emit(self, log_data: LogData): + def emit(self, log_record: LogRecord): 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) @@ -152,7 +152,7 @@ def __init__(self): class BatchLogRecordProcessor(LogRecordProcessor): """This is an implementation of LogRecordProcessor which creates batches of - received logs in the export-friendly LogData representation and + received logs in the export-friendly LogRecord representation and send to the configured LogExporter, as soon as they are emitted. `BatchLogRecordProcessor` is configurable with the following environment @@ -164,9 +164,9 @@ class BatchLogRecordProcessor(LogRecordProcessor): - :envvar:`OTEL_BLRP_EXPORT_TIMEOUT` """ - _queue: Deque[LogData] + _queue: Deque[LogRecord] _flush_request: Optional[_FlushRequest] - _log_records: List[Optional[LogData]] + _log_records: List[Optional[LogRecord]] def __init__( self, @@ -341,8 +341,8 @@ def _get_or_create_flush_request(self) -> _FlushRequest: self._flush_request = _FlushRequest() return self._flush_request - def emit(self, log_data: LogData) -> None: - """Adds the `LogData` to queue and notifies the waiting threads + def emit(self, log_data: LogRecord) -> None: + """Adds the `LogRecord` to queue and notifies the waiting threads when size of queue reaches max_export_batch_size. """ if self._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..b4e0239c246 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 LogRecord 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[LogRecord, ...]: with self._lock: return tuple(self._logs) - def export(self, batch: typing.Sequence[LogData]) -> LogExportResult: + def export(self, batch: typing.Sequence[LogRecord]) -> LogExportResult: if self._stopped: return LogExportResult.FAILURE with self._lock: diff --git a/opentelemetry-sdk/tests/logs/test_export.py b/opentelemetry-sdk/tests/logs/test_export.py index 2e00bad6538..5afd9f45b78 100644 --- a/opentelemetry-sdk/tests/logs/test_export.py +++ b/opentelemetry-sdk/tests/logs/test_export.py @@ -24,7 +24,7 @@ from opentelemetry._logs import SeverityNumber from opentelemetry.sdk import trace from opentelemetry.sdk._logs import ( - LogData, + LogRecord, LoggerProvider, LoggingHandler, LogRecord, @@ -65,7 +65,7 @@ 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 + warning_log_record = finished_logs[0] self.assertEqual(warning_log_record.body, "Something is wrong") self.assertEqual(warning_log_record.severity_text, "WARN") self.assertEqual( @@ -95,8 +95,8 @@ 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 + critical_log_record = finished_logs[0] + fatal_log_record = finished_logs[1] self.assertEqual(critical_log_record.body, "Error message") self.assertEqual(critical_log_record.severity_text, "ERROR") self.assertEqual( @@ -129,7 +129,7 @@ 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 + log_record = finished_logs[0] self.assertEqual(log_record.body, "Warning message") self.assertEqual(log_record.severity_text, "WARN") self.assertEqual(log_record.severity_number, SeverityNumber.WARN) @@ -148,7 +148,7 @@ 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 + log_record = finished_logs[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) @@ -176,7 +176,7 @@ 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 + warning_log_record = finished_logs[0] self.assertEqual(warning_log_record.body, "Something is wrong") self.assertEqual(warning_log_record.severity_text, "WARN") self.assertEqual( @@ -221,7 +221,7 @@ def test_simple_log_record_processor_different_msg_types(self): ({"key": "value"}, "ERROR"), ] emitted = [ - (item.log_record.body, item.log_record.severity_text) + (item.body, item.severity_text) for item in finished_logs ] self.assertEqual(expected, emitted) @@ -273,7 +273,7 @@ def test_simple_log_record_processor_custom_single_obj(self): (["a non-string with a percent-s", "%s"]), ] for emitted, expected in zip(finished_logs, expected): - self.assertEqual(emitted.log_record.body, expected) + self.assertEqual(emitted.body, expected) self.assertEqual(emitted.instrumentation_scope.name, "single_obj") def test_simple_log_record_processor_different_msg_types_with_formatter( @@ -320,7 +320,7 @@ def test_simple_log_record_processor_different_msg_types_with_formatter( ("different_msg_types - ERROR - {'key': 'value'}", "ERROR"), ] emitted = [ - (item.log_record.body, item.log_record.severity_text) + (item.body, item.severity_text) for item in finished_logs ] self.assertEqual(expected, emitted) @@ -493,7 +493,7 @@ def test_shutdown(self): ), ] emitted = [ - (item.log_record.body, item.log_record.severity_text) + (item.body, item.severity_text) for item in finished_logs ] self.assertEqual(expected, emitted) @@ -515,7 +515,7 @@ def test_force_flush(self): log_record_processor.force_flush() finished_logs = exporter.get_finished_logs() self.assertEqual(len(finished_logs), 1) - log_record = finished_logs[0].log_record + log_record = finished_logs[0] self.assertEqual(log_record.body, "Earth is burning") self.assertEqual(log_record.severity_number, SeverityNumber.FATAL) self.assertEqual( @@ -623,8 +623,7 @@ def _target(): class TestConsoleLogExporter(unittest.TestCase): def test_export(self): # pylint: disable=no-self-use """Check that the console exporter prints log records.""" - log_data = LogData( - log_record=LogRecord( + log_record = LogRecord( timestamp=int(time.time() * 1e9), trace_id=2604504634922341076776623263868986797, span_id=5213367945872657620, @@ -634,19 +633,18 @@ def test_export(self): # pylint: disable=no-self-use body="Zhengzhou, We have a heaviest rains in 1000 years", resource=SDKResource({"key": "value"}), attributes={"a": 1, "b": "c"}, - ), - instrumentation_scope=InstrumentationScope( - "first_name", "first_version" - ), - ) + instrumentation_scope=InstrumentationScope( + "first_name", "first_version" + ), + ) exporter = ConsoleLogExporter() # Mocking stdout interferes with debugging and test reporting, mock on # 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) @@ -661,11 +659,10 @@ def formatter(record): # pylint: disable=unused-argument mock_stdout = Mock() exporter = ConsoleLogExporter(out=mock_stdout, formatter=formatter) - log_data = LogData( - log_record=LogRecord(), + log_record = LogRecord( instrumentation_scope=InstrumentationScope( "first_name", "first_version" ), ) - exporter.export([log_data]) + exporter.export([log_record]) mock_stdout.write.assert_called_once_with(mock_record_str) diff --git a/opentelemetry-sdk/tests/logs/test_handler.py b/opentelemetry-sdk/tests/logs/test_handler.py index f6daa1b22cf..5b33335b1bf 100644 --- a/opentelemetry-sdk/tests/logs/test_handler.py +++ b/opentelemetry-sdk/tests/logs/test_handler.py @@ -23,7 +23,7 @@ from opentelemetry.attributes import BoundedAttributes from opentelemetry.sdk import trace from opentelemetry.sdk._logs import ( - LogData, + LogRecord, LoggerProvider, LoggingHandler, LogRecordProcessor, @@ -315,8 +315,8 @@ class FakeProcessor(LogRecordProcessor): def __init__(self): self.log_data_emitted = [] - def emit(self, log_data: LogData): - self.log_data_emitted.append(log_data) + def emit(self, log_record: LogRecord): + self.log_data_emitted.append(log_record) def shutdown(self): pass @@ -328,4 +328,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 0ea0f85bea3..aa9553cdfb8 100644 --- a/opentelemetry-sdk/tests/logs/test_log_record.py +++ b/opentelemetry-sdk/tests/logs/test_log_record.py @@ -24,7 +24,7 @@ LogRecord, ) from opentelemetry.sdk.resources import Resource - +from opentelemetry.sdk.util.instrumentation import InstrumentationScope class TestLogRecord(unittest.TestCase): def test_log_record_to_json(self): @@ -45,6 +45,12 @@ def test_log_record_to_json(self): "attributes": {"service.name": "foo"}, "schema_url": "", }, + "instrumentation_scope": { + "name": "name", + "version": "version", + "schema_url": "", + "attributes": None, + }, }, indent=4, ) @@ -53,12 +59,16 @@ def test_log_record_to_json(self): observed_timestamp=0, body="a log line", resource=Resource({"service.name": "foo"}), + instrumentation_scope=InstrumentationScope( + "name", "version" + ), ) self.assertEqual(expected, actual.to_json(indent=4)) + self.assertEqual( actual.to_json(indent=None), - '{"event_name": null, "body": "a log line", "severity_number": null, "severity_text": null, "attributes": null, "dropped_attributes": 0, "timestamp": "1970-01-01T00:00:00.000000Z", "observed_timestamp": "1970-01-01T00:00:00.000000Z", "trace_id": "", "span_id": "", "trace_flags": null, "resource": {"attributes": {"service.name": "foo"}, "schema_url": ""}}', + '{"event_name": null, "body": "a log line", "severity_number": null, "severity_text": null, "attributes": null, "dropped_attributes": 0, "timestamp": "1970-01-01T00:00:00.000000Z", "observed_timestamp": "1970-01-01T00:00:00.000000Z", "trace_id": "", "span_id": "", "trace_flags": null, "resource": {"attributes": {"service.name": "foo"}, "schema_url": ""}, "instrumentation_scope": {"name": "name", "version": "version", "schema_url": "", "attributes": null}}', ) def test_log_record_to_json_serializes_severity_number_as_int(self): @@ -68,6 +78,9 @@ def test_log_record_to_json_serializes_severity_number_as_int(self): observed_timestamp=0, body="a log line", resource=Resource({"service.name": "foo"}), + instrumentation_scope=InstrumentationScope( + "name", "version" + ), ) decoded = json.loads(actual.to_json()) diff --git a/opentelemetry-sdk/tests/logs/test_multi_log_processor.py b/opentelemetry-sdk/tests/logs/test_multi_log_processor.py index 110fedb9578..a4cfe1c9f59 100644 --- a/opentelemetry-sdk/tests/logs/test_multi_log_processor.py +++ b/opentelemetry-sdk/tests/logs/test_multi_log_processor.py @@ -38,11 +38,11 @@ def __init__(self, exporter, logs_list): self._log_list = logs_list self._closed = False - def emit(self, log_data): + def emit(self, log_record): if self._closed: return self._log_list.append( - (log_data.log_record.body, log_data.log_record.severity_text) + (log_record.body, log_record.severity_text) ) def shutdown(self):