Skip to content

Commit

Permalink
Support YJZ general robot
Browse files Browse the repository at this point in the history
  • Loading branch information
innerpeacez committed Mar 6, 2025
1 parent 55ccb06 commit 6cc7435
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 1 deletion.
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 - - @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]

0 comments on commit 6cc7435

Please sign in to comment.