Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support YJZ general robot alert #1641

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
- [Helm] Add optional liveness and readiness probe - [#1604](https://github.com/jertel/elastalert2/pull/1604) - @aizerin
- Add `include_rule_params_in_matches` rule parameter to enable copying of specific rule params into match data - [#1605](https://github.com/jertel/elastalert2/pull/1605) - @jertel
- [Helm] Add `--prometheus_addr` command line parameter to allow binding the Prometheus metrics server on a different host address - [#1608](https://github.com/jertel/elastalert2/pull/1608) - @tgxworld
- Support YZJ general robots - [#1641](https://github.com/jertel/elastalert2/pull/1641) - @innerpeacez

## Other changes
- [Docs] Add missing documentation of the `aggregation_alert_time_compared_with_timestamp_field` option. - [#1588](https://github.com/jertel/elastalert2/pull/1588) - @nicolasnovelli
Expand Down
28 changes: 28 additions & 0 deletions docs/source/alerts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ or
- webex_webhook
- workwechat
- zabbix
- yzj

Options for each alerter can either defined at the top level of the YAML file, or nested within the alert name, allowing for different settings
for multiple of the same alerter. For example, consider sending multiple emails, but with different 'To' and 'From' fields:
Expand Down Expand Up @@ -2605,3 +2606,30 @@ Example usage::
zbx_key: "sender_load1"

where ``hostname`` is the available elasticsearch field.

YZJ
~~~~~~~

YZJ will send notification to a YZJ application. The body of the notification is formatted the same as with other alerters.

Required:

``yzj_token``: The request token.

Optional:

``yzj_webhook_url``: The webhook URL.

``yzj_type``: Default 0, send text message. https://www.yunzhijia.com/opendocs/docs.html#/server-api/im/index?id=%e7%be%a4%e7%bb%84%e6%9c%ba%e5%99%a8%e4%ba%ba

``yzj_proxy``: By default ElastAlert 2 will not use a network proxy to send notifications to YZJ. Set this option using ``hostname:port`` if you need to use a proxy. only supports https.

``yzj_custom_loc``: The YZJ custom loc for privately deployed.


Example usage::

alert:
- "yzj"
yzj_token: "token"

57 changes: 57 additions & 0 deletions elastalert/alerters/yzj.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import json
import warnings
from urllib.parse import urlunsplit, urlsplit

import requests
from requests import RequestException

from elastalert.alerts import Alerter, DateTimeEncoder
from elastalert.util import EAException, elastalert_logger


class YzjAlerter(Alerter):
""" Creates a YZJ room message for each alert """
required_options = frozenset(['yzj_token'])

def __init__(self, rule):
super(YzjAlerter, self).__init__(rule)
self.yzj_token = self.rule.get('yzj_token', None)
self.yzj_type = self.rule.get('yzj_type', 0)
self.yzj_webhook_url = 'https://www.yunzhijia.com/gateway/robot/webhook/send?yzjtype=%s&yzjtoken=%s' % (self.yzj_type, self.yzj_token)
self.yzj_proxy = self.rule.get('yzj_proxy', None)
self.yzj_custom_loc = self.rule.get('yzj_custom_loc', None)

def alert(self, matches):
body = self.create_alert_body(matches)

proxies = {'https': self.yzj_proxy} if self.yzj_proxy else None
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json;charset=utf-8'
}

if self.yzj_custom_loc is not None:
part = urlsplit(self.yzj_webhook_url)
custom_part = part._replace(netloc=self.yzj_custom_loc)
self.yzj_webhook_url = urlunsplit(custom_part)

payload = {
'content': body
}

try:
response = requests.post(self.yzj_webhook_url, data=json.dumps(payload, cls=DateTimeEncoder),
headers=headers,
proxies=proxies)
warnings.resetwarnings()
response.raise_for_status()
except RequestException as e:
raise EAException("Error posting to yzj: %s" % e)

elastalert_logger.info("Trigger sent to YZJ")

def get_info(self):
return {
"type": "yzj",
"yzj_webhook_url": self.yzj_webhook_url
}
2 changes: 2 additions & 0 deletions elastalert/loaders.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
from elastalert.alerters.sns import SnsAlerter
from elastalert.alerters.teams import MsTeamsAlerter
from elastalert.alerters.powerautomate import MsPowerAutomateAlerter
from elastalert.alerters.yzj import YzjAlerter
from elastalert.alerters.zabbix import ZabbixAlerter
from elastalert.alerters.tencentsms import TencentSMSAlerter
from elastalert.alerters.indexer import IndexerAlerter
Expand Down Expand Up @@ -145,6 +146,7 @@ class RulesLoader(object):
'iris': elastalert.alerters.iris.IrisAlerter,
'indexer': IndexerAlerter,
'matrixhookshot': MatrixHookshotAlerter,
'yzj': YzjAlerter,
}

# A partial ordering of alert types. Relative order will be preserved in the resulting alerts list
Expand Down
8 changes: 7 additions & 1 deletion elastalert/schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ definitions:
additionalProperties: false
properties:
name: {type: string}
value: {type: string}
value: {type: string}

arrayOfMsTeamsFacts: &arrayOfMsTeamsFacts
type: array
Expand Down Expand Up @@ -913,3 +913,9 @@ properties:
zbx_host_from_field: {type: boolean}
zbx_host: {type: string}
zbx_key: {type: string}

### YZJ
yzj_token: {type: string}
yzj_type: {type: integer, enum: [0]}
yzj_custom_loc: {type: string}

47 changes: 47 additions & 0 deletions tests/alerters/yzj_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import json
import logging

from unittest import mock

from elastalert.alerters.yzj import YzjAlerter
from elastalert.loaders import FileRulesLoader


def test_yzj_text(caplog):
caplog.set_level(logging.INFO)
rule = {
'name': 'Test YZJ Rule',
'type': 'any',
'yzj_token': 'xxxxxxx',
'yzj_custom_loc': 'www.myloc.cn',
'alert': [],
'alert_subject': 'Test YZJ'
}
rules_loader = FileRulesLoader({})
rules_loader.load_modules(rule)
alert = YzjAlerter(rule)
match = {
'@timestamp': '2021-01-01T00:00:00',
'somefield': 'foobarbaz'
}

with mock.patch('requests.post') as mock_post_request:
alert.alert([match])

expected_data = {
'content': 'Test YZJ Rule\n\n@timestamp: 2021-01-01T00:00:00\nsomefield: foobarbaz\n'
}

mock_post_request.assert_called_once_with(
'https://www.myloc.cn/gateway/robot/webhook/send?yzjtype=0&yzjtoken=xxxxxxx',
data=mock.ANY,
headers={
'Content-Type': 'application/json',
'Accept': 'application/json;charset=utf-8'
},
proxies=None
)

actual_data = json.loads(mock_post_request.call_args_list[0][1]['data'])
assert expected_data == actual_data
assert ('elastalert', logging.INFO, 'Trigger sent to YZJ') == caplog.record_tuples[0]