From f0b26a76523a12f811ba7cce6c70f43aee347841 Mon Sep 17 00:00:00 2001 From: Artur Shiriev Date: Sun, 20 Sep 2026 17:14:41 +0300 Subject: [PATCH] fix: pass sentry_logs_level only to sentry-sdk versions that accept it --- .../instruments/sentry_instrument.py | 15 +++++++++++---- tests/instruments/test_sentry_instrument.py | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/lite_bootstrap/instruments/sentry_instrument.py b/lite_bootstrap/instruments/sentry_instrument.py index 2924422..8564554 100644 --- a/lite_bootstrap/instruments/sentry_instrument.py +++ b/lite_bootstrap/instruments/sentry_instrument.py @@ -1,4 +1,5 @@ import dataclasses +import inspect import logging import typing @@ -17,6 +18,12 @@ import sentry_sdk from sentry_sdk.integrations.logging import LoggingIntegration + # sentry-sdk 2.25 added the parameter along with Sentry Logs; the declared floor is 2.1, + # where passing it raises TypeError and there is no logs handler to disable anyway. + SENTRY_LOGS_LEVEL_SUPPORTED: typing.Final = ( + "sentry_logs_level" in inspect.signature(LoggingIntegration.__init__).parameters + ) + # Back-compat alias: this vocabulary moved to logging_factory and was renamed # STRUCTLOG_META_KEYS. Preserved here for external importers of the old name. @@ -110,10 +117,10 @@ def _build_integrations(self) -> list["Integration"]: if not config.sentry_default_integrations: self._warn_breadcrumb_level_ignored("sentry_default_integrations is False") return config.sentry_integrations - return [ - *config.sentry_integrations, - LoggingIntegration(level=config.sentry_logging_breadcrumb_level, sentry_logs_level=None), - ] + logging_integration_kwargs: dict[str, typing.Any] = {"level": config.sentry_logging_breadcrumb_level} + if SENTRY_LOGS_LEVEL_SUPPORTED: + logging_integration_kwargs["sentry_logs_level"] = None + return [*config.sentry_integrations, LoggingIntegration(**logging_integration_kwargs)] def bootstrap(self) -> None: config = self.bootstrap_config diff --git a/tests/instruments/test_sentry_instrument.py b/tests/instruments/test_sentry_instrument.py index e3c3c56..0ced91b 100644 --- a/tests/instruments/test_sentry_instrument.py +++ b/tests/instruments/test_sentry_instrument.py @@ -9,6 +9,7 @@ import structlog from sentry_sdk.integrations.logging import LoggingIntegration +from lite_bootstrap.instruments import sentry_instrument from lite_bootstrap.instruments.logging_instrument import LoggingConfig, LoggingInstrument from tests.conftest import LoggingMock, SentryTestTransport @@ -273,3 +274,20 @@ def test_sentry_does_not_warn_when_the_breadcrumb_level_is_left_at_its_default( assert [one for one in recwarn if "sentry_logging_breadcrumb_level" in str(one.message)] == [] finally: instrument.teardown() + + +@pytest.mark.parametrize("supported", [True, False], ids=["sdk_has_it", "sdk_lacks_it"]) +def test_sentry_passes_sentry_logs_level_only_when_the_sdk_accepts_it( + minimal_sentry_config: SentryConfig, monkeypatch: pytest.MonkeyPatch, supported: bool +) -> None: + """INVARIANT: `sentry_logs_level` reaches only the sentry-sdk versions that accept it. + + It arrived in sentry-sdk 2.25 while the declared floor is 2.1, where passing it raises + `TypeError: LoggingIntegration.__init__() got an unexpected keyword argument` at bootstrap. + Below 2.25 there is no Sentry Logs feature, so there is no handler to disable either. + """ + monkeypatch.setattr(sentry_instrument, "SENTRY_LOGS_LEVEL_SUPPORTED", supported) + integrations = SentryInstrument(bootstrap_config=minimal_sentry_config)._build_integrations() # noqa: SLF001 + + logging_integration = next(one for one in integrations if isinstance(one, LoggingIntegration)) + assert (logging_integration._sentry_logs_handler is None) is supported # noqa: SLF001