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 spans for streaming responses in WSGI based frameworks #3798

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

Conversation

antonpirker
Copy link
Member

@antonpirker antonpirker commented Nov 18, 2024

Fixes spans in streaming responses in WSGI based frameworks. Only close the transaction once the response was consumed. This way all the spans created during creation of the response will be recorded with the transaction.

This PR makes sure that:

  • the transaction stays open until all the streaming blocks are sent to the client. (because of this I had to update the tests, to make sure the tests, consume the response, because the Werkzeug test client (used by Flask and Django and our Strawberry tests) will not close the WSGI response)
  • the generator generating the streaming blocks uses the correct scope to have correct parent-child relationship of spans created in the generator.
  • Transactions are limited to a maximum duration of 5 minutes (like Javascript does it)

Fixes #3736

Copy link

codecov bot commented Nov 18, 2024

Codecov Report

Attention: Patch coverage is 89.55224% with 7 lines in your changes missing coverage. Please review.

Project coverage is 79.94%. Comparing base (a7c2d70) to head (7090227).

✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
sentry_sdk/integrations/wsgi.py 91.22% 4 Missing and 1 partial ⚠️
sentry_sdk/tracing_utils.py 80.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3798      +/-   ##
==========================================
+ Coverage   79.89%   79.94%   +0.04%     
==========================================
  Files         137      137              
  Lines       15385    15424      +39     
  Branches     2611     2615       +4     
==========================================
+ Hits        12292    12330      +38     
- Misses       2222     2223       +1     
  Partials      871      871              
Files with missing lines Coverage Δ
sentry_sdk/tracing_utils.py 83.92% <80.00%> (-0.11%) ⬇️
sentry_sdk/integrations/wsgi.py 85.63% <91.22%> (+0.80%) ⬆️

... and 2 files with indirect coverage changes

@antonpirker antonpirker changed the title Fix spans for streaming responses Fix spans for streaming responses in WSGI based frameworks Nov 20, 2024
@antonpirker antonpirker self-assigned this Nov 21, 2024
@antonpirker antonpirker force-pushed the antonpirker/fix-streaming-response branch from 32c40ed to c612326 Compare November 21, 2024 14:09
@antonpirker antonpirker force-pushed the antonpirker/fix-streaming-response branch from 15eb914 to 30d18fa Compare November 22, 2024 11:41
@antonpirker antonpirker marked this pull request as ready for review November 22, 2024 12:19
Copy link
Contributor

@sentrivana sentrivana left a comment

Choose a reason for hiding this comment

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

Left a couple of comments. As long as the tests for the various integrations that use the WSGI middleware are happy, I think this looks good.

transaction_duration = (
datetime.now(timezone.utc) - current_scope.transaction.start_timestamp
).total_seconds()
if transaction_duration > MAX_TRANSACTION_DURATION_SECONDS:
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need to check this here? Since this function can only get called when the timer fires this should always be the case

Comment on lines +753 to +754
if timer is not None:
timer.cancel()
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we maybe always cancel the timer as the first step in this function without the conditional checks on lines 749-752?

What I'm worried might happen is that if we for some reason don't cancel the timer (because there is no transaction anymore for instance), it'll still fire the _finish_long_running_transaction event at a later point and might potentially end up cancelling a different active transaction. IDK if that can realistically happen due to how we pass the scopes around, but probably doesn't hurt to be more cautious here.

sentry_sdk/integrations/wsgi.py Show resolved Hide resolved
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.

Django StreamingHttpResponse View not working as expected
2 participants