Skip to content

Commit ffe34cf

Browse files
committed
Always use LogRecord.getMessage to get the log body
Mostly a revert of #3343 Related to #4528
1 parent 0f47f66 commit ffe34cf

File tree

3 files changed

+10
-28
lines changed

3 files changed

+10
-28
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2222
([#4935](https://github.com/open-telemetry/opentelemetry-python/pull/4935))
2323
- `opentelemetry-sdk`: upgrade vendored OTel configuration schema from v1.0.0-rc.3 to v1.0.0
2424
([#4965](https://github.com/open-telemetry/opentelemetry-python/pull/4965))
25+
- Further improve compatibility with other logging libraries that override
26+
`LogRecord.getMessage()` in order to customize message formatting
27+
([#4327](https://github.com/open-telemetry/opentelemetry-python/pull/4327))
2528

2629
## Version 1.40.0/0.61b0 (2026-03-04)
2730

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

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
get_logger,
4040
get_logger_provider,
4141
)
42-
from opentelemetry.attributes import _VALID_ANY_VALUE_TYPES, BoundedAttributes
42+
from opentelemetry.attributes import BoundedAttributes
4343
from opentelemetry.context import get_current
4444
from opentelemetry.context.context import Context
4545
from opentelemetry.metrics import MeterProvider, get_meter_provider
@@ -572,25 +572,7 @@ def _translate(self, record: logging.LogRecord) -> LogRecord:
572572
if self.formatter:
573573
body = self.format(record)
574574
else:
575-
# `record.getMessage()` uses `record.msg` as a template to format
576-
# `record.args` into. There is a special case in `record.getMessage()`
577-
# where it will only attempt formatting if args are provided,
578-
# otherwise, it just stringifies `record.msg`.
579-
#
580-
# Since the OTLP body field has a type of 'any' and the logging module
581-
# is sometimes used in such a way that objects incorrectly end up
582-
# set as record.msg, in those cases we would like to bypass
583-
# `record.getMessage()` completely and set the body to the object
584-
# itself instead of its string representation.
585-
# For more background, see: https://github.com/open-telemetry/opentelemetry-python/pull/4216
586-
if not record.args and not isinstance(record.msg, str):
587-
# if record.msg is not a value we can export, cast it to string
588-
if not isinstance(record.msg, _VALID_ANY_VALUE_TYPES):
589-
body = str(record.msg)
590-
else:
591-
body = record.msg
592-
else:
593-
body = record.getMessage()
575+
body = record.getMessage()
594576

595577
# related to https://github.com/open-telemetry/opentelemetry-python/issues/3548
596578
# Severity Text = WARN as defined in https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#displaying-severity.

opentelemetry-sdk/tests/logs/test_export.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -292,8 +292,8 @@ def test_simple_log_record_processor_different_msg_types(self):
292292
"Temperature hits high 420 C in Hyderabad",
293293
"CRITICAL",
294294
),
295-
(["list", "of", "strings"], "WARN"),
296-
({"key": "value"}, "ERROR"),
295+
("['list', 'of', 'strings']", "WARN"),
296+
("{'key': 'value'}", "ERROR"),
297297
]
298298
emitted = [
299299
(item.log_record.body, item.log_record.severity_text)
@@ -307,8 +307,7 @@ def test_simple_log_record_processor_different_msg_types(self):
307307

308308
def test_simple_log_record_processor_custom_single_obj(self):
309309
"""
310-
Tests that special-case handling for logging a single non-string object
311-
is correctly applied.
310+
Tests that logging a single non-string object uses getMessage
312311
"""
313312
exporter = InMemoryLogRecordExporter()
314313
log_record_processor = BatchLogRecordProcessor(exporter)
@@ -334,9 +333,7 @@ def test_simple_log_record_processor_custom_single_obj(self):
334333
logger.warning("a string with a percent-s: %s", "and arg")
335334
# non-string msg with args - getMessage stringifies msg and formats args into it
336335
logger.warning(["a non-string with a percent-s", "%s"], "and arg")
337-
# non-string msg with no args:
338-
# - normally getMessage would stringify the object and bypass formatting
339-
# - SPECIAL CASE: bypass stringification as well to keep the raw object
336+
# non-string msg with no args - getMessage stringifies the object and bypasses formatting
340337
logger.warning(["a non-string with a percent-s", "%s"])
341338
log_record_processor.shutdown()
342339

@@ -345,7 +342,7 @@ def test_simple_log_record_processor_custom_single_obj(self):
345342
("a string with a percent-s: %s"),
346343
("a string with a percent-s: and arg"),
347344
("['a non-string with a percent-s', 'and arg']"),
348-
(["a non-string with a percent-s", "%s"]),
345+
("['a non-string with a percent-s', '%s']"),
349346
]
350347
for emitted, expected in zip(finished_logs, expected):
351348
self.assertEqual(emitted.log_record.body, expected)

0 commit comments

Comments
 (0)