From 587581e7fe859af3e2f8c84b8e6f100a33144b7c Mon Sep 17 00:00:00 2001 From: Scott Ernst Date: Tue, 13 Jun 2023 06:58:18 -0600 Subject: [PATCH] LogRecord Resource Serialization Currently, the `LogRecord.to_json` method serializes the resource object using `repr` of its attributes. This differs from how the serialization process is handled in `ReadableSpan.to_json` and `MetricsData.to_json`, which utilize the `Resource.to_json` functionality directly. Using `repr` does not produce a json-parseable output and doesn't follow the same depth of serialization as the other two signal types. Therefore, this change carries over the serialization process from the spans and metrics signal types to the logs type. Fixes #3345 --- CHANGELOG.md | 2 ++ .../sdk/_logs/_internal/__init__.py | 4 +-- .../tests/logs/test_log_record.py | 27 ++++++++++++++++++- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ce6fc42516..7462358dd59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - Use BoundedAttributes instead of raw dict to extract attributes from LogRecord and Support dropped_attributes_count in LogRecord ([#3310](https://github.com/open-telemetry/opentelemetry-python/pull/3310)) +- LogRecord now JSON serializes resource objects to match ReadableSpan and MetricsData equivalents ([#3345](https://github.com/open-telemetry/opentelemetry-python/issues/3345)) + ## Version 1.18.0/0.39b0 (2023-05-04) - Select histogram aggregation with an environment variable diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py index 7410138067c..d42bcaf680e 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py @@ -211,9 +211,9 @@ def to_json(self, indent=4) -> str: if self.span_id is not None else "", "trace_flags": self.trace_flags, - "resource": repr(self.resource.attributes) + "resource": json.loads(self.resource.to_json()) if self.resource - else "", + else None, }, indent=indent, ) diff --git a/opentelemetry-sdk/tests/logs/test_log_record.py b/opentelemetry-sdk/tests/logs/test_log_record.py index a5993e5833f..897a3b5893a 100644 --- a/opentelemetry-sdk/tests/logs/test_log_record.py +++ b/opentelemetry-sdk/tests/logs/test_log_record.py @@ -17,6 +17,7 @@ from opentelemetry.attributes import BoundedAttributes from opentelemetry.sdk._logs import LogLimits, LogRecord +from opentelemetry.sdk.resources import Resource class TestLogRecord(unittest.TestCase): @@ -31,7 +32,7 @@ def test_log_record_to_json(self): "trace_id": "", "span_id": "", "trace_flags": None, - "resource": "", + "resource": None, }, indent=4, ) @@ -41,6 +42,30 @@ def test_log_record_to_json(self): ).to_json() self.assertEqual(expected, actual) + def test_log_record_to_json_with_resource(self): + """Should JSON serialize/deserialize Resource objects within log records.""" + expected = json.dumps( + { + "body": "a log line", + "severity_number": "None", + "severity_text": None, + "attributes": None, + "timestamp": "1970-01-01T00:00:00.000000Z", + "trace_id": "", + "span_id": "", + "trace_flags": None, + "resource": {"attributes": {"foo": "bar"}, "schema_url": ""}, + }, + indent=4, + ) + + actual = LogRecord( + timestamp=0, + body="a log line", + resource=Resource(attributes={"foo": "bar"}), + ).to_json() + self.assertEqual(expected, actual) + def test_log_record_bounded_attributes(self): attr = {"key": "value"}