Skip to content

Commit e9829a8

Browse files
rbro112priscilawebdev
authored andcommitted
chore(preprod): Alert to Sentry on PreprodArtifact expiration (#102804)
Had a recent upload fail to process due to a hang. We never received an alert directly from the point of the hang (separate issue), but we do have a fallthrough to catch hanging artifacts. This wires up a [custom message](https://docs.sentry.io/platforms/python/usage/#capturing-messages) which will create an issue for each hung artifact we catch. Resolves EME-600
1 parent c207b48 commit e9829a8

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

src/sentry/preprod/tasks.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,13 @@ def detect_expired_preprod_artifacts() -> None:
642642

643643
if updated_artifact_ids:
644644
for artifact_id in updated_artifact_ids:
645+
sentry_sdk.capture_message(
646+
"PreprodArtifact expired",
647+
level="error",
648+
extras={
649+
"artifact_id": artifact_id,
650+
},
651+
)
645652
try:
646653
create_preprod_status_check_task.apply_async(
647654
kwargs={"preprod_artifact_id": artifact_id}

tests/sentry/preprod/test_tasks.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
from datetime import timedelta
22
from hashlib import sha1
3+
from unittest.mock import patch
34

5+
import sentry_sdk
46
from django.core.files.base import ContentFile
57
from django.utils import timezone
68

@@ -739,6 +741,42 @@ def test_detect_expired_preprod_artifacts_with_expired(self):
739741
and "30 minutes" in expired_size_comparison.error_message
740742
)
741743

744+
def test_detect_expired_preprod_artifacts_captures_sentry_message(self):
745+
"""Test that Sentry messages are captured for each expired artifact"""
746+
current_time = timezone.now()
747+
old_time = current_time - timedelta(minutes=35)
748+
749+
expired_artifact_1 = PreprodArtifact.objects.create(
750+
project=self.project,
751+
state=PreprodArtifact.ArtifactState.UPLOADING,
752+
)
753+
PreprodArtifact.objects.filter(id=expired_artifact_1.id).update(date_updated=old_time)
754+
755+
expired_artifact_2 = PreprodArtifact.objects.create(
756+
project=self.project,
757+
state=PreprodArtifact.ArtifactState.UPLOADED,
758+
)
759+
PreprodArtifact.objects.filter(id=expired_artifact_2.id).update(date_updated=old_time)
760+
761+
with patch.object(sentry_sdk, "capture_message") as mock_capture_message:
762+
detect_expired_preprod_artifacts()
763+
764+
# Should have captured a message for each expired artifact
765+
assert mock_capture_message.call_count == 2
766+
767+
# Verify the message text and parameters
768+
call_args_list = mock_capture_message.call_args_list
769+
captured_artifact_ids = [call[1]["extras"]["artifact_id"] for call in call_args_list]
770+
771+
assert expired_artifact_1.id in captured_artifact_ids
772+
assert expired_artifact_2.id in captured_artifact_ids
773+
774+
# Verify all calls have the same message text, error level, and contain artifact_id
775+
for call in call_args_list:
776+
assert call[0][0] == "PreprodArtifact expired"
777+
assert call[1]["level"] == "error"
778+
assert "artifact_id" in call[1]["extras"]
779+
742780
def test_detect_expired_preprod_artifacts_mixed_states(self):
743781
"""Test that only artifacts in the right states are considered for expiration"""
744782
current_time = timezone.now()

0 commit comments

Comments
 (0)