diff --git a/zerver/webhooks/grafana/fixtures/alert_ok.json b/zerver/webhooks/grafana/fixtures/alert_ok.json new file mode 100644 index 0000000000..9693ab877f --- /dev/null +++ b/zerver/webhooks/grafana/fixtures/alert_ok.json @@ -0,0 +1,20 @@ +{ + "dashboardId": 1, + "evalMatches": [ + { + "value": 0, + "metric": "High value", + "tags": null + } + ], + "imageUrl": "https://grafana.com/assets/img/blog/mixed_styles.png", + "message": "Someone is testing the alert notification within grafana.", + "orgId": 0, + "panelId": 1, + "ruleId": 0, + "ruleName": "Test rule", + "ruleUrl": "http://localhost:3000/", + "state": "ok", + "tags": {}, + "title": "[Ok] Test notification" + } diff --git a/zerver/webhooks/grafana/fixtures/alert_paused.json b/zerver/webhooks/grafana/fixtures/alert_paused.json new file mode 100644 index 0000000000..e1043e9332 --- /dev/null +++ b/zerver/webhooks/grafana/fixtures/alert_paused.json @@ -0,0 +1,13 @@ +{ + "dashboardId": 1, + "imageUrl": "https://grafana.com/assets/img/blog/mixed_styles.png", + "message": "Someone is testing the alert notification within grafana.", + "orgId": 0, + "panelId": 1, + "ruleId": 0, + "ruleName": "Test rule", + "ruleUrl": "http://localhost:3000/", + "state": "paused", + "tags": {}, + "title": "[Paused] Test notification" + } diff --git a/zerver/webhooks/grafana/fixtures/alert_pending.json b/zerver/webhooks/grafana/fixtures/alert_pending.json new file mode 100644 index 0000000000..35b412147f --- /dev/null +++ b/zerver/webhooks/grafana/fixtures/alert_pending.json @@ -0,0 +1,25 @@ +{ + "dashboardId": 1, + "evalMatches": [ + { + "value": 100, + "metric": "High value", + "tags": null + }, + { + "value": 200, + "metric": "Higher Value", + "tags": null + } + ], + "imageUrl": "https://grafana.com/assets/img/blog/mixed_styles.png", + "message": "Someone is testing the alert notification within grafana.", + "orgId": 0, + "panelId": 1, + "ruleId": 0, + "ruleName": "Test rule", + "ruleUrl": "http://localhost:3000/", + "state": "pending", + "tags": {}, + "title": "[Pending] Test notification" + } diff --git a/zerver/webhooks/grafana/tests.py b/zerver/webhooks/grafana/tests.py index 1afb4c2383..313aa2ac45 100644 --- a/zerver/webhooks/grafana/tests.py +++ b/zerver/webhooks/grafana/tests.py @@ -10,6 +10,8 @@ class GrafanaHookTests(WebhookTestCase): def test_alert(self) -> None: expected_topic = "[Alerting] Test notification" expected_message = """ +:alert: **ALERTING** + [Test rule](http://localhost:3000/) Someone is testing the alert notification within grafana. @@ -31,6 +33,8 @@ Someone is testing the alert notification within grafana. def test_no_data_alert(self) -> None: expected_topic = "[Alerting] No Data alert" expected_message = """ +:alert: **ALERTING** + [No Data alert](http://localhost:3000/d/GG2qhR3Wz/alerttest?fullscreen&edit&tab=alert&panelId=6&orgId=1) The panel has no data. @@ -48,6 +52,8 @@ The panel has no data. def test_no_message_alert(self) -> None: expected_topic = "[Alerting] No Message alert" expected_message = """ +:alert: **ALERTING** + [No Message alert](http://localhost:3000/d/GG2qhR3Wz/alerttest?fullscreen&edit&tab=alert&panelId=8&orgId=1) **A-series:** 21.573108436586445 @@ -60,3 +66,72 @@ The panel has no data. expected_message, content_type="application/x-www-form-urlencoded", ) + + # Note: Include a test function per each distinct message condition your integration supports + def test_alert_ok(self) -> None: + expected_topic = "[Ok] Test notification" + expected_message = """ +:squared_ok: **OK** + +[Test rule](http://localhost:3000/) + +Someone is testing the alert notification within grafana. + +**High value:** 0 + +[Click to view visualization](https://grafana.com/assets/img/blog/mixed_styles.png) +""".strip() + + # use fixture named helloworld_hello + self.check_webhook( + "alert_ok", + expected_topic, + expected_message, + content_type="application/x-www-form-urlencoded", + ) + + # Note: Include a test function per each distinct message condition your integration supports + def test_alert_paused(self) -> None: + expected_topic = "[Paused] Test notification" + expected_message = """ +:info: **PAUSED** + +[Test rule](http://localhost:3000/) + +Someone is testing the alert notification within grafana. + + +[Click to view visualization](https://grafana.com/assets/img/blog/mixed_styles.png) +""".strip() + + # use fixture named helloworld_hello + self.check_webhook( + "alert_paused", + expected_topic, + expected_message, + content_type="application/x-www-form-urlencoded", + ) + + # Note: Include a test function per each distinct message condition your integration supports + def test_alert_pending(self) -> None: + expected_topic = "[Pending] Test notification" + expected_message = """ +:info: **PENDING** + +[Test rule](http://localhost:3000/) + +Someone is testing the alert notification within grafana. + +**High value:** 100 +**Higher Value:** 200 + +[Click to view visualization](https://grafana.com/assets/img/blog/mixed_styles.png) +""".strip() + + # use fixture named helloworld_hello + self.check_webhook( + "alert_pending", + expected_topic, + expected_message, + content_type="application/x-www-form-urlencoded", + ) diff --git a/zerver/webhooks/grafana/view.py b/zerver/webhooks/grafana/view.py index 6223341479..d873a55dcf 100644 --- a/zerver/webhooks/grafana/view.py +++ b/zerver/webhooks/grafana/view.py @@ -10,7 +10,11 @@ from zerver.models import UserProfile GRAFANA_TOPIC_TEMPLATE = "{alert_title}" -GRAFANA_MESSAGE_TEMPLATE = "[{rule_name}]({rule_url})\n\n{alert_message}{eval_matches}" +GRAFANA_ALERT_STATUS_TEMPLATE = "{alert_icon} **{alert_state}**\n\n" + +GRAFANA_MESSAGE_TEMPLATE = ( + "{alert_status}[{rule_name}]({rule_url})\n\n{alert_message}{eval_matches}" +) @webhook_view("Grafana") @@ -33,8 +37,23 @@ def api_grafana_webhook( if payload.get("message") is not None: message_text = payload["message"] + "\n\n" + if payload.get("state") is not None: + if payload.get("state") == "alerting": + alert_status = GRAFANA_ALERT_STATUS_TEMPLATE.format( + alert_icon=":alert:", alert_state=payload["state"].upper() + ) + elif payload.get("state") == "ok": + alert_status = GRAFANA_ALERT_STATUS_TEMPLATE.format( + alert_icon=":squared_ok:", alert_state=payload["state"].upper() + ) + else: + alert_status = GRAFANA_ALERT_STATUS_TEMPLATE.format( + alert_icon=":info:", alert_state=payload["state"].upper() + ) + body = GRAFANA_MESSAGE_TEMPLATE.format( alert_message=message_text, + alert_status=alert_status, rule_name=payload["ruleName"], rule_url=payload["ruleUrl"], eval_matches=eval_matches_text,