Skip to content

Commit 675dc48

Browse files
committed
feat(uptime): Write date_in_progress to CheckIn table
1 parent a7512c6 commit 675dc48

File tree

6 files changed

+84
-1
lines changed

6 files changed

+84
-1
lines changed

migrations_lockfile.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ hybridcloud: 0021_django_arrayfield_scope_list
1313

1414
insights: 0001_add_starred_transactions_model
1515

16-
monitors: 0004_record_date_in_progress_sql_only
16+
monitors: 0005_record_date_in_progress_state
1717

1818
nodestore: 0002_nodestore_no_dictfield
1919

src/sentry/monitors/consumers/monitor_consumer.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,13 +828,17 @@ def _process_checkin(item: CheckinItem, txn: Transaction | Span) -> None:
828828
# to UTC
829829
clock_time = item.ts.replace(tzinfo=UTC)
830830

831+
# Record the reported in_progress time when the check is in progress
832+
date_in_progress = start_time if status == CheckInStatus.IN_PROGRESS else None
833+
831834
check_in, created = MonitorCheckIn.objects.get_or_create(
832835
defaults={
833836
"duration": duration,
834837
"status": status,
835838
"date_added": start_time,
836839
"date_updated": start_time,
837840
"date_clock": clock_time,
841+
"date_in_progress": date_in_progress,
838842
"expected_time": expected_time,
839843
"timeout_at": timeout_at,
840844
"monitor_config": monitor_config,
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Generated by Django 5.2.1 on 2025-05-15 16:51
2+
3+
from django.db import migrations, models
4+
5+
from django.db.migrations import SeparateDatabaseAndState
6+
from sentry.new_migrations.migrations import CheckedMigration
7+
8+
9+
class Migration(CheckedMigration):
10+
# This flag is used to mark that a migration shouldn't be automatically run in production.
11+
# This should only be used for operations where it's safe to run the migration after your
12+
# code has deployed. So this should not be used for most operations that alter the schema
13+
# of a table.
14+
# Here are some things that make sense to mark as post deployment:
15+
# - Large data migrations. Typically we want these to be run manually so that they can be
16+
# monitored and not block the deploy for a long period of time while they run.
17+
# - Adding indexes to large tables. Since this can take a long time, we'd generally prefer to
18+
# run this outside deployments so that we don't block them. Note that while adding an index
19+
# is a schema change, it's completely safe to run the operation after the code has deployed.
20+
# Once deployed, run these manually via: https://develop.sentry.dev/database-migrations/#migration-deployment
21+
22+
is_post_deployment = False
23+
24+
dependencies = [
25+
("monitors", "0004_record_date_in_progress_sql_only"),
26+
]
27+
28+
operations = [
29+
SeparateDatabaseAndState(
30+
database_operations=[],
31+
state_operations=[
32+
migrations.AddField(
33+
model_name="monitorcheckin",
34+
name="date_in_progress",
35+
field=models.DateTimeField(null=True),
36+
)
37+
],
38+
)
39+
]

src/sentry/monitors/models.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,12 @@ class MonitorCheckIn(Model):
495495
as detecting misses)
496496
"""
497497

498+
date_in_progress = models.DateTimeField(null=True)
499+
"""
500+
Records the time when the first in_progress check-in was received by relay.
501+
If no in_progress check-in was ever sent this will remain null.
502+
"""
503+
498504
expected_time = models.DateTimeField(null=True)
499505
"""
500506
Holds the exact time we expected to receive this check-in

src/sentry/monitors/serializers.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ class MonitorCheckInSerializerResponse(MonitorCheckInSerializerResponseOptional)
278278
dateCreated: datetime
279279
dateAdded: datetime
280280
dateUpdated: datetime
281+
dateInProgress: datetime
281282
dateClock: datetime
282283
expectedTime: datetime
283284
monitorConfig: MonitorConfigSerializerResponse
@@ -348,6 +349,7 @@ def serialize(self, obj, attrs, user, **kwargs) -> MonitorCheckInSerializerRespo
348349
"dateAdded": obj.date_added,
349350
"dateUpdated": obj.date_updated,
350351
"dateClock": obj.date_clock,
352+
"dateInProgress": obj.date_in_progress,
351353
"expectedTime": obj.expected_time,
352354
"monitorConfig": cast(MonitorConfigSerializerResponse, config),
353355
}

tests/sentry/monitors/consumers/test_monitor_consumer.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,38 @@ def test_check_in_date_clock(self):
359359
assert checkin.date_added == ts.replace(tzinfo=UTC)
360360
assert checkin.date_clock == item_ts.replace(tzinfo=UTC)
361361

362+
def test_check_in_date_in_progress(self):
363+
monitor = self._create_monitor(slug="my-monitor")
364+
now = datetime.now()
365+
now_tz = now.replace(tzinfo=UTC)
366+
367+
guid1 = uuid.uuid4().hex
368+
369+
# First check-in will not have a date_in_progress, since we never sent
370+
# an in-progress check.
371+
self.send_checkin(monitor.slug, guid=guid1, ts=now, status="ok")
372+
checkin1 = MonitorCheckIn.objects.get(guid=guid1)
373+
assert not checkin1.date_in_progress
374+
375+
# Second check-in does have a date_in_progress
376+
guid2 = uuid.uuid4().hex
377+
378+
self.send_checkin(
379+
monitor.slug,
380+
guid=guid2,
381+
ts=now + timedelta(minutes=1),
382+
status="in_progress",
383+
)
384+
self.send_checkin(
385+
monitor.slug,
386+
guid=guid2,
387+
ts=now + timedelta(minutes=1, seconds=25),
388+
status="ok",
389+
)
390+
391+
checkin2 = MonitorCheckIn.objects.get(guid=guid2)
392+
assert checkin2.date_in_progress == now_tz + timedelta(minutes=1)
393+
362394
def test_check_in_timeout_at(self):
363395
monitor = self._create_monitor(slug="my-monitor")
364396
self.send_checkin(monitor.slug, status="in_progress")

0 commit comments

Comments
 (0)