Skip to content

Commit 1278a64

Browse files
committed
Update
1 parent 49540d2 commit 1278a64

File tree

3 files changed

+95
-4
lines changed

3 files changed

+95
-4
lines changed

CHANGELOG.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,49 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1616
([#4734](https://github.com/open-telemetry/opentelemetry-python/pull/4734))
1717
- [BREAKING] Remove LogData and extend SDK LogRecord to have instrumentation scope
1818
([#4676](https://github.com/open-telemetry/opentelemetry-python/pull/4676))
19+
20+
**Migration Guide:**
21+
22+
`LogData` has been removed. Users should update their code as follows:
23+
24+
- **For Log Exporters:** Change from `Sequence[LogData]` to `Sequence[ReadableLogRecord]`
25+
```python
26+
# Before
27+
from opentelemetry.sdk._logs import LogData
28+
def export(self, batch: Sequence[LogData]) -> LogExportResult:
29+
...
30+
31+
# After
32+
from opentelemetry.sdk._logs import ReadableLogRecord
33+
def export(self, batch: Sequence[ReadableLogRecord]) -> LogExportResult:
34+
...
35+
```
36+
37+
- **For Log Processors:** Use `ReadWriteLogRecord` for processing, `ReadableLogRecord` for exporting
38+
```python
39+
# Before
40+
from opentelemetry.sdk._logs import LogData
41+
def on_emit(self, log_data: LogData):
42+
...
43+
44+
# After
45+
from opentelemetry.sdk._logs import ReadWriteLogRecord, ReadableLogRecord
46+
def on_emit(self, log_record: ReadWriteLogRecord):
47+
# Convert to ReadableLogRecord before exporting
48+
readable = ReadableLogRecord(
49+
log_record=log_record.log_record,
50+
resource=log_record.resource or Resource.create({}),
51+
instrumentation_scope=log_record.instrumentation_scope,
52+
limits=log_record.limits,
53+
)
54+
...
55+
```
56+
57+
- **Accessing log data:** Use the same attributes on `ReadableLogRecord`/`ReadWriteLogRecord`
58+
- `log_record.log_record` - The API LogRecord (contains body, severity, attributes, etc.)
59+
- `log_record.resource` - The Resource
60+
- `log_record.instrumentation_scope` - The InstrumentationScope (now included, was in LogData before)
61+
- `log_record.limits` - The LogLimits
1962

2063
## Version 1.38.0/0.59b0 (2025-10-16)
2164

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

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,46 @@ def dropped_attributes(self) -> int:
173173
return self.log_record.attributes.dropped
174174
return 0
175175

176+
def to_json(self, indent: int | None = 4) -> str:
177+
return json.dumps(
178+
{
179+
"body": self.log_record.body,
180+
"severity_number": self.log_record.severity_number.value
181+
if self.log_record.severity_number is not None
182+
else None,
183+
"severity_text": self.log_record.severity_text,
184+
"attributes": (
185+
dict(self.log_record.attributes)
186+
if bool(self.log_record.attributes)
187+
else None
188+
),
189+
"dropped_attributes": self.dropped_attributes,
190+
"timestamp": ns_to_iso_str(self.log_record.timestamp)
191+
if self.log_record.timestamp is not None
192+
else None,
193+
"observed_timestamp": ns_to_iso_str(
194+
self.log_record.observed_timestamp
195+
),
196+
"trace_id": (
197+
f"0x{format_trace_id(self.log_record.trace_id)}"
198+
if self.log_record.trace_id is not None
199+
else ""
200+
),
201+
"span_id": (
202+
f"0x{format_span_id(self.log_record.span_id)}"
203+
if self.log_record.span_id is not None
204+
else ""
205+
),
206+
"trace_flags": self.log_record.trace_flags,
207+
"resource": json.loads(self.resource.to_json()),
208+
"event_name": self.log_record.event_name
209+
if self.log_record.event_name
210+
else "",
211+
},
212+
indent=indent,
213+
cls=BytesEncoder,
214+
)
215+
176216

177217
@dataclass
178218
class ReadWriteLogRecord:
@@ -603,14 +643,17 @@ def emit(self, record: LogRecord):
603643
"""Emits the :class:`ReadWriteLogRecord` by setting instrumentation scope
604644
and forwarding to the processor.
605645
"""
646+
writable_record: ReadWriteLogRecord
606647
if not isinstance(record, ReadWriteLogRecord):
607648
# pylint:disable=protected-access
608-
record = ReadWriteLogRecord._from_api_log_record(
649+
writable_record = ReadWriteLogRecord._from_api_log_record(
609650
record=record,
610651
resource=self._resource,
611652
instrumentation_scope=self._instrumentation_scope,
612653
)
613-
self._multi_log_record_processor.on_emit(record)
654+
else:
655+
writable_record = record
656+
self._multi_log_record_processor.on_emit(writable_record)
614657

615658

616659
class LoggerProvider(APILoggerProvider):

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
ReadableLogRecord,
3232
ReadWriteLogRecord,
3333
)
34+
from opentelemetry.sdk.resources import Resource
3435
from opentelemetry.sdk._shared_internal import BatchProcessor, DuplicateFilter
3536
from opentelemetry.sdk.environment_variables import (
3637
OTEL_BLRP_EXPORT_TIMEOUT,
@@ -124,9 +125,11 @@ def on_emit(self, log_record: ReadWriteLogRecord):
124125
token = attach(set_value(_SUPPRESS_INSTRUMENTATION_KEY, True))
125126
try:
126127
# Convert ReadWriteLogRecord to ReadableLogRecord before exporting
128+
# Note: resource should not be None at this point as it's set during Logger.emit()
129+
resource = log_record.resource if log_record.resource is not None else Resource.create({})
127130
readable_log_record = ReadableLogRecord(
128131
log_record=log_record.log_record,
129-
resource=log_record.resource,
132+
resource=resource,
130133
instrumentation_scope=log_record.instrumentation_scope,
131134
limits=log_record.limits,
132135
)
@@ -199,9 +202,11 @@ def __init__(
199202

200203
def on_emit(self, log_record: ReadWriteLogRecord) -> None:
201204
# Convert ReadWriteLogRecord to ReadableLogRecord before passing to BatchProcessor
205+
# Note: resource should not be None at this point as it's set during Logger.emit()
206+
resource = log_record.resource if log_record.resource is not None else Resource.create({})
202207
readable_log_record = ReadableLogRecord(
203208
log_record=log_record.log_record,
204-
resource=log_record.resource,
209+
resource=resource,
205210
instrumentation_scope=log_record.instrumentation_scope,
206211
limits=log_record.limits,
207212
)

0 commit comments

Comments
 (0)