Skip to content

Commit bebd815

Browse files
antonpirkersentry-bot
andauthored
fix(python): Capture only 5xx HTTP errors in Falcon Integration (#1314)
* Only catch errors that lead to a HTTP 5xx * Write code that is actually somehow typed and can be linted. Co-authored-by: sentry-bot <[email protected]>
1 parent 6d89f4f commit bebd815

File tree

2 files changed

+82
-7
lines changed

2 files changed

+82
-7
lines changed

sentry_sdk/integrations/falcon.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ def sentry_patched_handle_exception(self, *args):
153153
hub = Hub.current
154154
integration = hub.get_integration(FalconIntegration)
155155

156-
if integration is not None and not _is_falcon_http_error(ex):
156+
if integration is not None and _exception_leads_to_http_5xx(ex):
157157
# If an integration is there, a client has to be there.
158158
client = hub.client # type: Any
159159

@@ -186,9 +186,15 @@ def sentry_patched_prepare_middleware(
186186
falcon.api_helpers.prepare_middleware = sentry_patched_prepare_middleware
187187

188188

189-
def _is_falcon_http_error(ex):
190-
# type: (BaseException) -> bool
191-
return isinstance(ex, (falcon.HTTPError, falcon.http_status.HTTPStatus))
189+
def _exception_leads_to_http_5xx(ex):
190+
# type: (Exception) -> bool
191+
is_server_error = isinstance(ex, falcon.HTTPError) and (ex.status or "").startswith(
192+
"5"
193+
)
194+
is_unhandled_error = not isinstance(
195+
ex, (falcon.HTTPError, falcon.http_status.HTTPStatus)
196+
)
197+
return is_server_error or is_unhandled_error
192198

193199

194200
def _make_request_event_processor(req, integration):

tests/integrations/falcon/test_falcon.py

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,15 +71,15 @@ def test_transaction_style(
7171
assert event["transaction"] == expected_transaction
7272

7373

74-
def test_errors(sentry_init, capture_exceptions, capture_events):
74+
def test_unhandled_errors(sentry_init, capture_exceptions, capture_events):
7575
sentry_init(integrations=[FalconIntegration()], debug=True)
7676

77-
class ZeroDivisionErrorResource:
77+
class Resource:
7878
def on_get(self, req, resp):
7979
1 / 0
8080

8181
app = falcon.API()
82-
app.add_route("/", ZeroDivisionErrorResource())
82+
app.add_route("/", Resource())
8383

8484
exceptions = capture_exceptions()
8585
events = capture_events()
@@ -96,6 +96,75 @@ def on_get(self, req, resp):
9696

9797
(event,) = events
9898
assert event["exception"]["values"][0]["mechanism"]["type"] == "falcon"
99+
assert " by zero" in event["exception"]["values"][0]["value"]
100+
101+
102+
def test_raised_5xx_errors(sentry_init, capture_exceptions, capture_events):
103+
sentry_init(integrations=[FalconIntegration()], debug=True)
104+
105+
class Resource:
106+
def on_get(self, req, resp):
107+
raise falcon.HTTPError(falcon.HTTP_502)
108+
109+
app = falcon.API()
110+
app.add_route("/", Resource())
111+
112+
exceptions = capture_exceptions()
113+
events = capture_events()
114+
115+
client = falcon.testing.TestClient(app)
116+
client.simulate_get("/")
117+
118+
(exc,) = exceptions
119+
assert isinstance(exc, falcon.HTTPError)
120+
121+
(event,) = events
122+
assert event["exception"]["values"][0]["mechanism"]["type"] == "falcon"
123+
assert event["exception"]["values"][0]["type"] == "HTTPError"
124+
125+
126+
def test_raised_4xx_errors(sentry_init, capture_exceptions, capture_events):
127+
sentry_init(integrations=[FalconIntegration()], debug=True)
128+
129+
class Resource:
130+
def on_get(self, req, resp):
131+
raise falcon.HTTPError(falcon.HTTP_400)
132+
133+
app = falcon.API()
134+
app.add_route("/", Resource())
135+
136+
exceptions = capture_exceptions()
137+
events = capture_events()
138+
139+
client = falcon.testing.TestClient(app)
140+
client.simulate_get("/")
141+
142+
assert len(exceptions) == 0
143+
assert len(events) == 0
144+
145+
146+
def test_http_status(sentry_init, capture_exceptions, capture_events):
147+
"""
148+
This just demonstrates, that if Falcon raises a HTTPStatus with code 500
149+
(instead of a HTTPError with code 500) Sentry will not capture it.
150+
"""
151+
sentry_init(integrations=[FalconIntegration()], debug=True)
152+
153+
class Resource:
154+
def on_get(self, req, resp):
155+
raise falcon.http_status.HTTPStatus(falcon.HTTP_508)
156+
157+
app = falcon.API()
158+
app.add_route("/", Resource())
159+
160+
exceptions = capture_exceptions()
161+
events = capture_events()
162+
163+
client = falcon.testing.TestClient(app)
164+
client.simulate_get("/")
165+
166+
assert len(exceptions) == 0
167+
assert len(events) == 0
99168

100169

101170
def test_falcon_large_json_request(sentry_init, capture_events):

0 commit comments

Comments
 (0)