Skip to content

Commit

Permalink
Check for long running transaction on span exit.
Browse files Browse the repository at this point in the history
  • Loading branch information
antonpirker committed Nov 29, 2024
1 parent d09babd commit 85ba9a5
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 10 deletions.
3 changes: 0 additions & 3 deletions sentry_sdk/integrations/wsgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,6 @@ def __call__(self, status, response_headers, exc_info=None): # type: ignore
pass


MAX_TRANSACTION_DURATION_SECONDS = 5 * 60


_wsgi_middleware_applied = ContextVar("sentry_wsgi_middleware_applied")


Expand Down
29 changes: 29 additions & 0 deletions sentry_sdk/tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
nanosecond_time,
)

MAX_TRANSACTION_DURATION_SECONDS = 5 * 60

from typing import TYPE_CHECKING

if TYPE_CHECKING:
Expand Down Expand Up @@ -377,7 +379,10 @@ def __exit__(self, ty, value, tb):

scope, old_span = self._context_manager_state
del self._context_manager_state

self.finish(scope)
self.prune_transaction()

scope.span = old_span

@property
Expand Down Expand Up @@ -651,6 +656,30 @@ def finish(self, scope=None, end_timestamp=None):

return None

def prune_transaction(self, scope=None):
# type: (Optional[sentry_sdk.Scope]) -> None
if (
self.containing_transaction
and self.containing_transaction.timestamp is not None
):
# transaction already finished, nothing to do
return

trx = self.containing_transaction
if trx is None or self is trx:
return

transaction_duration = (
datetime.now(timezone.utc) - trx.start_timestamp
).total_seconds()

if transaction_duration > MAX_TRANSACTION_DURATION_SECONDS:
logger.debug(
"Finishing Transaction because it is running longer the maximum allowed duration (%ss)",
MAX_TRANSACTION_DURATION_SECONDS,
)
trx.__exit__(None, None, None)

def to_json(self):
# type: () -> Dict[str, Any]
"""Returns a JSON-compatible representation of the span."""
Expand Down
19 changes: 12 additions & 7 deletions tests/integrations/wsgi/test_wsgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -500,20 +500,23 @@ def dogpark(environ, start_response):


def test_long_running_transaction_finished(sentry_init, capture_events):
# we allow transactions to be 0.5 seconds as a maximum
new_max_duration = 0.5
# we allow transactions to be 1 seconds as a maximum
new_max_duration = 1

with mock.patch.object(
sentry_sdk.integrations.wsgi,
sentry_sdk.tracing,
"MAX_TRANSACTION_DURATION_SECONDS",
new_max_duration,
):

def generate_content():
# This response will take 1.5 seconds to generate
for _ in range(15):
time.sleep(0.1)
yield "ok"
with sentry_sdk.start_span(
op="generate_content", name="generate_content {_}"
):
time.sleep(0.1)
yield "ok"

def long_running_app(environ, start_response):
start_response("200 OK", [])
Expand All @@ -534,6 +537,8 @@ def long_running_app(environ, start_response):
datetime_from_isoformat(transaction["timestamp"])
- datetime_from_isoformat(transaction["start_timestamp"])
).total_seconds()

assert (
transaction_duration <= new_max_duration * 1.02
) # we allow 2% margin for processing the request
transaction_duration
<= new_max_duration * 1.05 # we allow 5% margin for processing the request
), "Long running transaction has not been finished after a set maximum duration"

0 comments on commit 85ba9a5

Please sign in to comment.