Skip to content

Commit

Permalink
Improve getting/updating contact points for Grafana Alerting integrat…
Browse files Browse the repository at this point in the history
…ion (#2742)

This PR improves Grafana Alerting integration:
- get alerting contact points "on fly" instead of keeping them in db
- add ability to connect more than one contact point
- add ability to create new contact point on create Grafana Alerting
integration
- show warnings in integration settings for non-active contact points
- remove creation alerting notification policies on create Grafana
Alerting integration

## Checklist

- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] `CHANGELOG.md` updated (or `pr:no changelog` PR label added if not
required)

---------

Co-authored-by: Rares Mardare <rares.mardare@grafana.com>
  • Loading branch information
Ferril and teodosii authored Aug 18, 2023
1 parent 3960e0d commit 58a9a39
Show file tree
Hide file tree
Showing 30 changed files with 2,700 additions and 895 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased

### Changed

- Improve Grafana Alerting integration by @Ferril @teodosii ([#2742](https://github.com/grafana/oncall/pull/2742))

## v1.3.24 (2023-08-17)

### Added
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .grafana_alerting_sync import GrafanaAlertingSyncManager # noqa: F401
889 changes: 410 additions & 479 deletions engine/apps/alerts/grafana_alerting_sync_manager/grafana_alerting_sync.py

Large diffs are not rendered by default.

31 changes: 13 additions & 18 deletions engine/apps/alerts/models/alert_receive_channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from apps.alerts.grafana_alerting_sync_manager.grafana_alerting_sync import GrafanaAlertingSyncManager
from apps.alerts.integration_options_mixin import IntegrationOptionsMixin
from apps.alerts.models.maintainable_object import MaintainableObject
from apps.alerts.tasks import disable_maintenance, sync_grafana_alerting_contact_points
from apps.alerts.tasks import disable_maintenance, disconnect_integration_from_alerting_contact_points
from apps.base.messaging import get_messaging_backend_from_id
from apps.base.utils import live_settings
from apps.integrations.legacy_prefix import remove_legacy_prefix
Expand All @@ -41,7 +41,7 @@
if typing.TYPE_CHECKING:
from django.db.models.manager import RelatedManager

from apps.alerts.models import AlertGroup, ChannelFilter, GrafanaAlertingContactPoint
from apps.alerts.models import AlertGroup, ChannelFilter
from apps.user_management.models import Organization, Team

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -117,7 +117,6 @@ class AlertReceiveChannel(IntegrationOptionsMixin, MaintainableObject):

alert_groups: "RelatedManager['AlertGroup']"
channel_filters: "RelatedManager['ChannelFilter']"
contact_points: "RelatedManager['GrafanaAlertingContactPoint']"
organization: "Organization"
team: typing.Optional["Team"]

Expand Down Expand Up @@ -165,7 +164,7 @@ class AlertReceiveChannel(IntegrationOptionsMixin, MaintainableObject):
verbal_name = models.CharField(max_length=150, null=True, default=None)
description_short = models.CharField(max_length=250, null=True, default=None)

is_finished_alerting_setup = models.BooleanField(default=False)
is_finished_alerting_setup = models.BooleanField(default=False) # deprecated

# *_*_template fields are legacy way of storing templates
# messaging_backends_templates for new integrations' templates
Expand Down Expand Up @@ -288,6 +287,13 @@ def change_team(self, team_id, user):
def grafana_alerting_sync_manager(self):
return GrafanaAlertingSyncManager(self)

@property
def is_alerting_integration(self):
return self.integration in {
AlertReceiveChannel.INTEGRATION_GRAFANA_ALERTING,
AlertReceiveChannel.INTEGRATION_LEGACY_GRAFANA_ALERTING,
}

@cached_property
def team_name(self):
return self.team.name if self.team else "No team"
Expand Down Expand Up @@ -652,21 +658,10 @@ def listen_for_alertreceivechannel_model_save(

metrics_add_integration_to_cache(instance)

if instance.integration in {
AlertReceiveChannel.INTEGRATION_GRAFANA_ALERTING,
AlertReceiveChannel.INTEGRATION_LEGACY_GRAFANA_ALERTING,
}:
if created:
instance.grafana_alerting_sync_manager.create_contact_points()
# do not trigger sync contact points if field "is_finished_alerting_setup" was updated
elif (
kwargs is None
or not kwargs.get("update_fields")
or "is_finished_alerting_setup" not in kwargs["update_fields"]
):
sync_grafana_alerting_contact_points.apply_async((instance.pk,), countdown=5)

elif instance.deleted_at:
if instance.is_alerting_integration:
disconnect_integration_from_alerting_contact_points.apply_async((instance.pk,), countdown=5)

metrics_remove_deleted_integration_from_cache(instance)
else:
metrics_update_integration_cache(instance)
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
logger = logging.getLogger(__name__)


# deprecated
class GrafanaAlertingContactPoint(models.Model):
GRAFANA_CONTACT_POINT = "grafana"
ALERTING_DATASOURCE = "alertmanager"
Expand Down
5 changes: 4 additions & 1 deletion engine/apps/alerts/tasks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
from .send_alert_group_signal import send_alert_group_signal # noqa: F401
from .send_update_log_report_signal import send_update_log_report_signal # noqa: F401
from .send_update_resolution_note_signal import send_update_resolution_note_signal # noqa: F401
from .sync_grafana_alerting_contact_points import sync_grafana_alerting_contact_points # noqa: F401
from .sync_grafana_alerting_contact_points import ( # noqa: F401
disconnect_integration_from_alerting_contact_points,
sync_grafana_alerting_contact_points,
)
from .unsilence import unsilence_task # noqa: F401
from .wipe import wipe # noqa: F401
10 changes: 7 additions & 3 deletions engine/apps/alerts/tasks/sync_grafana_alerting_contact_points.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
from apps.alerts.grafana_alerting_sync_manager.grafana_alerting_sync import GrafanaAlertingSyncManager
from common.custom_celery_tasks import shared_dedicated_queue_retry_task


# deprecated
@shared_dedicated_queue_retry_task(autoretry_for=(Exception,), retry_backoff=True, max_retries=10)
def sync_grafana_alerting_contact_points(alert_receive_channel_id):
pass


@shared_dedicated_queue_retry_task(autoretry_for=(Exception,), retry_backoff=True, max_retries=10)
def disconnect_integration_from_alerting_contact_points(alert_receive_channel_id):
from apps.alerts.models import AlertReceiveChannel

alert_receive_channel = AlertReceiveChannel.objects_with_deleted.get(pk=alert_receive_channel_id)

GrafanaAlertingSyncManager(alert_receive_channel).sync_each_contact_point()
alert_receive_channel.grafana_alerting_sync_manager.disconnect_all_contact_points()
Loading

0 comments on commit 58a9a39

Please sign in to comment.