Skip to content

Commit bc72f78

Browse files
authored
feat(litestar): Add failed_request_status_codes (#4021)
1 parent ab36fc4 commit bc72f78

File tree

5 files changed

+77
-23
lines changed

5 files changed

+77
-23
lines changed

sentry_sdk/integrations/litestar.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1+
from collections.abc import Set
12
import sentry_sdk
23
from sentry_sdk.consts import OP
3-
from sentry_sdk.integrations import DidNotEnable, Integration
4+
from sentry_sdk.integrations import (
5+
_DEFAULT_FAILED_REQUEST_STATUS_CODES,
6+
DidNotEnable,
7+
Integration,
8+
)
49
from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
510
from sentry_sdk.integrations.logging import ignore_logger
611
from sentry_sdk.scope import should_send_default_pii
@@ -17,6 +22,7 @@
1722
from litestar.middleware import DefineMiddleware # type: ignore
1823
from litestar.routes.http import HTTPRoute # type: ignore
1924
from litestar.data_extractors import ConnectionDataExtractor # type: ignore
25+
from litestar.exceptions import HTTPException # type: ignore
2026
except ImportError:
2127
raise DidNotEnable("Litestar is not installed")
2228

@@ -45,6 +51,12 @@ class LitestarIntegration(Integration):
4551
identifier = "litestar"
4652
origin = f"auto.http.{identifier}"
4753

54+
def __init__(
55+
self,
56+
failed_request_status_codes=_DEFAULT_FAILED_REQUEST_STATUS_CODES, # type: Set[int]
57+
) -> None:
58+
self.failed_request_status_codes = failed_request_status_codes
59+
4860
@staticmethod
4961
def setup_once():
5062
# type: () -> None
@@ -277,6 +289,14 @@ def exception_handler(exc, scope):
277289
sentry_scope = sentry_sdk.get_isolation_scope()
278290
sentry_scope.set_user(user_info)
279291

292+
if isinstance(exc, HTTPException):
293+
integration = sentry_sdk.get_client().get_integration(LitestarIntegration)
294+
if (
295+
integration is not None
296+
and exc.status_code not in integration.failed_request_status_codes
297+
):
298+
return
299+
280300
event, hint = event_from_exception(
281301
exc,
282302
client_options=sentry_sdk.get_client().options,

tests/integrations/conftest.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,24 @@ def capture_event_scope(self, event, hint=None, scope=None):
3232
return errors
3333

3434
return inner
35+
36+
37+
parametrize_test_configurable_status_codes = pytest.mark.parametrize(
38+
("failed_request_status_codes", "status_code", "expected_error"),
39+
(
40+
(None, 500, True),
41+
(None, 400, False),
42+
({500, 501}, 500, True),
43+
({500, 501}, 401, False),
44+
({*range(400, 500)}, 401, True),
45+
({*range(400, 500)}, 500, False),
46+
({*range(400, 600)}, 300, False),
47+
({*range(400, 600)}, 403, True),
48+
({*range(400, 600)}, 503, True),
49+
({*range(400, 403), 500, 501}, 401, True),
50+
({*range(400, 403), 500, 501}, 405, False),
51+
({*range(400, 403), 500, 501}, 501, True),
52+
({*range(400, 403), 500, 501}, 503, False),
53+
(set(), 500, False),
54+
),
55+
)

tests/integrations/fastapi/test_fastapi.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
FASTAPI_VERSION = parse_version(fastapi.__version__)
2121

22+
from tests.integrations.conftest import parametrize_test_configurable_status_codes
2223
from tests.integrations.starlette import test_starlette
2324

2425

@@ -650,7 +651,7 @@ def test_transaction_http_method_custom(sentry_init, capture_events):
650651
assert event2["request"]["method"] == "HEAD"
651652

652653

653-
@test_starlette.parametrize_test_configurable_status_codes
654+
@parametrize_test_configurable_status_codes
654655
def test_configurable_status_codes(
655656
sentry_init,
656657
capture_events,

tests/integrations/litestar/test_litestar.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22
import functools
33

4+
from litestar.exceptions import HTTPException
45
import pytest
56

67
from sentry_sdk import capture_message
@@ -16,6 +17,8 @@
1617
from litestar.middleware.session.server_side import ServerSideSessionConfig
1718
from litestar.testing import TestClient
1819

20+
from tests.integrations.conftest import parametrize_test_configurable_status_codes
21+
1922

2023
def litestar_app_factory(middleware=None, debug=True, exception_handlers=None):
2124
class MyController(Controller):
@@ -396,3 +399,31 @@ async def __call__(self, scope, receive, send):
396399
}
397400
else:
398401
assert "user" not in event
402+
403+
404+
@parametrize_test_configurable_status_codes
405+
def test_configurable_status_codes(
406+
sentry_init,
407+
capture_events,
408+
failed_request_status_codes,
409+
status_code,
410+
expected_error,
411+
):
412+
integration_kwargs = (
413+
{"failed_request_status_codes": failed_request_status_codes}
414+
if failed_request_status_codes is not None
415+
else {}
416+
)
417+
sentry_init(integrations=[LitestarIntegration(**integration_kwargs)])
418+
419+
events = capture_events()
420+
421+
@get("/error")
422+
async def error() -> None:
423+
raise HTTPException(status_code=status_code)
424+
425+
app = Litestar([error])
426+
client = TestClient(app)
427+
client.get("/error")
428+
429+
assert len(events) == int(expected_error)

tests/integrations/starlette/test_starlette.py

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
from starlette.middleware.trustedhost import TrustedHostMiddleware
3333
from starlette.testclient import TestClient
3434

35+
from tests.integrations.conftest import parametrize_test_configurable_status_codes
36+
3537

3638
STARLETTE_VERSION = parse_version(starlette.__version__)
3739

@@ -1298,27 +1300,6 @@ def test_transaction_http_method_custom(sentry_init, capture_events):
12981300
assert event2["request"]["method"] == "HEAD"
12991301

13001302

1301-
parametrize_test_configurable_status_codes = pytest.mark.parametrize(
1302-
("failed_request_status_codes", "status_code", "expected_error"),
1303-
(
1304-
(None, 500, True),
1305-
(None, 400, False),
1306-
({500, 501}, 500, True),
1307-
({500, 501}, 401, False),
1308-
({*range(400, 500)}, 401, True),
1309-
({*range(400, 500)}, 500, False),
1310-
({*range(400, 600)}, 300, False),
1311-
({*range(400, 600)}, 403, True),
1312-
({*range(400, 600)}, 503, True),
1313-
({*range(400, 403), 500, 501}, 401, True),
1314-
({*range(400, 403), 500, 501}, 405, False),
1315-
({*range(400, 403), 500, 501}, 501, True),
1316-
({*range(400, 403), 500, 501}, 503, False),
1317-
(set(), 500, False),
1318-
),
1319-
)
1320-
1321-
13221303
@parametrize_test_configurable_status_codes
13231304
def test_configurable_status_codes(
13241305
sentry_init,

0 commit comments

Comments
 (0)