From b38050c83c78f644471033559eba9cce85270629 Mon Sep 17 00:00:00 2001 From: Artur Shiriev Date: Mon, 19 Jan 2026 17:18:55 +0300 Subject: [PATCH] preserve exc_info in logs dict --- lite_bootstrap/instruments/logging_instrument.py | 12 +++++++++++- tests/instruments/test_logging_instrument.py | 5 +++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/lite_bootstrap/instruments/logging_instrument.py b/lite_bootstrap/instruments/logging_instrument.py index 7f84321..0feaf3f 100644 --- a/lite_bootstrap/instruments/logging_instrument.py +++ b/lite_bootstrap/instruments/logging_instrument.py @@ -15,6 +15,7 @@ if import_checker.is_structlog_installed: import orjson import structlog + from structlog.processors import ExceptionRenderer ScopeType = typing.MutableMapping[str, typing.Any] @@ -96,6 +97,15 @@ class LoggingConfig(BaseConfig): ) +class CustomExceptionRenderer(ExceptionRenderer): + def __call__(self, logger: "WrappedLogger", name: str, event_dict: "EventDict") -> "EventDict": + exc_info = event_dict.get("exc_info") + event_dict = super().__call__(logger=logger, name=name, event_dict=event_dict) + if exc_info: + event_dict["exc_info"] = exc_info + return event_dict + + @dataclasses.dataclass(kw_only=True, slots=True, frozen=True) class LoggingInstrument(BaseInstrument): bootstrap_config: LoggingConfig @@ -111,7 +121,7 @@ def structlog_pre_chain_processors(self) -> list[typing.Any]: structlog.stdlib.PositionalArgumentsFormatter(), structlog.processors.TimeStamper(fmt="%Y-%m-%d %H:%M:%S"), structlog.processors.StackInfoRenderer(), - structlog.processors.format_exc_info, + CustomExceptionRenderer(), structlog.processors.UnicodeDecoder(), ] diff --git a/tests/instruments/test_logging_instrument.py b/tests/instruments/test_logging_instrument.py index 044c597..2fdce14 100644 --- a/tests/instruments/test_logging_instrument.py +++ b/tests/instruments/test_logging_instrument.py @@ -21,6 +21,11 @@ def test_logging_instrument_simple() -> None: try: logging_instrument.bootstrap() logger.info("testing structlog", key="value") + try: + msg = "some error" + raise ValueError(msg) # noqa: TRY301 + except ValueError: + logger.exception("logging error") std_logger.info("testing std logger", extra={"key": "value"}) finally: logging_instrument.teardown()