|
9 | 9 | from django.db.models import Count, Max, OuterRef, Subquery |
10 | 10 | from django.db.models.functions import TruncHour |
11 | 11 |
|
12 | | -from sentry import features |
13 | 12 | from sentry.api.paginator import GenericOffsetPaginator, OffsetPaginator |
14 | 13 | from sentry.models.group import Group |
15 | 14 | from sentry.models.rulefirehistory import RuleFireHistory |
@@ -69,60 +68,57 @@ def fetch_rule_groups_paginated( |
69 | 68 | cursor: Cursor | None = None, |
70 | 69 | per_page: int = 25, |
71 | 70 | ) -> CursorResult[RuleGroupHistory]: |
72 | | - if features.has( |
73 | | - "organizations:workflow-engine-single-process-workflows", rule.project.organization |
74 | | - ): |
75 | | - try: |
76 | | - alert_rule_workflow = AlertRuleWorkflow.objects.get(rule_id=rule.id) |
77 | | - workflow = alert_rule_workflow.workflow |
78 | | - |
79 | | - # Performs the raw SQL query with pagination |
80 | | - def data_fn(offset: int, limit: int) -> list[_Result]: |
81 | | - query = """ |
82 | | - WITH combined_data AS ( |
83 | | - SELECT group_id, date_added, event_id |
84 | | - FROM sentry_rulefirehistory |
85 | | - WHERE rule_id = %s AND date_added >= %s AND date_added < %s |
86 | | - UNION ALL |
87 | | - SELECT group_id, date_added, event_id |
88 | | - FROM workflow_engine_workflowfirehistory |
89 | | - WHERE workflow_id = %s |
90 | | - AND date_added >= %s AND date_added < %s |
| 71 | + try: |
| 72 | + alert_rule_workflow = AlertRuleWorkflow.objects.get(rule_id=rule.id) |
| 73 | + workflow = alert_rule_workflow.workflow |
| 74 | + |
| 75 | + # Performs the raw SQL query with pagination |
| 76 | + def data_fn(offset: int, limit: int) -> list[_Result]: |
| 77 | + query = """ |
| 78 | + WITH combined_data AS ( |
| 79 | + SELECT group_id, date_added, event_id |
| 80 | + FROM sentry_rulefirehistory |
| 81 | + WHERE rule_id = %s AND date_added >= %s AND date_added < %s |
| 82 | + UNION ALL |
| 83 | + SELECT group_id, date_added, event_id |
| 84 | + FROM workflow_engine_workflowfirehistory |
| 85 | + WHERE workflow_id = %s |
| 86 | + AND date_added >= %s AND date_added < %s |
| 87 | + ) |
| 88 | + SELECT |
| 89 | + group_id as group, |
| 90 | + COUNT(*) as count, |
| 91 | + MAX(date_added) as last_triggered, |
| 92 | + (ARRAY_AGG(event_id ORDER BY date_added DESC))[1] as event_id |
| 93 | + FROM combined_data |
| 94 | + GROUP BY group_id |
| 95 | + ORDER BY count DESC, last_triggered DESC |
| 96 | + LIMIT %s OFFSET %s |
| 97 | + """ |
| 98 | + |
| 99 | + with connection.cursor() as cursor: |
| 100 | + cursor.execute( |
| 101 | + query, [rule.id, start, end, workflow.id, start, end, limit, offset] |
| 102 | + ) |
| 103 | + return [ |
| 104 | + _Result( |
| 105 | + group=row[0], |
| 106 | + count=row[1], |
| 107 | + last_triggered=row[2], |
| 108 | + event_id=row[3], |
91 | 109 | ) |
92 | | - SELECT |
93 | | - group_id as group, |
94 | | - COUNT(*) as count, |
95 | | - MAX(date_added) as last_triggered, |
96 | | - (ARRAY_AGG(event_id ORDER BY date_added DESC))[1] as event_id |
97 | | - FROM combined_data |
98 | | - GROUP BY group_id |
99 | | - ORDER BY count DESC, last_triggered DESC |
100 | | - LIMIT %s OFFSET %s |
101 | | - """ |
| 110 | + for row in cursor.fetchall() |
| 111 | + ] |
102 | 112 |
|
103 | | - with connection.cursor() as cursor: |
104 | | - cursor.execute( |
105 | | - query, [rule.id, start, end, workflow.id, start, end, limit, offset] |
106 | | - ) |
107 | | - return [ |
108 | | - _Result( |
109 | | - group=row[0], |
110 | | - count=row[1], |
111 | | - last_triggered=row[2], |
112 | | - event_id=row[3], |
113 | | - ) |
114 | | - for row in cursor.fetchall() |
115 | | - ] |
116 | | - |
117 | | - result = GenericOffsetPaginator(data_fn=data_fn).get_result(per_page, cursor) |
118 | | - result.results = convert_results(result.results) |
119 | | - |
120 | | - return result |
121 | | - |
122 | | - except AlertRuleWorkflow.DoesNotExist: |
123 | | - # If no workflow is associated with this rule, just use the original behavior |
124 | | - logger.exception("No workflow associated with rule", extra={"rule_id": rule.id}) |
125 | | - pass |
| 113 | + result = GenericOffsetPaginator(data_fn=data_fn).get_result(per_page, cursor) |
| 114 | + result.results = convert_results(result.results) |
| 115 | + |
| 116 | + return result |
| 117 | + |
| 118 | + except AlertRuleWorkflow.DoesNotExist: |
| 119 | + # If no workflow is associated with this rule, just use the original behavior |
| 120 | + logger.exception("No workflow associated with rule", extra={"rule_id": rule.id}) |
| 121 | + pass |
126 | 122 |
|
127 | 123 | rule_filtered_history = RuleFireHistory.objects.filter( |
128 | 124 | rule=rule, |
@@ -154,50 +150,47 @@ def fetch_rule_hourly_stats( |
154 | 150 |
|
155 | 151 | existing_data: dict[datetime, TimeSeriesValue] = {} |
156 | 152 |
|
157 | | - if features.has( |
158 | | - "organizations:workflow-engine-single-process-workflows", rule.project.organization |
159 | | - ): |
160 | | - try: |
161 | | - alert_rule_workflow = AlertRuleWorkflow.objects.get(rule_id=rule.id) |
162 | | - workflow = alert_rule_workflow.workflow |
163 | | - |
164 | | - # Use raw SQL to combine data from both tables |
165 | | - with connection.cursor() as db_cursor: |
166 | | - db_cursor.execute( |
167 | | - """ |
168 | | - SELECT |
169 | | - DATE_TRUNC('hour', date_added) as bucket, |
170 | | - COUNT(*) as count |
171 | | - FROM ( |
172 | | - SELECT date_added |
173 | | - FROM sentry_rulefirehistory |
174 | | - WHERE rule_id = %s |
175 | | - AND date_added >= %s |
176 | | - AND date_added < %s |
177 | | -
|
178 | | - UNION ALL |
179 | | -
|
180 | | - SELECT date_added |
181 | | - FROM workflow_engine_workflowfirehistory |
182 | | - WHERE workflow_id = %s |
183 | | - AND date_added >= %s |
184 | | - AND date_added < %s |
185 | | - ) combined_data |
186 | | - GROUP BY DATE_TRUNC('hour', date_added) |
187 | | - ORDER BY bucket |
188 | | - """, |
189 | | - [rule.id, start, end, workflow.id, start, end], |
190 | | - ) |
| 153 | + try: |
| 154 | + alert_rule_workflow = AlertRuleWorkflow.objects.get(rule_id=rule.id) |
| 155 | + workflow = alert_rule_workflow.workflow |
| 156 | + |
| 157 | + # Use raw SQL to combine data from both tables |
| 158 | + with connection.cursor() as db_cursor: |
| 159 | + db_cursor.execute( |
| 160 | + """ |
| 161 | + SELECT |
| 162 | + DATE_TRUNC('hour', date_added) as bucket, |
| 163 | + COUNT(*) as count |
| 164 | + FROM ( |
| 165 | + SELECT date_added |
| 166 | + FROM sentry_rulefirehistory |
| 167 | + WHERE rule_id = %s |
| 168 | + AND date_added >= %s |
| 169 | + AND date_added < %s |
| 170 | +
|
| 171 | + UNION ALL |
| 172 | +
|
| 173 | + SELECT date_added |
| 174 | + FROM workflow_engine_workflowfirehistory |
| 175 | + WHERE workflow_id = %s |
| 176 | + AND date_added >= %s |
| 177 | + AND date_added < %s |
| 178 | + ) combined_data |
| 179 | + GROUP BY DATE_TRUNC('hour', date_added) |
| 180 | + ORDER BY bucket |
| 181 | + """, |
| 182 | + [rule.id, start, end, workflow.id, start, end], |
| 183 | + ) |
191 | 184 |
|
192 | | - results = db_cursor.fetchall() |
| 185 | + results = db_cursor.fetchall() |
193 | 186 |
|
194 | | - # Convert raw SQL results to the expected format |
195 | | - existing_data = {row[0]: TimeSeriesValue(row[0], row[1]) for row in results} |
| 187 | + # Convert raw SQL results to the expected format |
| 188 | + existing_data = {row[0]: TimeSeriesValue(row[0], row[1]) for row in results} |
196 | 189 |
|
197 | | - except AlertRuleWorkflow.DoesNotExist: |
198 | | - # If no workflow is associated with this rule, just use the original behavior |
199 | | - logger.exception("No workflow associated with rule", extra={"rule_id": rule.id}) |
200 | | - pass |
| 190 | + except AlertRuleWorkflow.DoesNotExist: |
| 191 | + # If no workflow is associated with this rule, just use the original behavior |
| 192 | + logger.exception("No workflow associated with rule", extra={"rule_id": rule.id}) |
| 193 | + pass |
201 | 194 |
|
202 | 195 | if not existing_data: |
203 | 196 | qs = ( |
|
0 commit comments