From 24c6c982241a9ebdf2a8ce12cbae5f34bae6f1e4 Mon Sep 17 00:00:00 2001 From: Evan Lock Date: Fri, 2 Apr 2021 09:40:10 -0400 Subject: [PATCH 1/4] Add alert handler to create Datadog Events --- elastalert/alerts.py | 30 ++++++++++++++++++++++++++++++ elastalert/loaders.py | 3 ++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/elastalert/alerts.py b/elastalert/alerts.py index f2f31853f..17f2e730a 100644 --- a/elastalert/alerts.py +++ b/elastalert/alerts.py @@ -2184,3 +2184,33 @@ def get_info(self): 'type': 'hivealerter', 'hive_host': self.rule.get('hive_connection', {}).get('hive_host', '') } + +class DatadogAlerter(Alerter): + ''' Creates a Datadog Event for each alert ''' + required_options = frozenset(['datadog_api_key', 'datadog_app_key']) + + def __init__(self, rule): + super(DatadogAlerter, self).__init__(rule) + self.dd_api_key = self.rule.get('datadog_api_key', None) + self.dd_app_key = self.rule.get('datadog_app_key', None) + + def alert(self, matches): + url = 'https://api.datadoghq.com/api/v1/events' + headers = { + 'Content-Type': 'application/json', + 'DD-API-KEY': self.dd_api_key, + 'DD-APPLICATION-KEY': self.dd_app_key + } + payload = { + 'title': self.create_title(matches), + 'text': self.create_alert_body(matches) + } + try: + response = requests.post(url, data=json.dumps(payload, cls=DateTimeEncoder), headers=headers) + response.raise_for_status() + except RequestException as e: + raise EAException('Error posting event to Datadog: %s' % e) + elastalert_logger.info('Alert sent to Datadog') + + def get_info(self): + return {'type': 'datadog'} diff --git a/elastalert/loaders.py b/elastalert/loaders.py index 771194768..1aabd0034 100644 --- a/elastalert/loaders.py +++ b/elastalert/loaders.py @@ -77,7 +77,8 @@ class RulesLoader(object): 'servicenow': alerts.ServiceNowAlerter, 'alerta': alerts.AlertaAlerter, 'post': alerts.HTTPPostAlerter, - 'hivealerter': alerts.HiveAlerter + 'hivealerter': alerts.HiveAlerter, + 'datadog': alerts.DatadogAlerter } # A partial ordering of alert types. Relative order will be preserved in the resulting alerts list From d348a2f55fe3170323e8800172c05726b85de1e8 Mon Sep 17 00:00:00 2001 From: Evan Lock Date: Fri, 23 Apr 2021 14:02:05 -0400 Subject: [PATCH 2/4] Add documentation for alert type --- docs/source/ruletypes.rst | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/source/ruletypes.rst b/docs/source/ruletypes.rst index 253a9dbc7..62e5a4c6b 100644 --- a/docs/source/ruletypes.rst +++ b/docs/source/ruletypes.rst @@ -1489,6 +1489,18 @@ Example usage using new-style format:: command: ["/bin/send_alert", "--username", "{match[username]}"] +Datadog +~~~~~~~ + +This alert will create a [Datadog Event](https://docs.datadoghq.com/events/). Events are limited to 4000 characters. If an event is sent that contains +a message that is longer than 4000 characters, only his first 4000 characters will be displayed. + +This alert requires two additional options: + +``datadog_api_key``: [Datadog API key](https://docs.datadoghq.com/account_management/api-app-keys/#api-keys) + +``datadog_app_key``: [Datadog application key](https://docs.datadoghq.com/account_management/api-app-keys/#application-keys) + Email ~~~~~ From bb141fdc253214cb74aa77e11cc9ee58ec541802 Mon Sep 17 00:00:00 2001 From: Evan Lock Date: Fri, 23 Apr 2021 15:46:31 -0400 Subject: [PATCH 3/4] Add test for Datadog alert --- tests/alerts_test.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/alerts_test.py b/tests/alerts_test.py index c0221ed1b..f66f08729 100644 --- a/tests/alerts_test.py +++ b/tests/alerts_test.py @@ -12,6 +12,7 @@ from elastalert.alerts import Alerter from elastalert.alerts import BasicMatchString from elastalert.alerts import CommandAlerter +from elastalert.alerts import DatadogAlerter from elastalert.alerts import EmailAlerter from elastalert.alerts import HTTPPostAlerter from elastalert.alerts import JiraAlerter @@ -2296,3 +2297,38 @@ def test_alert_subject_size_limit_with_args(ea): alert = Alerter(rule) alertSubject = alert.create_custom_title([{'test_term': 'test_value', '@timestamp': '2014-10-31T00:00:00'}]) assert 6 == len(alertSubject) + +def test_datadog_alerter(): + rule = { + 'name': 'Test Datadog Event Alerter', + 'type': 'any', + 'datadog_api_key': 'test-api-key', + 'datadog_app_key': 'test-app-key', + 'alert': [], + 'alert_subject': 'Test Datadog Event Alert' + } + rules_loader = FileRulesLoader({}) + rules_loader.load_modules(rule) + alert = DatadogAlerter(rule) + match = { + '@timestamp': '2021-01-01T00:00:00', + 'name': 'datadog-test-name' + } + with mock.patch('requests.post') as mock_post_request: + alert.alert([match]) + + expected_data = { + 'title': rule['alert_subject'], + 'text': "Test Datadog Event Alerter\n\n@timestamp: 2021-01-01T00:00:00\nname: datadog-test-name\n" + } + mock_post_request.assert_called_once_with( + "https://api.datadoghq.com/api/v1/events", + data=mock.ANY, + headers={ + 'Content-Type': 'application/json', + 'DD-API-KEY': rule['datadog_api_key'], + 'DD-APPLICATION-KEY': rule['datadog_app_key'] + } + ) + actual_data = json.loads(mock_post_request.call_args_list[0][1]['data']) + assert expected_data == actual_data From a6e8673a1049d2223c2f86f96b3b225a958d9112 Mon Sep 17 00:00:00 2001 From: Evan Lock Date: Fri, 23 Apr 2021 15:59:06 -0400 Subject: [PATCH 4/4] Correct linting errors --- elastalert/alerts.py | 1 + tests/alerts_test.py | 1 + 2 files changed, 2 insertions(+) diff --git a/elastalert/alerts.py b/elastalert/alerts.py index 26d19008b..db3988442 100644 --- a/elastalert/alerts.py +++ b/elastalert/alerts.py @@ -2232,6 +2232,7 @@ def get_info(self): "chatwork_room_id": self.chatwork_room_id } + class DatadogAlerter(Alerter): ''' Creates a Datadog Event for each alert ''' required_options = frozenset(['datadog_api_key', 'datadog_app_key']) diff --git a/tests/alerts_test.py b/tests/alerts_test.py index f66f08729..4f56ad1a7 100644 --- a/tests/alerts_test.py +++ b/tests/alerts_test.py @@ -2298,6 +2298,7 @@ def test_alert_subject_size_limit_with_args(ea): alertSubject = alert.create_custom_title([{'test_term': 'test_value', '@timestamp': '2014-10-31T00:00:00'}]) assert 6 == len(alertSubject) + def test_datadog_alerter(): rule = { 'name': 'Test Datadog Event Alerter',