Skip to content

Commit 49faf7c

Browse files
authored
migration(crons): Add MonitorIncident table (#56435)
Adds `MonitorIncidentTable` to keep track of open monitor incidents + display them on the timeline view. If a `failure` threshold is set, we will open an `incident` and tag it with the appropriate `hash` and reference the `checkin` that caused it to pass the threshold. If a `recovery` threshold is set, we will find any `incident` with the appropriate `hash` and set it as the `closing_checkin`. In the future, if no thresholds are set, we will move to this behavior. But for now, we will keep existing behavior as-is. The `thresholds` can be derived from the `checkin` configs, though we may want to add them as top level fields.
1 parent 58ee52a commit 49faf7c

File tree

6 files changed

+133
-2
lines changed

6 files changed

+133
-2
lines changed

fixtures/backup/model_dependencies/detailed.json

+25
Original file line numberDiff line numberDiff line change
@@ -1830,6 +1830,31 @@
18301830
"Region"
18311831
]
18321832
},
1833+
"sentry.MonitorIncident": {
1834+
"foreign_keys": {
1835+
"monitor": {
1836+
"kind": "FlexibleForeignKey",
1837+
"model": "sentry.Monitor"
1838+
},
1839+
"monitor_environment": {
1840+
"kind": "FlexibleForeignKey",
1841+
"model": "sentry.MonitorEnvironment"
1842+
},
1843+
"resolving_checkin": {
1844+
"kind": "FlexibleForeignKey",
1845+
"model": "sentry.MonitorCheckIn"
1846+
},
1847+
"starting_checkin": {
1848+
"kind": "FlexibleForeignKey",
1849+
"model": "sentry.MonitorCheckIn"
1850+
}
1851+
},
1852+
"model": "sentry.MonitorIncident",
1853+
"relocation_scope": "Excluded",
1854+
"silos": [
1855+
"Region"
1856+
]
1857+
},
18331858
"sentry.MonitorLocation": {
18341859
"foreign_keys": {},
18351860
"model": "sentry.MonitorLocation",

fixtures/backup/model_dependencies/flat.json

+5
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,11 @@
412412
"sentry.Environment",
413413
"sentry.Monitor"
414414
],
415+
"sentry.MonitorIncident": [
416+
"sentry.Monitor",
417+
"sentry.MonitorCheckIn",
418+
"sentry.MonitorEnvironment"
419+
],
415420
"sentry.MonitorLocation": [],
416421
"sentry.NeglectedRule": [
417422
"sentry.Organization",

fixtures/backup/model_dependencies/sorted.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -212,5 +212,6 @@
212212
"sentry.IncidentSnapshot",
213213
"sentry.IncidentActivity",
214214
"sentry.IncidentSubscription",
215-
"sentry.IncidentTrigger"
215+
"sentry.IncidentTrigger",
216+
"sentry.MonitorIncident"
216217
]

migrations_lockfile.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ will then be regenerated, and you should be able to merge without conflicts.
88
feedback: 0002_feedback_add_org_id_and_rename_event_id
99
nodestore: 0002_nodestore_no_dictfield
1010
replays: 0003_add_size_to_recording_segment
11-
sentry: 0559_custom_dynamic_sampling_rule
11+
sentry: 0560_add_monitorincident_table
1212
social_auth: 0002_default_auto_field
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Generated by Django 3.2.20 on 2023-09-18 23:09
2+
3+
import django.db.models.deletion
4+
import django.utils.timezone
5+
from django.db import migrations, models
6+
7+
import sentry.db.models.fields.bounded
8+
import sentry.db.models.fields.foreignkey
9+
from sentry.new_migrations.migrations import CheckedMigration
10+
11+
12+
class Migration(CheckedMigration):
13+
# This flag is used to mark that a migration shouldn't be automatically run in production. For
14+
# the most part, this should only be used for operations where it's safe to run the migration
15+
# after your code has deployed. So this should not be used for most operations that alter the
16+
# schema of a table.
17+
# Here are some things that make sense to mark as dangerous:
18+
# - Large data migrations. Typically we want these to be run manually by ops so that they can
19+
# be monitored and not block the deploy for a long period of time while they run.
20+
# - Adding indexes to large tables. Since this can take a long time, we'd generally prefer to
21+
# have ops run this and not block the deploy. Note that while adding an index is a schema
22+
# change, it's completely safe to run the operation after the code has deployed.
23+
is_dangerous = False
24+
25+
dependencies = [
26+
("sentry", "0559_custom_dynamic_sampling_rule"),
27+
]
28+
29+
operations = [
30+
migrations.CreateModel(
31+
name="MonitorIncident",
32+
fields=[
33+
(
34+
"id",
35+
sentry.db.models.fields.bounded.BoundedBigAutoField(
36+
primary_key=True, serialize=False
37+
),
38+
),
39+
("starting_timestamp", models.DateTimeField(null=True)),
40+
("resolving_timestamp", models.DateTimeField(null=True)),
41+
("grouphash", models.CharField(max_length=32)),
42+
("date_added", models.DateTimeField(default=django.utils.timezone.now)),
43+
(
44+
"monitor",
45+
sentry.db.models.fields.foreignkey.FlexibleForeignKey(
46+
on_delete=django.db.models.deletion.CASCADE, to="sentry.monitor"
47+
),
48+
),
49+
(
50+
"monitor_environment",
51+
sentry.db.models.fields.foreignkey.FlexibleForeignKey(
52+
on_delete=django.db.models.deletion.CASCADE, to="sentry.monitorenvironment"
53+
),
54+
),
55+
(
56+
"resolving_checkin",
57+
sentry.db.models.fields.foreignkey.FlexibleForeignKey(
58+
null=True,
59+
on_delete=django.db.models.deletion.CASCADE,
60+
related_name="resolved_incidents",
61+
to="sentry.monitorcheckin",
62+
),
63+
),
64+
(
65+
"starting_checkin",
66+
sentry.db.models.fields.foreignkey.FlexibleForeignKey(
67+
null=True,
68+
on_delete=django.db.models.deletion.CASCADE,
69+
related_name="created_incidents",
70+
to="sentry.monitorcheckin",
71+
),
72+
),
73+
],
74+
options={
75+
"db_table": "sentry_monitorincident",
76+
},
77+
),
78+
]

src/sentry/monitors/models.py

+22
Original file line numberDiff line numberDiff line change
@@ -591,3 +591,25 @@ def check_monitor_environment_limits(sender, instance, **kwargs):
591591
raise MonitorEnvironmentLimitsExceeded(
592592
f"You may not exceed {settings.MAX_ENVIRONMENTS_PER_MONITOR} environments per monitor"
593593
)
594+
595+
596+
@region_silo_only_model
597+
class MonitorIncident(Model):
598+
__relocation_scope__ = RelocationScope.Excluded
599+
600+
monitor = FlexibleForeignKey("sentry.Monitor")
601+
monitor_environment = FlexibleForeignKey("sentry.MonitorEnvironment")
602+
starting_checkin = FlexibleForeignKey(
603+
"sentry.MonitorCheckIn", null=True, related_name="created_incidents"
604+
)
605+
starting_timestamp = models.DateTimeField(null=True)
606+
resolving_checkin = FlexibleForeignKey(
607+
"sentry.MonitorCheckIn", null=True, related_name="resolved_incidents"
608+
)
609+
resolving_timestamp = models.DateTimeField(null=True)
610+
grouphash = models.CharField(max_length=32)
611+
date_added = models.DateTimeField(default=timezone.now)
612+
613+
class Meta:
614+
app_label = "sentry"
615+
db_table = "sentry_monitorincident"

0 commit comments

Comments
 (0)