1
+ import logging
2
+
1
3
from django .db import models
2
4
from django .db .models import Q
3
5
8
10
FlexibleForeignKey ,
9
11
region_silo_model ,
10
12
)
13
+ from sentry .incidents .models .alert_rule import AlertRule
14
+ from sentry .incidents .models .incident import Incident
15
+ from sentry .models .groupopenperiod import GroupOpenPeriod
16
+ from sentry .workflow_engine .models .alertrule_detector import AlertRuleDetector
17
+
18
+ logger = logging .getLogger (__name__ )
11
19
12
20
13
21
@region_silo_model
@@ -32,3 +40,157 @@ class Meta:
32
40
name = "inc_id_inc_identifier_together" ,
33
41
)
34
42
]
43
+
44
+ @classmethod
45
+ def create_from_occurrence (self , occurrence , group , open_period ):
46
+ """
47
+ Creates an IncidentGroupOpenPeriod relationship from an issue occurrence.
48
+ This method handles the case where the incident might not exist yet.
49
+
50
+ Args:
51
+ occurrence: The IssueOccurrence that triggered the group creation
52
+ group: The Group that was created
53
+ open_period: The GroupOpenPeriod for the group
54
+ """
55
+ try :
56
+ # Extract alert_id from evidence_data using the detector_id
57
+ detector_id = occurrence .evidence_data .get ("detector_id" )
58
+ if detector_id :
59
+ alert_id = AlertRuleDetector .objects .get (detector_id = detector_id ).alert_rule_id
60
+ else :
61
+ raise Exception ("No detector_id found in evidence_data for metric issue" )
62
+
63
+ # Try to find the active incident for this alert rule and project
64
+ try :
65
+ alert_rule = AlertRule .objects .get (id = alert_id )
66
+ incident = Incident .objects .get_active_incident (
67
+ alert_rule = alert_rule ,
68
+ project = group .project ,
69
+ )
70
+ except AlertRule .DoesNotExist :
71
+ logger .warning (
72
+ "AlertRule not found for alert_id" ,
73
+ extra = {
74
+ "alert_id" : alert_id ,
75
+ "group_id" : group .id ,
76
+ },
77
+ )
78
+ incident = None
79
+
80
+ if incident :
81
+ # Incident exists, create the relationship immediately
82
+ return self .create_relationship (incident , open_period )
83
+ else :
84
+ # Incident doesn't exist yet, create a placeholder relationship
85
+ # that will be updated when the incident is created
86
+ return self .create_placeholder_relationship (detector_id , open_period , group .project )
87
+
88
+ except Exception as e :
89
+ logger .exception (
90
+ "Failed to create IncidentGroupOpenPeriod relationship" ,
91
+ extra = {
92
+ "group_id" : group .id ,
93
+ "occurrence_id" : occurrence .id ,
94
+ "error" : str (e ),
95
+ },
96
+ )
97
+ return None
98
+
99
+ @classmethod
100
+ def create_relationship (self , incident , open_period ):
101
+ """
102
+ Creates IncidentGroupOpenPeriod relationship.
103
+
104
+ Args:
105
+ incident: The Incident to link
106
+ open_period: The GroupOpenPeriod to link
107
+ """
108
+ try :
109
+ incident_group_open_period , _ = self .objects .get_or_create (
110
+ group_open_period = open_period ,
111
+ defaults = {
112
+ "incident_id" : incident .id ,
113
+ "incident_identifier" : incident .identifier ,
114
+ },
115
+ )
116
+
117
+ return incident_group_open_period
118
+
119
+ except Exception as e :
120
+ logger .exception (
121
+ "Failed to create/update IncidentGroupOpenPeriod relationship" ,
122
+ extra = {
123
+ "incident_id" : incident .id ,
124
+ "open_period_id" : open_period .id ,
125
+ "error" : str (e ),
126
+ },
127
+ )
128
+ return None
129
+
130
+ @classmethod
131
+ def create_placeholder_relationship (self , detector_id , open_period , project ):
132
+ """
133
+ Creates a placeholder relationship when the incident doesn't exist yet.
134
+ This will be updated when the incident is created.
135
+
136
+ Args:
137
+ detector_id: The detector ID
138
+ open_period: The GroupOpenPeriod to link
139
+ project: The project for the group
140
+ """
141
+ try :
142
+ # Store the alert_id in the open_period data for later lookup
143
+ data = open_period .data or {}
144
+ data ["pending_incident_detector_id" ] = detector_id
145
+ open_period .update (data = data )
146
+
147
+ return None
148
+
149
+ except Exception as e :
150
+ logger .exception (
151
+ "Failed to create placeholder IncidentGroupOpenPeriod relationship" ,
152
+ extra = {
153
+ "detector_id" : detector_id ,
154
+ "open_period_id" : open_period .id ,
155
+ "error" : str (e ),
156
+ },
157
+ )
158
+ return None
159
+
160
+ @classmethod
161
+ def create_pending_relationships_for_incident (self , incident , alert_rule ):
162
+ """
163
+ Creates IncidentGroupOpenPeriod relationships for any groups that were created
164
+ before the incident. This handles the timing issue where groups might be created
165
+ before incidents.
166
+
167
+ Args:
168
+ incident: The Incident that was just created
169
+ alert_rule: The AlertRule that triggered the incident
170
+ """
171
+ try :
172
+ # Find all open periods that have a pending incident detector_id for this alert rule
173
+ detector_id = AlertRuleDetector .objects .get (alert_rule_id = alert_rule .id ).detector_id
174
+ pending_open_periods = GroupOpenPeriod .objects .filter (
175
+ data__pending_incident_detector_id = detector_id ,
176
+ group__project__in = list (incident .projects .all ()),
177
+ )
178
+
179
+ for open_period in pending_open_periods :
180
+ # Create the relationship
181
+ relationship = self .create_relationship (incident , open_period )
182
+ if relationship :
183
+ # Remove the pending flag from the open_period data
184
+ data = open_period .data or {}
185
+ data .pop ("pending_incident_detector_id" , None )
186
+ open_period .update (data = data )
187
+
188
+ except Exception as e :
189
+ logger .exception (
190
+ "Failed to create pending IncidentGroupOpenPeriod relationships" ,
191
+ extra = {
192
+ "incident_id" : incident .id ,
193
+ "alert_rule_id" : alert_rule .id ,
194
+ "error" : str (e ),
195
+ },
196
+ )
0 commit comments