Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(Litestar): Apply failed_request_status_codes to exceptions raised in middleware #4074

Open
wants to merge 17 commits into
base: master
Choose a base branch
from

Conversation

vrslev
Copy link
Contributor

@vrslev vrslev commented Feb 19, 2025

This is a fix for #4021: exceptions raised in middleware were sent without taking into account failed_request_status_codes value.

See the test case for an example.


Thank you for contributing to sentry-python! Please add tests to validate your changes, and lint your code using tox -e linters.

Running the test suite on your PR might require maintainer approval. The AWS Lambda tests additionally require a maintainer to add a special label, and they will fail until this label is added.

@vrslev vrslev marked this pull request as ready for review February 19, 2025 08:43
Copy link

codecov bot commented Feb 19, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 79.49%. Comparing base (d0d70a5) to head (53baddd).
Report is 1 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #4074      +/-   ##
==========================================
+ Coverage   79.48%   79.49%   +0.01%     
==========================================
  Files         141      141              
  Lines       15809    15815       +6     
  Branches     2703     2703              
==========================================
+ Hits        12565    12572       +7     
  Misses       2382     2382              
+ Partials      862      861       -1     
Files with missing lines Coverage Δ
sentry_sdk/integrations/asgi.py 86.20% <100.00%> (+0.39%) ⬆️
sentry_sdk/integrations/litestar.py 84.86% <100.00%> (+0.20%) ⬆️

... and 2 files with indirect coverage changes

@vrslev
Copy link
Contributor Author

vrslev commented Feb 20, 2025

Relates to #3134

@vrslev
Copy link
Contributor Author

vrslev commented Mar 10, 2025

@sentrivana @antonpirker @untitaker can you review this please? 🙂

@antonpirker antonpirker requested a review from a team as a code owner March 27, 2025 09:42
Copy link
Member

@szokeasaurusrex szokeasaurusrex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the contribution! I need some extra clarification on some items and also have some suggestions, please see the comments I left

@@ -57,17 +57,6 @@
TRANSACTION_STYLE_VALUES = ("endpoint", "url")


def _capture_exception(exc, mechanism_type="asgi"):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to keep this function the same, as a standalone function instead of a method. I don't think it has to be modified to implement your changes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

Comment on lines 146 to 150
def _capture_lifespan_exception(self, exc):
# type: (Exception) -> None
return self._capture_exception(exc)

def _capture_request_exception(self, exc):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am a bit unsure of the difference between these two functions. Please add docstrings to both to clarify the distinction

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

Comment on lines 90 to 92
def _capture_request_exception(self, exc):
# type: (Exception) -> None
"""Ignore exceptions for requests here: we catch them in Litestar.after_exception handler."""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am slightly unsure why this function is needed/how it relates to what you are trying to explain in this PR. Could you please explain in a bit more detail?

Also, I think you need a pass here:

Suggested change
def _capture_request_exception(self, exc):
# type: (Exception) -> None
"""Ignore exceptions for requests here: we catch them in Litestar.after_exception handler."""
def _capture_request_exception(self, exc):
# type: (Exception) -> None
"""Ignore exceptions for requests here: we catch them in Litestar.after_exception handler."""
pass

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, Litestar integration catches exceptions raised in middleware twice:

  1. In the custom ASGI handler.
  2. In the Litestar.after_exception handler, which is added in patch_app_init.

The custom ASGI handler doesn't filter exceptions using failed_request_status_codes, so all exceptions (including those not filtered by the expected status code) appear in Sentry.

Interestingly, this behavior doesn't apply to exceptions raised in request handlers because Litestar prepends the built-in exception handling middleware.


This leads us to the conclusion that the ASGI handler only catches exceptions raised in middleware or lifespan handlers. It's still valuable to catch exceptions from lifespan handlers.

In this case, we patch _capture_request_exception to prevent catching exceptions raised in middleware.

@vrslev vrslev requested a review from a team as a code owner April 1, 2025 14:51
@vrslev vrslev requested a review from szokeasaurusrex April 1, 2025 14:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants