Skip to content

Commit 4f837bf

Browse files
authored
Merge pull request #5120 from grafana/dev
v1.10.1
2 parents 44e7d99 + 4d9846e commit 4f837bf

24 files changed

+18
-1138
lines changed

engine/apps/alerts/escalation_snapshot/snapshot_classes/escalation_policy_snapshot.py

-29
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,11 @@
1212
from apps.alerts.models.escalation_policy import EscalationPolicy
1313
from apps.alerts.tasks import (
1414
custom_webhook_result,
15-
declare_incident,
1615
notify_all_task,
1716
notify_group_task,
1817
notify_user_task,
1918
resolve_by_last_step_task,
2019
)
21-
from apps.alerts.utils import is_declare_incident_step_enabled
2220
from apps.schedules.ical_utils import list_users_to_notify_from_ical
2321
from apps.user_management.models import User
2422

@@ -138,7 +136,6 @@ def execute(self, alert_group: "AlertGroup", reason) -> StepExecutionResultData:
138136
EscalationPolicy.STEP_NOTIFY_IF_NUM_ALERTS_IN_TIME_WINDOW: self._escalation_step_notify_if_num_alerts_in_time_window,
139137
EscalationPolicy.STEP_NOTIFY_MULTIPLE_USERS: self._escalation_step_notify_multiple_users,
140138
EscalationPolicy.STEP_NOTIFY_MULTIPLE_USERS_IMPORTANT: self._escalation_step_notify_multiple_users,
141-
EscalationPolicy.STEP_DECLARE_INCIDENT: self._escalation_step_declare_incident,
142139
None: self._escalation_step_not_configured,
143140
}
144141
result = action_map[self.step](alert_group, reason)
@@ -413,32 +410,6 @@ def _escalation_step_notify_team_members(self, alert_group: "AlertGroup", reason
413410

414411
self._execute_tasks(tasks)
415412

416-
def _escalation_step_declare_incident(self, alert_group: "AlertGroup", _reason: str) -> None:
417-
grafana_declare_incident_enabled = is_declare_incident_step_enabled(
418-
organization=alert_group.channel.organization
419-
)
420-
if not grafana_declare_incident_enabled:
421-
AlertGroupLogRecord(
422-
type=AlertGroupLogRecord.TYPE_ESCALATION_FAILED,
423-
alert_group=alert_group,
424-
reason="Declare Incident step is not enabled",
425-
escalation_policy=self.escalation_policy,
426-
escalation_error_code=AlertGroupLogRecord.ERROR_ESCALATION_DECLARE_INCIDENT_STEP_IS_NOT_ENABLED,
427-
escalation_policy_step=self.step,
428-
).save()
429-
return
430-
tasks = []
431-
declare_incident_task = declare_incident.signature(
432-
args=(alert_group.pk,),
433-
kwargs={
434-
"escalation_policy_pk": self.id,
435-
"severity": self.severity,
436-
},
437-
immutable=True,
438-
)
439-
tasks.append(declare_incident_task)
440-
self._execute_tasks(tasks)
441-
442413
def _escalation_step_notify_if_time(self, alert_group: "AlertGroup", _reason: str) -> StepExecutionResultData:
443414
eta = None
444415

engine/apps/alerts/migrations/0059_escalationpolicy_severity_and_more.py

-16
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,4 @@ class Migration(migrations.Migration):
2222
name='step',
2323
field=models.IntegerField(choices=[(0, 'Wait'), (1, 'Notify User'), (2, 'Notify Whole Channel'), (3, 'Repeat Escalation (5 times max)'), (4, 'Resolve'), (5, 'Notify Group'), (6, 'Notify Schedule'), (7, 'Notify User (Important)'), (8, 'Notify Group (Important)'), (9, 'Notify Schedule (Important)'), (10, 'Trigger Outgoing Webhook'), (11, 'Notify User (next each time)'), (12, 'Continue escalation only if time is from'), (13, 'Notify multiple Users'), (14, 'Notify multiple Users (Important)'), (15, 'Continue escalation if >X alerts per Y minutes'), (16, 'Trigger Webhook'), (17, 'Notify all users in a Team'), (18, 'Notify all users in a Team (Important)'), (19, 'Declare Incident')], default=None, null=True),
2424
),
25-
migrations.CreateModel(
26-
name='DeclaredIncident',
27-
fields=[
28-
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
29-
('incident_id', models.CharField(db_index=True, max_length=50)),
30-
('created_at', models.DateTimeField(auto_now_add=True)),
31-
('is_active', models.BooleanField(default=True)),
32-
('channel_filter', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='declared_incidents', to='alerts.channelfilter')),
33-
('organization', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='declared_incidents', to='user_management.organization')),
34-
],
35-
),
36-
migrations.AddField(
37-
model_name='alertgroup',
38-
name='declared_incident',
39-
field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='attached_alert_groups', to='alerts.declaredincident'),
40-
),
4125
]

engine/apps/alerts/models/__init__.py

-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
from .alert_receive_channel_connection import AlertReceiveChannelConnection # noqa: F401
99
from .channel_filter import ChannelFilter # noqa: F401
1010
from .custom_button import CustomButton # noqa: F401
11-
from .declared_incident import DeclaredIncident # noqa: F401
1211
from .escalation_chain import EscalationChain # noqa: F401
1312
from .escalation_policy import EscalationPolicy # noqa: F401
1413
from .grafana_alerting_contact_point import GrafanaAlertingContactPoint # noqa: F401

engine/apps/alerts/models/alert_group.py

-11
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@
4444
AlertGroupLogRecord,
4545
AlertReceiveChannel,
4646
BundledNotification,
47-
DeclaredIncident,
4847
ResolutionNote,
4948
ResolutionNoteSlackMessage,
5049
)
@@ -207,7 +206,6 @@ class AlertGroup(AlertGroupSlackRenderingMixin, EscalationSnapshotMixin, models.
207206
slack_messages: "RelatedManager['SlackMessage']"
208207
users: "RelatedManager['User']"
209208
labels: "RelatedManager['AlertGroupAssociatedLabel']"
210-
declared_incident: typing.Optional["DeclaredIncident"]
211209

212210
objects: models.Manager["AlertGroup"] = AlertGroupQuerySet.as_manager()
213211

@@ -423,17 +421,8 @@ def status(self) -> int:
423421
# https://code.djangoproject.com/ticket/28545
424422
is_open_for_grouping = models.BooleanField(default=None, null=True, blank=True)
425423

426-
# todo: rework using this field to use DeclaredIncident model field instead
427424
grafana_incident_id = models.CharField(max_length=100, null=True, default=None)
428425

429-
declared_incident = models.ForeignKey(
430-
"alerts.DeclaredIncident",
431-
on_delete=models.SET_NULL,
432-
null=True,
433-
default=None,
434-
related_name="attached_alert_groups",
435-
)
436-
437426
@staticmethod
438427
def get_silenced_state_filter():
439428
"""

engine/apps/alerts/models/alert_group_log_record.py

+9-104
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,18 @@
1111

1212
from apps.alerts import tasks
1313
from apps.alerts.constants import ActionSource
14-
from apps.alerts.incident_appearance.renderers.constants import DEFAULT_BACKUP_TITLE
1514
from apps.alerts.utils import render_relative_timeline
1615
from apps.slack.slack_formatter import SlackFormatter
1716
from common.utils import clean_markup
1817

1918
if typing.TYPE_CHECKING:
2019
from apps.alerts.models import AlertGroup, CustomButton, EscalationPolicy, Invitation
21-
from apps.user_management.models import Organization, User
20+
from apps.user_management.models import User
2221

2322
logger = logging.getLogger(__name__)
2423
logger.setLevel(logging.DEBUG)
2524

2625

27-
class RelatedIncidentData(typing.TypedDict):
28-
incident_link: typing.Optional[str]
29-
incident_title: str
30-
31-
3226
class AlertGroupLogRecord(models.Model):
3327
alert_group: "AlertGroup"
3428
author: typing.Optional["User"]
@@ -167,9 +161,7 @@ class AlertGroupLogRecord(models.Model):
167161
ERROR_ESCALATION_TRIGGER_CUSTOM_WEBHOOK_ERROR,
168162
ERROR_ESCALATION_NOTIFY_TEAM_MEMBERS_STEP_IS_NOT_CONFIGURED,
169163
ERROR_ESCALATION_TRIGGER_WEBHOOK_IS_DISABLED,
170-
ERROR_ESCALATION_DECLARE_INCIDENT_STEP_IS_NOT_ENABLED,
171-
ERROR_ESCALATION_INCIDENT_COULD_NOT_BE_DECLARED,
172-
) = range(22)
164+
) = range(20)
173165

174166
type = models.IntegerField(choices=TYPE_CHOICES)
175167

@@ -233,60 +225,16 @@ class AlertGroupLogRecord(models.Model):
233225
escalation_policy_step = models.IntegerField(null=True, default=None)
234226
step_specific_info = JSONField(null=True, default=None)
235227

236-
STEP_SPECIFIC_INFO_KEYS = [
237-
"schedule_name",
238-
"custom_button_name",
239-
"usergroup_handle",
240-
"source_integration_name",
241-
"incident_link",
242-
"incident_title",
243-
]
244-
245-
def _make_log_line_link(self, url, title, html=False, for_slack=False, substitute_with_tag=False):
246-
if html and url:
247-
return f"<a href='{url}'>{title}</a>"
248-
elif for_slack and url:
249-
return f"<{url}|{title}>"
250-
elif substitute_with_tag:
251-
return f"{{{{{substitute_with_tag}}}}}"
252-
else:
253-
return title
228+
STEP_SPECIFIC_INFO_KEYS = ["schedule_name", "custom_button_name", "usergroup_handle", "source_integration_name"]
254229

255230
def render_log_line_json(self):
256231
time = humanize.naturaldelta(self.alert_group.started_at - self.created_at)
257232
created_at = DateTimeField().to_representation(self.created_at)
258233
organization = self.alert_group.channel.organization
259234
author = self.author.short(organization) if self.author is not None else None
260-
escalation_chain = self.alert_group.channel_filter.escalation_chain if self.alert_group.channel_filter else None
261-
step_info = self.get_step_specific_info()
262-
related_incident = self.render_incident_data_from_step_info(organization, step_info)
263-
escalation_chain_data = (
264-
{
265-
"pk": escalation_chain.public_primary_key,
266-
"title": escalation_chain.name,
267-
}
268-
if escalation_chain
269-
else None
270-
)
271-
schedule = (
272-
{
273-
"pk": self.escalation_policy.notify_schedule.public_primary_key,
274-
"title": self.escalation_policy.notify_schedule.name,
275-
}
276-
if self.escalation_policy and self.escalation_policy.notify_schedule
277-
else None
278-
)
279-
webhook = (
280-
{
281-
"pk": step_info["webhook_id"],
282-
"title": step_info.get("webhook_name", "webhook"),
283-
}
284-
if step_info and "webhook_id" in step_info
285-
else None
286-
)
287235

288236
sf = SlackFormatter(organization)
289-
action = sf.format(self.rendered_log_line_action(substitute_with_tag=True))
237+
action = sf.format(self.rendered_log_line_action(substitute_author_with_tag=True))
290238
action = clean_markup(action)
291239

292240
result = {
@@ -296,10 +244,6 @@ def render_log_line_json(self):
296244
"type": self.type,
297245
"created_at": created_at,
298246
"author": author,
299-
"incident": related_incident,
300-
"escalation_chain": escalation_chain_data,
301-
"schedule": schedule,
302-
"webhook": webhook,
303247
}
304248
return result
305249

@@ -314,7 +258,7 @@ def rendered_incident_log_line(self, for_slack=False, html=False):
314258
result += self.rendered_log_line_action(for_slack=for_slack, html=html)
315259
return result
316260

317-
def rendered_log_line_action(self, for_slack=False, html=False, substitute_with_tag=False):
261+
def rendered_log_line_action(self, for_slack=False, html=False, substitute_author_with_tag=False):
318262
from apps.alerts.models import EscalationPolicy
319263

320264
result = ""
@@ -332,7 +276,7 @@ def rendered_log_line_action(self, for_slack=False, html=False, substitute_with_
332276
elif self.action_source == ActionSource.BACKSYNC:
333277
author_name = "source integration " + step_specific_info.get("source_integration_name", "")
334278
elif self.author:
335-
if substitute_with_tag:
279+
if substitute_author_with_tag:
336280
author_name = "{{author}}"
337281
elif for_slack:
338282
author_name = self.author.get_username_with_slack_verbal()
@@ -359,9 +303,7 @@ def rendered_log_line_action(self, for_slack=False, html=False, substitute_with_
359303
result += f'alert group assigned to route "{channel_filter.str_for_clients}"'
360304

361305
if escalation_chain is not None:
362-
tag = "escalation_chain" if substitute_with_tag else False
363-
escalation_chain_text = self._make_log_line_link(None, escalation_chain.name, html, for_slack, tag)
364-
result += f' with escalation chain "{escalation_chain_text}"'
306+
result += f' with escalation chain "{escalation_chain.name}"'
365307
else:
366308
result += " with no escalation chain, skipping escalation"
367309
else:
@@ -437,19 +379,9 @@ def rendered_log_line_action(self, for_slack=False, html=False, substitute_with_
437379
important_text = ""
438380
if escalation_policy_step == EscalationPolicy.STEP_NOTIFY_SCHEDULE_IMPORTANT:
439381
important_text = " (Important)"
440-
tag = "schedule" if substitute_with_tag else False
441-
schedule_text = self._make_log_line_link(None, schedule_name, html, for_slack, tag)
442-
result += f'triggered step "Notify on-call from Schedule {schedule_text}{important_text}"'
382+
result += f'triggered step "Notify on-call from Schedule {schedule_name}{important_text}"'
443383
elif escalation_policy_step == EscalationPolicy.STEP_REPEAT_ESCALATION_N_TIMES:
444384
result += "escalation started from the beginning"
445-
elif escalation_policy_step == EscalationPolicy.STEP_DECLARE_INCIDENT:
446-
organization = self.alert_group.channel.organization
447-
incident_data = self.render_incident_data_from_step_info(organization, step_specific_info)
448-
incident_link = incident_data["incident_link"]
449-
incident_title = incident_data["incident_title"]
450-
tag = "related_incident" if substitute_with_tag else False
451-
incident_text = self._make_log_line_link(incident_link, incident_title, html, for_slack, tag)
452-
result += self.reason + f": {incident_text}"
453385
else:
454386
result += f'triggered step "{EscalationPolicy.get_step_display_name(escalation_policy_step)}"'
455387
elif self.type == AlertGroupLogRecord.TYPE_SILENCE:
@@ -553,10 +485,7 @@ def rendered_log_line_action(self, for_slack=False, html=False, substitute_with_
553485
trigger = f"{author_name}"
554486
else:
555487
trigger = trigger or "escalation chain"
556-
tag = "webhook" if substitute_with_tag else False
557-
webhook_text = self._make_log_line_link(None, webhook_name, html, for_slack, tag)
558-
result += f"outgoing webhook `{webhook_text}` triggered by {trigger}"
559-
488+
result += f"outgoing webhook `{webhook_name}` triggered by {trigger}"
560489
elif self.type == AlertGroupLogRecord.TYPE_FAILED_ATTACHMENT:
561490
if self.alert_group.slack_message is not None:
562491
result += (
@@ -665,32 +594,8 @@ def rendered_log_line_action(self, for_slack=False, html=False, substitute_with_
665594
result += f"failed to notify User Group{usergroup_handle_text} in Slack"
666595
elif self.escalation_error_code == AlertGroupLogRecord.ERROR_ESCALATION_TRIGGER_WEBHOOK_IS_DISABLED:
667596
result += 'skipped escalation step "Trigger Outgoing Webhook" because it is disabled'
668-
elif (
669-
self.escalation_error_code == AlertGroupLogRecord.ERROR_ESCALATION_DECLARE_INCIDENT_STEP_IS_NOT_ENABLED
670-
):
671-
result += 'skipped escalation step "Declare Incident": step is not enabled'
672-
elif self.escalation_error_code == AlertGroupLogRecord.ERROR_ESCALATION_INCIDENT_COULD_NOT_BE_DECLARED:
673-
result += "failed to declare an Incident"
674-
if self.reason:
675-
result += f": {self.reason}"
676597
return result
677598

678-
def render_incident_data_from_step_info(
679-
self, organization: "Organization", step_specific_info: dict
680-
) -> RelatedIncidentData | None:
681-
from apps.alerts.models.declared_incident import get_incident_url
682-
683-
if not step_specific_info or not all(key in step_specific_info for key in ["incident_title", "incident_id"]):
684-
return None
685-
686-
incident_link = (
687-
get_incident_url(organization, step_specific_info["incident_id"])
688-
if step_specific_info["incident_id"]
689-
else None
690-
)
691-
incident_title = step_specific_info["incident_title"] or DEFAULT_BACKUP_TITLE
692-
return {"incident_link": incident_link, "incident_title": incident_title}
693-
694599
def get_step_specific_info(self):
695600
step_specific_info = None
696601
# in some cases step_specific_info was saved with using json.dumps

engine/apps/alerts/models/declared_incident.py

-38
This file was deleted.

engine/apps/alerts/models/escalation_policy.py

-3
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ class EscalationPolicy(OrderedModel):
9292
STEP_NOTIFY_IF_TIME,
9393
STEP_NOTIFY_IF_NUM_ALERTS_IN_TIME_WINDOW,
9494
STEP_REPEAT_ESCALATION_N_TIMES,
95-
STEP_DECLARE_INCIDENT,
9695
]
9796
# Steps can be stored in db while interacting with internal api
9897
# Includes important versions of default steps
@@ -219,7 +218,6 @@ class EscalationPolicy(OrderedModel):
219218
STEP_NOTIFY_IF_TIME,
220219
STEP_NOTIFY_IF_NUM_ALERTS_IN_TIME_WINDOW,
221220
STEP_REPEAT_ESCALATION_N_TIMES,
222-
STEP_DECLARE_INCIDENT,
223221
]
224222

225223
PUBLIC_STEP_CHOICES_MAP = {
@@ -241,7 +239,6 @@ class EscalationPolicy(OrderedModel):
241239
STEP_NOTIFY_IF_TIME: "notify_if_time_from_to",
242240
STEP_NOTIFY_IF_NUM_ALERTS_IN_TIME_WINDOW: "notify_if_num_alerts_in_window",
243241
STEP_REPEAT_ESCALATION_N_TIMES: "repeat_escalation",
244-
STEP_DECLARE_INCIDENT: "declare_incident",
245242
}
246243

247244
public_primary_key = models.CharField(

engine/apps/alerts/tasks/__init__.py

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
)
66
from .check_escalation_finished import check_escalation_finished_task # noqa: F401
77
from .custom_webhook_result import custom_webhook_result # noqa: F401
8-
from .declare_incident import declare_incident # noqa: F401
98
from .delete_alert_group import delete_alert_group # noqa: F401
109
from .delete_alert_group import finish_delete_alert_group # noqa: F401
1110
from .delete_alert_group import send_alert_group_signal_for_delete # noqa: F401

0 commit comments

Comments
 (0)