Skip to content

Commit baa8542

Browse files
authored
Merge pull request #300 from grafana/dev
Merge dev to main
2 parents c358586 + a1b1b83 commit baa8542

34 files changed

+476
-662
lines changed

engine/apps/alerts/incident_appearance/renderers/base_renderer.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,12 @@ def templater_class(self):
1818

1919

2020
class AlertGroupBaseRenderer(ABC):
21-
def __init__(self, alert_group):
21+
def __init__(self, alert_group, alert=None):
22+
if alert is None:
23+
alert = alert_group.alerts.first()
24+
2225
self.alert_group = alert_group
23-
self.alert_renderer = self.alert_renderer_class(self.alert_group.alerts.first())
26+
self.alert_renderer = self.alert_renderer_class(alert)
2427

2528
@property
2629
@abstractmethod

engine/apps/alerts/incident_appearance/renderers/classic_markdown_renderer.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ def render(self):
2020

2121

2222
class AlertGroupClassicMarkdownRenderer(AlertGroupBaseRenderer):
23-
def __init__(self, alert_group):
24-
super().__init__(alert_group)
23+
def __init__(self, alert_group, alert=None):
24+
if alert is None:
25+
alert = alert_group.alerts.last()
2526

26-
# use the last alert to render content
27-
self.alert_renderer = self.alert_renderer_class(self.alert_group.alerts.last())
27+
super().__init__(alert_group, alert)
2828

2929
@property
3030
def alert_renderer_class(self):

engine/apps/alerts/incident_appearance/renderers/web_renderer.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ def render(self):
2020

2121

2222
class AlertGroupWebRenderer(AlertGroupBaseRenderer):
23-
def __init__(self, alert_group):
24-
super().__init__(alert_group)
23+
def __init__(self, alert_group, alert=None):
24+
if alert is None:
25+
alert = alert_group.alerts.last()
2526

26-
# use the last alert to render content
27-
self.alert_renderer = self.alert_renderer_class(self.alert_group.alerts.last())
27+
super().__init__(alert_group, alert)
2828

2929
@property
3030
def alert_renderer_class(self):
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Generated by Django 3.2.13 on 2022-07-27 10:51
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('alerts', '0005_alertgroup_cached_render_for_web'),
10+
]
11+
12+
operations = [
13+
migrations.AddIndex(
14+
model_name='alertgroup',
15+
index=models.Index(fields=['channel_id', 'resolved', 'acknowledged', 'silenced', 'root_alert_group_id', 'is_archived'], name='alerts_aler_channel_ee84a7_idx'),
16+
),
17+
]

engine/apps/alerts/models/alert.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from django.apps import apps
66
from django.conf import settings
77
from django.core.validators import MinLengthValidator
8-
from django.db import models, transaction
8+
from django.db import models
99
from django.db.models import JSONField
1010
from django.db.models.signals import post_save
1111

@@ -261,9 +261,6 @@ def listen_for_alert_model_save(sender, instance, created, *args, **kwargs):
261261
else:
262262
distribute_alert.apply_async((instance.pk,), countdown=TASK_DELAY_SECONDS)
263263

264-
logger.info(f"Recalculate AG cache. Reason: save alert model {instance.pk}")
265-
transaction.on_commit(instance.group.schedule_cache_for_web)
266-
267264

268265
# Connect signal to base Alert class
269266
post_save.connect(listen_for_alert_model_save, Alert)

engine/apps/alerts/models/alert_group.py

Lines changed: 13 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,9 @@
88
from celery import uuid as celery_uuid
99
from django.apps import apps
1010
from django.conf import settings
11-
from django.core.cache import cache
1211
from django.core.validators import MinLengthValidator
13-
from django.db import IntegrityError, models, transaction
12+
from django.db import IntegrityError, models
1413
from django.db.models import JSONField, Q, QuerySet
15-
from django.db.models.signals import post_save
16-
from django.dispatch import receiver
1714
from django.utils import timezone
1815
from django.utils.functional import cached_property
1916

@@ -22,16 +19,9 @@
2219
from apps.alerts.incident_appearance.renderers.slack_renderer import AlertGroupSlackRenderer
2320
from apps.alerts.incident_log_builder import IncidentLogBuilder
2421
from apps.alerts.signals import alert_group_action_triggered_signal
25-
from apps.alerts.tasks import (
26-
acknowledge_reminder_task,
27-
call_ack_url,
28-
schedule_cache_for_alert_group,
29-
send_alert_group_signal,
30-
unsilence_task,
31-
)
22+
from apps.alerts.tasks import acknowledge_reminder_task, call_ack_url, send_alert_group_signal, unsilence_task
3223
from apps.slack.slack_formatter import SlackFormatter
3324
from apps.user_management.models import User
34-
from common.mixins.use_random_readonly_db_manager_mixin import UseRandomReadonlyDbManagerMixin
3525
from common.public_primary_keys import generate_public_primary_key, increase_public_primary_key_length
3626
from common.utils import clean_markup, str_or_backup
3727

@@ -108,10 +98,6 @@ def filter(self, *args, **kwargs):
10898
return super().filter(*args, **kwargs, is_archived=False)
10999

110100

111-
class AlertGroupManager(UseRandomReadonlyDbManagerMixin, models.Manager):
112-
pass
113-
114-
115101
class AlertGroupSlackRenderingMixin:
116102
"""
117103
Ideally this mixin should not exist. Instead of this instance of AlertGroupSlackRenderer should be created and used
@@ -134,8 +120,8 @@ def slack_templated_first_alert(self):
134120

135121

136122
class AlertGroup(AlertGroupSlackRenderingMixin, EscalationSnapshotMixin, models.Model):
137-
all_objects = AlertGroupManager.from_queryset(AlertGroupQuerySet)()
138-
unarchived_objects = AlertGroupManager.from_queryset(UnarchivedAlertGroupQuerySet)()
123+
all_objects = AlertGroupQuerySet.as_manager()
124+
unarchived_objects = UnarchivedAlertGroupQuerySet.as_manager()
139125

140126
(
141127
NEW,
@@ -242,8 +228,6 @@ class AlertGroup(AlertGroupSlackRenderingMixin, EscalationSnapshotMixin, models.
242228

243229
active_escalation_id = models.CharField(max_length=100, null=True, default=None) # ID generated by celery
244230
active_resolve_calculation_id = models.CharField(max_length=100, null=True, default=None) # ID generated by celery
245-
# ID generated by celery
246-
active_cache_for_web_calculation_id = models.CharField(max_length=100, null=True, default=None)
247231

248232
SILENCE_DELAY_OPTIONS = (
249233
(1800, "30 minutes"),
@@ -315,7 +299,9 @@ def status(self):
315299
related_name="dependent_alert_groups",
316300
)
317301

318-
cached_render_for_web = JSONField(default=dict)
302+
# cached_render_for_web and active_cache_for_web_calculation_id are deprecated
303+
cached_render_for_web = models.JSONField(default=dict)
304+
active_cache_for_web_calculation_id = models.CharField(max_length=100, null=True, default=None)
319305

320306
last_unique_unacknowledge_process_id = models.CharField(max_length=100, null=True, default=None)
321307
is_archived = models.BooleanField(default=False)
@@ -364,6 +350,11 @@ class Meta:
364350
"distinction",
365351
"is_open_for_grouping",
366352
]
353+
indexes = [
354+
models.Index(
355+
fields=["channel_id", "resolved", "acknowledged", "silenced", "root_alert_group_id", "is_archived"]
356+
),
357+
]
367358

368359
def __str__(self):
369360
return f"{self.pk}: {self.verbose_name}"
@@ -404,18 +395,6 @@ def skip_escalation_in_slack(self):
404395
def is_alert_a_resolve_signal(self, alert):
405396
raise NotImplementedError
406397

407-
def cache_for_web(self, organization):
408-
from apps.api.serializers.alert_group import AlertGroupSerializer
409-
410-
# Re-take object to switch connection from readonly db to master.
411-
_self = AlertGroup.all_objects.get(pk=self.pk)
412-
_self.cached_render_for_web = AlertGroupSerializer(self, context={"organization": organization}).data
413-
self.cached_render_for_web = _self.cached_render_for_web
414-
_self.save(update_fields=["cached_render_for_web"])
415-
416-
def schedule_cache_for_web(self):
417-
schedule_cache_for_alert_group.apply_async((self.pk,))
418-
419398
@property
420399
def permalink(self):
421400
if self.slack_message is not None:
@@ -425,10 +404,6 @@ def permalink(self):
425404
def web_link(self):
426405
return urljoin(self.channel.organization.web_link, f"?page=incident&id={self.public_primary_key}")
427406

428-
@property
429-
def alerts_count(self):
430-
return self.alerts.count()
431-
432407
@property
433408
def happened_while_maintenance(self):
434409
return self.root_alert_group is not None and self.root_alert_group.maintenance_uuid is not None
@@ -449,10 +424,6 @@ def acknowledge_by_user(self, user: User, action_source: Optional[str] = None) -
449424
self.unresolve()
450425
self.log_records.create(type=AlertGroupLogRecord.TYPE_UN_RESOLVED, author=user, reason="Acknowledge button")
451426

452-
# clear resolve report cache
453-
cache_key = "render_after_resolve_report_json_{}".format(self.pk)
454-
cache.delete(cache_key)
455-
456427
self.acknowledge(acknowledged_by_user=user, acknowledged_by=AlertGroup.USER)
457428
self.stop_escalation()
458429
if self.is_root_alert_group:
@@ -673,9 +644,6 @@ def un_resolve_by_user(self, user: User, action_source: Optional[str] = None) ->
673644
self.unresolve()
674645
log_record = self.log_records.create(type=AlertGroupLogRecord.TYPE_UN_RESOLVED, author=user)
675646

676-
# clear resolve report cache
677-
self.drop_cached_after_resolve_report_json()
678-
679647
if self.is_root_alert_group:
680648
self.start_escalation_if_needed()
681649

@@ -848,10 +816,6 @@ def silence_by_user(self, user: User, silence_delay: Optional[int], action_sourc
848816
self.unresolve()
849817
self.log_records.create(type=AlertGroupLogRecord.TYPE_UN_RESOLVED, author=user, reason="Silence button")
850818

851-
# clear resolve report cache
852-
cache_key = "render_after_resolve_report_json_{}".format(self.pk)
853-
cache.delete(cache_key)
854-
855819
if self.acknowledged:
856820
self.unacknowledge()
857821
self.log_records.create(type=AlertGroupLogRecord.TYPE_UN_ACK, author=user, reason="Silence button")
@@ -1060,8 +1024,6 @@ def bulk_acknowledge(user: User, alert_groups: "QuerySet[AlertGroup]") -> None:
10601024
author=user,
10611025
reason="Bulk action acknowledge",
10621026
)
1063-
# clear resolve report cache
1064-
alert_group.drop_cached_after_resolve_report_json()
10651027

10661028
for alert_group in alert_groups_to_unsilence_before_acknowledge_list:
10671029
alert_group.log_records.create(
@@ -1194,8 +1156,6 @@ def bulk_restart(user: User, alert_groups: "QuerySet[AlertGroup]") -> None:
11941156
reason="Bulk action restart",
11951157
)
11961158

1197-
alert_group.drop_cached_after_resolve_report_json()
1198-
11991159
if alert_group.is_root_alert_group:
12001160
alert_group.start_escalation_if_needed()
12011161

@@ -1293,7 +1253,6 @@ def bulk_silence(user: User, alert_groups: "QuerySet[AlertGroup]", silence_delay
12931253
author=user,
12941254
reason="Bulk action silence",
12951255
)
1296-
alert_group.drop_cached_after_resolve_report_json()
12971256

12981257
for alert_group in alert_groups_to_unsilence_before_silence_list:
12991258
alert_group.log_records.create(
@@ -1483,7 +1442,7 @@ def get_acknowledge_text(self, mention_user=False):
14831442
else:
14841443
return "Acknowledged"
14851444

1486-
def non_cached_after_resolve_report_json(self):
1445+
def render_after_resolve_report_json(self):
14871446
AlertGroupLogRecord = apps.get_model("alerts", "AlertGroupLogRecord")
14881447
UserNotificationPolicyLogRecord = apps.get_model("base", "UserNotificationPolicyLogRecord")
14891448
ResolutionNote = apps.get_model("alerts", "ResolutionNote")
@@ -1501,21 +1460,6 @@ def non_cached_after_resolve_report_json(self):
15011460
result_log_report.append(log_record.render_log_line_json())
15021461
return result_log_report
15031462

1504-
def render_after_resolve_report_json(self):
1505-
cache_key = "render_after_resolve_report_json_{}".format(self.pk)
1506-
1507-
# cache.get_or_set in some cases returns None, so use get and set cache methods separately
1508-
log_report = cache.get(cache_key)
1509-
if log_report is None:
1510-
log_report = self.non_cached_after_resolve_report_json()
1511-
cache.set(cache_key, log_report)
1512-
return log_report
1513-
1514-
def drop_cached_after_resolve_report_json(self):
1515-
cache_key = "render_after_resolve_report_json_{}".format(self.pk)
1516-
if cache_key in cache:
1517-
cache.delete(cache_key)
1518-
15191463
@property
15201464
def has_resolution_notes(self):
15211465
return self.resolution_notes.exists()
@@ -1595,14 +1539,3 @@ def last_stop_escalation_log(self):
15951539
)
15961540

15971541
return stop_escalation_log
1598-
1599-
1600-
@receiver(post_save, sender=AlertGroup)
1601-
def listen_for_alert_group_model_save(sender, instance, created, *args, **kwargs):
1602-
if (
1603-
kwargs is not None
1604-
and "update_fields" in kwargs
1605-
and kwargs["update_fields"] is dict
1606-
and "cached_render_for_web" not in kwargs["update_fields"]
1607-
):
1608-
transaction.on_commit(instance.schedule_cache_for_alert_group)

engine/apps/alerts/models/alert_group_log_record.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import humanize
55
from django.apps import apps
6-
from django.db import models, transaction
6+
from django.db import models
77
from django.db.models import JSONField
88
from django.db.models.signals import post_save
99
from django.dispatch import receiver
@@ -546,7 +546,6 @@ def get_step_specific_info(self):
546546

547547
@receiver(post_save, sender=AlertGroupLogRecord)
548548
def listen_for_alertgrouplogrecord(sender, instance, created, *args, **kwargs):
549-
instance.alert_group.drop_cached_after_resolve_report_json()
550549
if instance.type != AlertGroupLogRecord.TYPE_DELETED:
551550
if not instance.alert_group.is_maintenance_incident:
552551
alert_group_pk = instance.alert_group.pk
@@ -555,6 +554,3 @@ def listen_for_alertgrouplogrecord(sender, instance, created, *args, **kwargs):
555554
f"alert group event: {instance.get_type_display()}"
556555
)
557556
send_update_log_report_signal.apply_async(kwargs={"alert_group_pk": alert_group_pk}, countdown=8)
558-
559-
logger.info(f"Recalculate AG cache. Reason: save alert_group_log_record model {instance.pk}")
560-
transaction.on_commit(instance.alert_group.schedule_cache_for_web)

engine/apps/alerts/models/alert_receive_channel.py

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,7 @@
1919
from apps.alerts.grafana_alerting_sync_manager.grafana_alerting_sync import GrafanaAlertingSyncManager
2020
from apps.alerts.integration_options_mixin import IntegrationOptionsMixin
2121
from apps.alerts.models.maintainable_object import MaintainableObject
22-
from apps.alerts.tasks import (
23-
disable_maintenance,
24-
invalidate_web_cache_for_alert_group,
25-
sync_grafana_alerting_contact_points,
26-
)
22+
from apps.alerts.tasks import disable_maintenance, sync_grafana_alerting_contact_points
2723
from apps.base.messaging import get_messaging_backend_from_id
2824
from apps.base.utils import live_settings
2925
from apps.integrations.metadata import heartbeat
@@ -693,21 +689,6 @@ def listen_for_alertreceivechannel_model_save(sender, instance, created, *args,
693689
create_organization_log(
694690
instance.organization, None, OrganizationLogType.TYPE_HEARTBEAT_CREATED, description
695691
)
696-
else:
697-
if kwargs is not None:
698-
if "update_fields" in kwargs:
699-
if kwargs["update_fields"] is not None:
700-
fields_to_not_to_invalidate_cache = [
701-
"rate_limit_message_task_id",
702-
"rate_limited_in_slack_at",
703-
"reason_to_skip_escalation",
704-
]
705-
# Hack to not to invalidate web cache on AlertReceiveChannel.start_send_rate_limit_message_task
706-
for f in fields_to_not_to_invalidate_cache:
707-
if f in kwargs["update_fields"]:
708-
return
709-
logger.info(f"Drop AG cache. Reason: save alert_receive_channel {instance.pk}")
710-
invalidate_web_cache_for_alert_group.apply_async(kwargs={"channel_pk": instance.pk})
711692

712693
if instance.integration == AlertReceiveChannel.INTEGRATION_GRAFANA_ALERTING:
713694
if created:

engine/apps/alerts/tasks/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from .delete_alert_group import delete_alert_group # noqa: F401
1010
from .distribute_alert import distribute_alert # noqa: F401
1111
from .escalate_alert_group import escalate_alert_group # noqa: F401
12-
from .invalidate_web_cache_for_alert_group import invalidate_web_cache_for_alert_group # noqa: F401
12+
from .invalidate_web_cache_for_alert_group import invalidate_web_cache_for_alert_group # noqa: F401, todo: remove
1313
from .invite_user_to_join_incident import invite_user_to_join_incident # noqa: F401
1414
from .maintenance import disable_maintenance # noqa: F401
1515
from .notify_all import notify_all_task # noqa: F401

0 commit comments

Comments
 (0)