From 8ecd0683fc7b995d047e404f1026e862e60622e1 Mon Sep 17 00:00:00 2001 From: winebarrel Date: Sun, 24 Sep 2023 12:38:01 +0900 Subject: [PATCH 1/6] Add Datadog alert destination --- .../assets/images/destinations/datadog.png | Bin 0 -> 45797 bytes redash/destinations/datadog.py | 92 ++++++++++++++++++ redash/settings/__init__.py | 1 + 3 files changed, 93 insertions(+) create mode 100644 client/app/assets/images/destinations/datadog.png create mode 100644 redash/destinations/datadog.py diff --git a/client/app/assets/images/destinations/datadog.png b/client/app/assets/images/destinations/datadog.png new file mode 100644 index 0000000000000000000000000000000000000000..0c1cd4e583ff8bc31dc600149f875add0ead5384 GIT binary patch literal 45797 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%0DU%-gOhX>GKF{Q1+*w6LhAcOY!7bxaF0}ihdY<- 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 literal 0 HcmV?d00001 diff --git a/redash/destinations/datadog.py b/redash/destinations/datadog.py new file mode 100644 index 0000000000..0b161be324 --- /dev/null +++ b/redash/destinations/datadog.py @@ -0,0 +1,92 @@ +import logging +import os + +import requests + +from redash.destinations import BaseDestination, register +from redash.utils import json_dumps + + +class Datadog(BaseDestination): + @classmethod + def configuration_schema(cls): + return { + "type": "object", + "properties": { + "api_key": {"type": "string", "title": "API Key"}, + "tags": {"type": "string", "title": "Tags"}, + "priority": {"type": "string", "default": "normal", "title": "Priority"}, + # https://docs.datadoghq.com/integrations/faq/list-of-api-source-attribute-value/ + "source_type_name": {"type": "string", "default": "my_apps", "title": "Source Type Name"}, + }, + "secret": ["api_key"], + "required": ["api_key"], + } + + @classmethod + def icon(cls): + return "fa-datadog" + + def notify(self, alert, query, user, new_state, app, host, metadata, options): + # Documentation: https://docs.datadoghq.com/api/latest/events/#post-an-event + if new_state == "triggered": + alert_type = "error" + if alert.custom_subject: + title = alert.custom_subject + else: + title = f"{alert.name} just triggered" + else: + alert_type = "success" + if alert.custom_subject: + title = alert.custom_subject + else: + title = f"{alert.name} went back to normal" + + if alert.custom_body: + text = alert.custom_body + else: + text = f"{alert.name} changed state to {new_state}." + + query_url = f"{host}/queries/{query.id}" + alert_url = f"{host}/alerts/{alert.id}" + text += f"\nQuery: {query_url}\nAlert: {alert_url}" + + headers = { + "Accept": "application/json", + "Content-Type": "application/json", + "DD-API-KEY": options.get("api_key"), + } + + body = { + "title": title, + "text": text, + "alert_type": alert_type, + "priority": options.get("priority"), + "source_type_name": options.get("source_type_name"), + "tags": [], + } + + tags = options.get("tags") + if tags: + body["tags"] = tags.split(",") + body["tags"].extend( + [ + "redash", + f"query_id:{query.id}", + f"alert_id:{alert.id}", + ] + ) + + dd_host = os.getenv("DATADOG_HOST", "api.datadoghq.com") + url = f"https://{dd_host}/api/v1/events" + + try: + resp = requests.post(url, headers=headers, data=json_dumps(body), timeout=5.0) + logging.warning(resp.text) + if resp.status_code != 200: + logging.error(f"Datadog send ERROR. status_code => {resp.status_code}") + except Exception as e: + logging.exception("Datadog send ERROR: %s", e) + + +register(Datadog) diff --git a/redash/settings/__init__.py b/redash/settings/__init__.py index cce5e71158..74842fd769 100644 --- a/redash/settings/__init__.py +++ b/redash/settings/__init__.py @@ -366,6 +366,7 @@ def email_server_is_configured(): "redash.destinations.microsoft_teams_webhook", "redash.destinations.asana", "redash.destinations.webex", + "redash.destinations.datadog", ] enabled_destinations = array_from_string(os.environ.get("REDASH_ENABLED_DESTINATIONS", ",".join(default_destinations))) From e10e90a22877daaa220ed64f077ffa3870a22231 Mon Sep 17 00:00:00 2001 From: winebarrel Date: Sun, 24 Sep 2023 13:08:04 +0900 Subject: [PATCH 2/6] Fix Datadog Event API response code: 200 -> 202 --- redash/destinations/datadog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redash/destinations/datadog.py b/redash/destinations/datadog.py index 0b161be324..1acf0f86d2 100644 --- a/redash/destinations/datadog.py +++ b/redash/destinations/datadog.py @@ -83,7 +83,7 @@ def notify(self, alert, query, user, new_state, app, host, metadata, options): try: resp = requests.post(url, headers=headers, data=json_dumps(body), timeout=5.0) logging.warning(resp.text) - if resp.status_code != 200: + if resp.status_code != 202: logging.error(f"Datadog send ERROR. status_code => {resp.status_code}") except Exception as e: logging.exception("Datadog send ERROR: %s", e) From cace68ca4a948114a4f3d7b1522c329a11e7405b Mon Sep 17 00:00:00 2001 From: winebarrel Date: Sun, 24 Sep 2023 13:14:13 +0900 Subject: [PATCH 3/6] Add datadog alert dest test --- tests/handlers/test_destinations.py | 62 +++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/tests/handlers/test_destinations.py b/tests/handlers/test_destinations.py index aa0e865d6c..98e642d298 100644 --- a/tests/handlers/test_destinations.py +++ b/tests/handlers/test_destinations.py @@ -5,6 +5,7 @@ from redash.destinations.asana import Asana from redash.destinations.discord import Discord from redash.destinations.webex import Webex +from redash.destinations.datadog import Datadog from redash.models import Alert, NotificationDestination from tests import BaseTestCase @@ -247,3 +248,64 @@ def test_webex_notify_calls_requests_post(): ) assert mock_response.status_code == 204 + + +def test_datadog_notify_calls_requests_post(): + alert = mock.Mock(spec_set=["id", "name", "options", "render_template"]) + alert.id = 1 + alert.name = "Test Alert" + alert.options = { + "custom_subject": "Test custom subject", + "custom_body": "Test custom body", + } + alert.render_template = mock.Mock(return_value={"Rendered": "template"}) + query = mock.Mock() + query.id = 1 + + user = mock.Mock() + app = mock.Mock() + host = "https://localhost:5000" + options = { + "api_key": "my-api-key", + "tags": "foo:bar,zoo:baz", + "priority": "normal", + "source_type_name": "postgres", + } + metadata = {"Scheduled": False} + new_state = Alert.TRIGGERED_STATE + destination = Datadog(options) + + with mock.patch("redash.destinations.datadog.requests.post") as mock_post: + mock_response = mock.Mock() + mock_response.status_code = 202 + mock_post.return_value = mock_response + + destination.notify(alert, query, user, new_state, app, host, metadata, options) + + expected_payload = { + "title": "Test custom subject", + "text": "Test custom body\nQuery: https://localhost:5000/queries/1\nAlert: https://localhost:5000/alerts/1", + "alert_type": "error", + "priority": "normal", + "source_type_name": "postgres", + "tags": [ + "foo:bar", + "zoo:baz", + "redash", + "query_id:1", + "alert_id:1", + ], + } + + mock_post.assert_called_once_with( + "https://api.datadoghq.com/api/v1/events", + data=json.dumps(expected_payload), + headers={ + "Accept": "application/json", + "Content-Type": "application/json", + "DD-API-KEY": "my-api-key", + }, + timeout=5.0, + ) + + assert mock_response.status_code == 202 From 1acd7bb854ac43390d52287c93cf41cdf76ebd6b Mon Sep 17 00:00:00 2001 From: winebarrel Date: Sun, 24 Sep 2023 13:15:35 +0900 Subject: [PATCH 4/6] Sort test_destinations.py imports --- tests/handlers/test_destinations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/handlers/test_destinations.py b/tests/handlers/test_destinations.py index 98e642d298..63a21997bc 100644 --- a/tests/handlers/test_destinations.py +++ b/tests/handlers/test_destinations.py @@ -3,9 +3,9 @@ from unittest import mock from redash.destinations.asana import Asana +from redash.destinations.datadog import Datadog from redash.destinations.discord import Discord from redash.destinations.webex import Webex -from redash.destinations.datadog import Datadog from redash.models import Alert, NotificationDestination from tests import BaseTestCase From 1ecc4ef27ef0217f6d4d35da0fa2c4551a942fae Mon Sep 17 00:00:00 2001 From: winebarrel Date: Sun, 24 Sep 2023 13:29:37 +0900 Subject: [PATCH 5/6] Fix test_datadog_notify_calls_requests_post --- tests/handlers/test_destinations.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/handlers/test_destinations.py b/tests/handlers/test_destinations.py index 63a21997bc..5ae566481d 100644 --- a/tests/handlers/test_destinations.py +++ b/tests/handlers/test_destinations.py @@ -251,13 +251,11 @@ def test_webex_notify_calls_requests_post(): def test_datadog_notify_calls_requests_post(): - alert = mock.Mock(spec_set=["id", "name", "options", "render_template"]) + alert = mock.Mock(spec_set=["id", "name", "custom_subject", "custom_body", "render_template"]) alert.id = 1 alert.name = "Test Alert" - alert.options = { - "custom_subject": "Test custom subject", - "custom_body": "Test custom body", - } + alert.custom_subject = "Test custom subject" + alert.custom_body = "Test custom body" alert.render_template = mock.Mock(return_value={"Rendered": "template"}) query = mock.Mock() query.id = 1 From ae1c6f690967ec27a21db54ec825605c2947d462 Mon Sep 17 00:00:00 2001 From: winebarrel Date: Sun, 24 Sep 2023 15:28:54 +0900 Subject: [PATCH 6/6] Fix datadog alert dest: Add aggregation_key --- redash/destinations/datadog.py | 1 + tests/handlers/test_destinations.py | 1 + 2 files changed, 2 insertions(+) diff --git a/redash/destinations/datadog.py b/redash/destinations/datadog.py index 1acf0f86d2..61a4e0ddc0 100644 --- a/redash/destinations/datadog.py +++ b/redash/destinations/datadog.py @@ -63,6 +63,7 @@ def notify(self, alert, query, user, new_state, app, host, metadata, options): "alert_type": alert_type, "priority": options.get("priority"), "source_type_name": options.get("source_type_name"), + "aggregation_key": f"redash:{alert_url}", "tags": [], } diff --git a/tests/handlers/test_destinations.py b/tests/handlers/test_destinations.py index 5ae566481d..7a08dfcc9b 100644 --- a/tests/handlers/test_destinations.py +++ b/tests/handlers/test_destinations.py @@ -286,6 +286,7 @@ def test_datadog_notify_calls_requests_post(): "alert_type": "error", "priority": "normal", "source_type_name": "postgres", + "aggregation_key": "redash:https://localhost:5000/alerts/1", "tags": [ "foo:bar", "zoo:baz",