11import sys
22from functools import partial
3- from threading import Timer
43
54import sentry_sdk
65from sentry_sdk ._werkzeug import get_host , _get_headers
76from sentry_sdk .api import continue_trace
87from sentry_sdk .consts import OP
9- from sentry_sdk .scope import should_send_default_pii , use_isolation_scope , use_scope
8+ from sentry_sdk .scope import should_send_default_pii
109from sentry_sdk .integrations ._wsgi_common import (
1110 DEFAULT_HTTP_METHODS_TO_CAPTURE ,
1211 _filter_headers ,
12+ nullcontext ,
1313)
1414from sentry_sdk .sessions import track_session
15+ from sentry_sdk .scope import use_isolation_scope
1516from sentry_sdk .tracing import Transaction , TRANSACTION_SOURCE_ROUTE
16- from sentry_sdk .tracing_utils import finish_running_transaction
1717from sentry_sdk .utils import (
1818 ContextVar ,
1919 capture_internal_exceptions ,
@@ -46,9 +46,6 @@ def __call__(self, status, response_headers, exc_info=None): # type: ignore
4646 pass
4747
4848
49- MAX_TRANSACTION_DURATION_SECONDS = 5 * 60
50-
51-
5249_wsgi_middleware_applied = ContextVar ("sentry_wsgi_middleware_applied" )
5350
5451
@@ -101,7 +98,6 @@ def __call__(self, environ, start_response):
10198 _wsgi_middleware_applied .set (True )
10299 try :
103100 with sentry_sdk .isolation_scope () as scope :
104- current_scope = sentry_sdk .get_current_scope ()
105101 with track_session (scope , session_mode = "request" ):
106102 with capture_internal_exceptions ():
107103 scope .clear_breadcrumbs ()
@@ -113,7 +109,6 @@ def __call__(self, environ, start_response):
113109 )
114110
115111 method = environ .get ("REQUEST_METHOD" , "" ).upper ()
116-
117112 transaction = None
118113 if method in self .http_methods_to_capture :
119114 transaction = continue_trace (
@@ -124,43 +119,27 @@ def __call__(self, environ, start_response):
124119 origin = self .span_origin ,
125120 )
126121
127- timer = None
128- if transaction is not None :
122+ with (
129123 sentry_sdk .start_transaction (
130124 transaction ,
131125 custom_sampling_context = {"wsgi_environ" : environ },
132- ).__enter__ ()
133- timer = Timer (
134- MAX_TRANSACTION_DURATION_SECONDS ,
135- _finish_long_running_transaction ,
136- args = (current_scope , scope ),
137126 )
138- timer .start ()
139-
140- try :
141- response = self .app (
142- environ ,
143- partial (
144- _sentry_start_response ,
145- start_response ,
146- transaction ,
147- ),
148- )
149- except BaseException :
150- exc_info = sys .exc_info ()
151- _capture_exception (exc_info )
152- finish_running_transaction (current_scope , exc_info , timer )
153- reraise (* exc_info )
154-
127+ if transaction is not None
128+ else nullcontext ()
129+ ):
130+ try :
131+ response = self .app (
132+ environ ,
133+ partial (
134+ _sentry_start_response , start_response , transaction
135+ ),
136+ )
137+ except BaseException :
138+ reraise (* _capture_exception ())
155139 finally :
156140 _wsgi_middleware_applied .set (False )
157141
158- return _ScopedResponse (
159- response = response ,
160- current_scope = current_scope ,
161- isolation_scope = scope ,
162- timer = timer ,
163- )
142+ return _ScopedResponse (scope , response )
164143
165144
166145def _sentry_start_response ( # type: ignore
@@ -222,13 +201,13 @@ def get_client_ip(environ):
222201 return environ .get ("REMOTE_ADDR" )
223202
224203
225- def _capture_exception (exc_info = None ):
226- # type: (Optional[ExcInfo] ) -> ExcInfo
204+ def _capture_exception ():
205+ # type: () -> ExcInfo
227206 """
228207 Captures the current exception and sends it to Sentry.
229208 Returns the ExcInfo tuple to it can be reraised afterwards.
230209 """
231- exc_info = exc_info or sys .exc_info ()
210+ exc_info = sys .exc_info ()
232211 e = exc_info [1 ]
233212
234213 # SystemExit(0) is the only uncaught exception that is expected behavior
@@ -246,7 +225,7 @@ def _capture_exception(exc_info=None):
246225
247226class _ScopedResponse :
248227 """
249- Use separate scopes for each response chunk.
228+ Users a separate scope for each response chunk.
250229
251230 This will make WSGI apps more tolerant against:
252231 - WSGI servers streaming responses from a different thread/from
@@ -255,54 +234,37 @@ class _ScopedResponse:
255234 - WSGI servers streaming responses interleaved from the same thread
256235 """
257236
258- __slots__ = ("_response" , "_current_scope" , "_isolation_scope" , "_timer " )
237+ __slots__ = ("_response" , "_scope " )
259238
260- def __init__ (
261- self ,
262- response , # type: Iterator[bytes]
263- current_scope , # type: sentry_sdk.scope.Scope
264- isolation_scope , # type: sentry_sdk.scope.Scope
265- timer = None , # type: Optional[Timer]
266- ):
267- # type: (...) -> None
239+ def __init__ (self , scope , response ):
240+ # type: (sentry_sdk.scope.Scope, Iterator[bytes]) -> None
241+ self ._scope = scope
268242 self ._response = response
269- self ._current_scope = current_scope
270- self ._isolation_scope = isolation_scope
271- self ._timer = timer
272243
273244 def __iter__ (self ):
274245 # type: () -> Iterator[bytes]
275246 iterator = iter (self ._response )
276247
277- try :
278- while True :
279- with use_isolation_scope (self ._isolation_scope ):
280- with use_scope (self ._current_scope ):
281- try :
282- chunk = next (iterator )
283- except StopIteration :
284- break
285- except BaseException :
286- reraise (* _capture_exception ())
287-
288- yield chunk
248+ while True :
249+ with use_isolation_scope (self ._scope ):
250+ try :
251+ chunk = next (iterator )
252+ except StopIteration :
253+ break
254+ except BaseException :
255+ reraise (* _capture_exception ())
289256
290- finally :
291- with use_isolation_scope (self ._isolation_scope ):
292- with use_scope (self ._current_scope ):
293- finish_running_transaction (timer = self ._timer )
257+ yield chunk
294258
295259 def close (self ):
296260 # type: () -> None
297- with use_isolation_scope (self ._isolation_scope ):
298- with use_scope (self ._current_scope ):
299- try :
300- finish_running_transaction (timer = self ._timer )
301- self ._response .close () # type: ignore
302- except AttributeError :
303- pass
304- except BaseException :
305- reraise (* _capture_exception ())
261+ with use_isolation_scope (self ._scope ):
262+ try :
263+ self ._response .close () # type: ignore
264+ except AttributeError :
265+ pass
266+ except BaseException :
267+ reraise (* _capture_exception ())
306268
307269
308270def _make_wsgi_event_processor (environ , use_x_forwarded_for ):
@@ -346,18 +308,3 @@ def event_processor(event, hint):
346308 return event
347309
348310 return event_processor
349-
350-
351- def _finish_long_running_transaction (current_scope , isolation_scope ):
352- # type: (sentry_sdk.scope.Scope, sentry_sdk.scope.Scope) -> None
353- """
354- Make sure we don't keep transactions open for too long.
355- Triggered after MAX_TRANSACTION_DURATION_SECONDS have passed.
356- """
357- try :
358- with use_isolation_scope (isolation_scope ):
359- with use_scope (current_scope ):
360- finish_running_transaction ()
361- except AttributeError :
362- # transaction is not there anymore
363- pass
0 commit comments