11import sys
2+ from contextlib import nullcontext
23from functools import partial
34
45import sentry_sdk
1112)
1213from sentry_sdk .sessions import track_session
1314from sentry_sdk .tracing import Transaction , TRANSACTION_SOURCE_ROUTE
14- from sentry_sdk .tracing_utils import finish_running_transaction
1515from sentry_sdk .utils import (
1616 ContextVar ,
1717 capture_internal_exceptions ,
@@ -44,9 +44,6 @@ def __call__(self, status, response_headers, exc_info=None): # type: ignore
4444 pass
4545
4646
47- MAX_TRANSACTION_DURATION_SECONDS = 5 * 60
48-
49-
5047_wsgi_middleware_applied = ContextVar ("sentry_wsgi_middleware_applied" )
5148
5249DEFAULT_TRANSACTION_NAME = "generic WSGI request"
@@ -113,7 +110,6 @@ def __call__(self, environ, start_response):
113110 scope .set_transaction_name (
114111 DEFAULT_TRANSACTION_NAME , source = TRANSACTION_SOURCE_ROUTE
115112 )
116- current_scope = sentry_sdk .get_current_scope ()
117113
118114 with track_session (scope , session_mode = "request" ):
119115 with capture_internal_exceptions ():
@@ -124,14 +120,11 @@ def __call__(self, environ, start_response):
124120 environ , self .use_x_forwarded_for
125121 )
126122 )
127-
128123 method = environ .get ("REQUEST_METHOD" , "" ).upper ()
129124 should_trace = method in self .http_methods_to_capture
130- transaction = None
131-
132125 with sentry_sdk .continue_trace (environ ):
133- if should_trace :
134- transaction = sentry_sdk .start_span (
126+ with (
127+ sentry_sdk .start_span (
135128 op = OP .HTTP_SERVER ,
136129 name = DEFAULT_TRANSACTION_NAME ,
137130 source = TRANSACTION_SOURCE_ROUTE ,
@@ -140,9 +133,9 @@ def __call__(self, environ, start_response):
140133 environ , self .use_x_forwarded_for
141134 ),
142135 )
143- transaction . __enter__ ()
144- current_scope = transaction . scope
145-
136+ if should_trace
137+ else nullcontext ()
138+ ) as transaction :
146139 try :
147140 response = self .app (
148141 environ ,
@@ -153,20 +146,12 @@ def __call__(self, environ, start_response):
153146 ),
154147 )
155148 except BaseException :
156- exc_info = sys .exc_info ()
157- _capture_exception (exc_info )
158- finish_running_transaction (transaction , exc_info )
159- reraise (* exc_info )
149+ reraise (* _capture_exception ())
160150
161151 finally :
162152 _wsgi_middleware_applied .set (False )
163153
164- return _ScopedResponse (
165- response = response ,
166- current_scope = current_scope ,
167- isolation_scope = scope ,
168- transaction = transaction ,
169- )
154+ return _ScopedResponse (scope , response )
170155
171156
172157def _sentry_start_response ( # type: ignore
@@ -228,13 +213,13 @@ def get_client_ip(environ):
228213 return environ .get ("REMOTE_ADDR" )
229214
230215
231- def _capture_exception (exc_info = None ):
232- # type: (Optional[ExcInfo] ) -> ExcInfo
216+ def _capture_exception ():
217+ # type: () -> ExcInfo
233218 """
234219 Captures the current exception and sends it to Sentry.
235220 Returns the ExcInfo tuple to it can be reraised afterwards.
236221 """
237- exc_info = exc_info or sys .exc_info ()
222+ exc_info = sys .exc_info ()
238223 e = exc_info [1 ]
239224
240225 # SystemExit(0) is the only uncaught exception that is expected behavior
@@ -252,7 +237,7 @@ def _capture_exception(exc_info=None):
252237
253238class _ScopedResponse :
254239 """
255- Use separate scopes for each response chunk.
240+ Users a separate scope for each response chunk.
256241
257242 This will make WSGI apps more tolerant against:
258243 - WSGI servers streaming responses from a different thread/from
@@ -261,54 +246,37 @@ class _ScopedResponse:
261246 - WSGI servers streaming responses interleaved from the same thread
262247 """
263248
264- __slots__ = ("_response" , "_current_scope" , "_isolation_scope" , "_transaction " )
249+ __slots__ = ("_response" , "_scope " )
265250
266- def __init__ (
267- self ,
268- response , # type: Iterator[bytes]
269- current_scope , # type: sentry_sdk.scope.Scope
270- isolation_scope , # type: sentry_sdk.scope.Scope
271- transaction = None , # type: Optional[Transaction]
272- ):
273- # type: (...) -> None
251+ def __init__ (self , scope , response ):
252+ # type: (sentry_sdk.scope.Scope, Iterator[bytes]) -> None
253+ self ._scope = scope
274254 self ._response = response
275- self ._current_scope = current_scope
276- self ._isolation_scope = isolation_scope
277- self ._transaction = transaction
278255
279256 def __iter__ (self ):
280257 # type: () -> Iterator[bytes]
281258 iterator = iter (self ._response )
282259
283- try :
284- while True :
285- with sentry_sdk .use_isolation_scope (self ._isolation_scope ):
286- with sentry_sdk .use_scope (self ._current_scope ):
287- try :
288- chunk = next (iterator )
289- except StopIteration :
290- break
291- except BaseException :
292- reraise (* _capture_exception ())
293-
294- yield chunk
260+ while True :
261+ with sentry_sdk .use_isolation_scope (self ._scope ):
262+ try :
263+ chunk = next (iterator )
264+ except StopIteration :
265+ break
266+ except BaseException :
267+ reraise (* _capture_exception ())
295268
296- finally :
297- with sentry_sdk .use_isolation_scope (self ._isolation_scope ):
298- with sentry_sdk .use_scope (self ._current_scope ):
299- finish_running_transaction (transaction = self ._transaction )
269+ yield chunk
300270
301271 def close (self ):
302272 # type: () -> None
303- with sentry_sdk .use_isolation_scope (self ._isolation_scope ):
304- with sentry_sdk .use_scope (self ._current_scope ):
305- try :
306- finish_running_transaction (transaction = self ._transaction )
307- self ._response .close () # type: ignore
308- except AttributeError :
309- pass
310- except BaseException :
311- reraise (* _capture_exception ())
273+ with sentry_sdk .use_isolation_scope (self ._scope ):
274+ try :
275+ self ._response .close () # type: ignore
276+ except AttributeError :
277+ pass
278+ except BaseException :
279+ reraise (* _capture_exception ())
312280
313281
314282def _make_wsgi_event_processor (environ , use_x_forwarded_for ):
0 commit comments