Skip to content

Commit 308a179

Browse files
committed
Use Timer to finish transaction
1 parent 17b77be commit 308a179

File tree

2 files changed

+31
-17
lines changed

2 files changed

+31
-17
lines changed

sentry_sdk/integrations/wsgi.py

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from datetime import datetime, timezone
22
import sys
33
from functools import partial
4+
from threading import Timer
45

56
import sentry_sdk
67
from sentry_sdk._werkzeug import get_host, _get_headers
@@ -46,7 +47,7 @@ def __call__(self, status, response_headers, exc_info=None): # type: ignore
4647
pass
4748

4849

49-
MAX_TRANSACTION_DURATION_MINUTES = 5
50+
MAX_TRANSACTION_DURATION_SECONDS = 5 * 60
5051

5152

5253
_wsgi_middleware_applied = ContextVar("sentry_wsgi_middleware_applied")
@@ -128,7 +129,12 @@ def __call__(self, environ, start_response):
128129
transaction,
129130
custom_sampling_context={"wsgi_environ": environ},
130131
).__enter__()
131-
132+
timer = Timer(
133+
MAX_TRANSACTION_DURATION_SECONDS,
134+
finish_long_running_transaction,
135+
args=(current_scope, scope),
136+
)
137+
timer.start()
132138
try:
133139
response = self.app(
134140
environ,
@@ -235,6 +241,25 @@ def _capture_exception(exc_info=None):
235241
return exc_info
236242

237243

244+
def finish_long_running_transaction(current_scope, isolation_scope):
245+
# type: (sentry_sdk.scope.Scope, sentry_sdk.scope.Scope) -> None
246+
"""
247+
Make sure we don't keep transactions open for too long.
248+
Triggered after MAX_TRANSACTION_DURATION_SECONDS have passed.
249+
"""
250+
try:
251+
transaction_duration = (
252+
datetime.now(timezone.utc) - current_scope.transaction.start_timestamp
253+
).total_seconds()
254+
if transaction_duration > MAX_TRANSACTION_DURATION_SECONDS:
255+
with use_isolation_scope(isolation_scope):
256+
with use_scope(current_scope):
257+
finish_running_transaction()
258+
except AttributeError:
259+
# transaction is not there anymore
260+
pass
261+
262+
238263
class _ScopedResponse:
239264
"""
240265
Use separate scopes for each response chunk.
@@ -276,17 +301,6 @@ def __iter__(self):
276301

277302
yield chunk
278303

279-
# Finish long running transactions at some point
280-
try:
281-
transaction_duration = (datetime.now(timezone.utc) - self._current_scope.transaction.start_timestamp).total_seconds() / 60
282-
if transaction_duration > MAX_TRANSACTION_DURATION_MINUTES:
283-
with use_isolation_scope(self._isolation_scope):
284-
with use_scope(self._current_scope):
285-
finish_running_transaction(self._current_scope)
286-
except AttributeError:
287-
# transaction is not there anymore
288-
pass
289-
290304
finally:
291305
with use_isolation_scope(self._isolation_scope):
292306
with use_scope(self._current_scope):

tests/integrations/wsgi/test_wsgi.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -501,9 +501,9 @@ def dogpark(environ, start_response):
501501

502502
def test_long_running_transaction_finished(sentry_init, capture_events):
503503
# we allow transactions to be 0.5 seconds as a maximum
504-
new_max_duration = 0.5 / 60
504+
new_max_duration = 0.5
505505

506-
with mock.patch.object(sentry_sdk.integrations.wsgi, "MAX_TRANSACTION_DURATION_MINUTES", new_max_duration):
506+
with mock.patch.object(sentry_sdk.integrations.wsgi, "MAX_TRANSACTION_DURATION_SECONDS", new_max_duration):
507507
def generate_content():
508508
# This response will take 1.5 seconds to generate
509509
for _ in range(15):
@@ -525,5 +525,5 @@ def long_running_app(environ, start_response):
525525

526526
(transaction,) = events
527527

528-
transaction_duration = (datetime_from_isoformat(transaction["timestamp"]) - datetime_from_isoformat(transaction["start_timestamp"])).total_seconds() / 60
529-
assert transaction_duration <= new_max_duration * 1.05 # we allow 2% error margin for processing the request
528+
transaction_duration = (datetime_from_isoformat(transaction["timestamp"]) - datetime_from_isoformat(transaction["start_timestamp"])).total_seconds()
529+
assert transaction_duration <= new_max_duration * 1.2 # we allow 2% margin for processing the request

0 commit comments

Comments
 (0)