Skip to content

Commit e4dafa8

Browse files
committed
opentelemetry-sdk: convert an API LogRecord into a LogRecord in Logger.emit
So that the layers below would not care about any difference.
1 parent 1c149a0 commit e4dafa8

File tree

3 files changed

+83
-2
lines changed

3 files changed

+83
-2
lines changed

opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,19 @@ def dropped_attributes(self) -> int:
337337
return attributes.dropped
338338
return 0
339339

340+
@classmethod
341+
def from_api_log_record(cls, record: APILogRecord) -> LogRecord:
342+
return cls(
343+
timestamp=record.timestamp,
344+
observed_timestamp=record.observed_timestamp,
345+
context=record.context,
346+
severity_text=record.severity_text,
347+
severity_number=record.severity_number,
348+
body=record.body,
349+
attributes=record.attributes,
350+
event_name=record.event_name,
351+
)
352+
340353

341354
class LogData:
342355
"""Readable LogRecord data plus associated InstrumentationLibrary."""
@@ -680,10 +693,12 @@ def __init__(
680693
def resource(self):
681694
return self._resource
682695

683-
def emit(self, record: LogRecord):
696+
def emit(self, record: LogRecord | APILogRecord):
684697
"""Emits the :class:`LogData` by associating :class:`LogRecord`
685698
and instrumentation info.
686699
"""
700+
if isinstance(record, APILogRecord):
701+
record = LogRecord.from_api_log_record(record)
687702
log_data = LogData(record, self._instrumentation_scope)
688703
self._multi_log_record_processor.on_emit(log_data)
689704

opentelemetry-sdk/tests/logs/test_log_record.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import unittest
1717
import warnings
1818

19+
from opentelemetry._logs import LogRecord as APILogRecord
1920
from opentelemetry._logs.severity import SeverityNumber
2021
from opentelemetry.attributes import BoundedAttributes
2122
from opentelemetry.context import get_current
@@ -182,3 +183,26 @@ def test_log_record_deprecated_init_warning(self):
182183
for _ in range(10):
183184
LogRecord(context=get_current())
184185
self.assertEqual(len(cw), 0)
186+
187+
def test_log_record_from_api_log_record(self):
188+
api_log_record = APILogRecord(
189+
timestamp=1,
190+
observed_timestamp=2,
191+
context=get_current(),
192+
severity_text="WARN",
193+
severity_number=SeverityNumber.WARN,
194+
body="a log line",
195+
attributes={"a": "b"},
196+
event_name="an.event",
197+
)
198+
199+
record = LogRecord.from_api_log_record(api_log_record)
200+
201+
self.assertEqual(record.timestamp, 1)
202+
self.assertEqual(record.observed_timestamp, 2)
203+
self.assertEqual(record.context, get_current())
204+
self.assertEqual(record.severity_text, "WARN")
205+
self.assertEqual(record.severity_number, SeverityNumber.WARN)
206+
self.assertEqual(record.body, "a log line")
207+
self.assertEqual(record.attributes, {"a": "b"})
208+
self.assertEqual(record.event_name, "an.event")

opentelemetry-sdk/tests/logs/test_logs.py

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@
1717
import unittest
1818
from unittest.mock import Mock, patch
1919

20-
from opentelemetry.sdk._logs import LoggerProvider
20+
from opentelemetry._logs import LogRecord as APILogRecord
21+
from opentelemetry.sdk._logs import Logger, LoggerProvider, LogRecord
2122
from opentelemetry.sdk._logs._internal import (
2223
NoOpLogger,
2324
SynchronousMultiLogRecordProcessor,
2425
)
2526
from opentelemetry.sdk.environment_variables import OTEL_SDK_DISABLED
2627
from opentelemetry.sdk.resources import Resource
28+
from opentelemetry.sdk.util.instrumentation import InstrumentationScope
2729

2830

2931
class TestLoggerProvider(unittest.TestCase):
@@ -85,3 +87,43 @@ def test_logger_provider_init(self, resource_patch):
8587
)
8688
)
8789
self.assertIsNotNone(logger_provider._at_exit_handler)
90+
91+
92+
class TestLogger(unittest.TestCase):
93+
@staticmethod
94+
def _get_logger():
95+
log_record_processor_mock = Mock()
96+
logger = Logger(
97+
resource=Resource.create({}),
98+
multi_log_record_processor=log_record_processor_mock,
99+
instrumentation_scope=InstrumentationScope(
100+
"name",
101+
"version",
102+
"schema_url",
103+
{"an": "attribute"},
104+
),
105+
)
106+
return logger, log_record_processor_mock
107+
108+
def test_can_emit_logrecord(self):
109+
logger, log_record_processor_mock = self._get_logger()
110+
log_record = LogRecord(
111+
observed_timestamp=0,
112+
body="a log line",
113+
)
114+
115+
logger.emit(log_record)
116+
log_record_processor_mock.on_emit.assert_called_once()
117+
log_data = log_record_processor_mock.on_emit.call_args.args[0]
118+
self.assertTrue(isinstance(log_data.log_record, LogRecord))
119+
120+
def test_can_emit_api_logrecord(self):
121+
logger, log_record_processor_mock = self._get_logger()
122+
api_log_record = APILogRecord(
123+
observed_timestamp=0,
124+
body="a log line",
125+
)
126+
logger.emit(api_log_record)
127+
log_record_processor_mock.on_emit.assert_called_once()
128+
log_data = log_record_processor_mock.on_emit.call_args.args[0]
129+
self.assertTrue(isinstance(log_data.log_record, LogRecord))

0 commit comments

Comments
 (0)