Skip to content

Commit

Permalink
Change Zabbix alerter
Browse files Browse the repository at this point in the history
  • Loading branch information
timeforplanb123 committed Apr 20, 2022
1 parent ec53a91 commit 3b200e8
Show file tree
Hide file tree
Showing 3 changed files with 211 additions and 81 deletions.
16 changes: 16 additions & 0 deletions docs/source/ruletypes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3324,6 +3324,8 @@ Required:

``zbx_sender_port``: The port where zabbix server is listenning, defaults to ``10051``.

``zbx_host_from_field``: This field allows to specify ``zbx_host`` value from the available terms. Defaults to ``False``.

``zbx_host``: This field setup the host in zabbix that receives the value sent by ElastAlert 2.

``zbx_key``: This field setup the key in the host that receives the value sent by ElastAlert 2.
Expand All @@ -3336,3 +3338,17 @@ Example usage::
zbx_sender_port: 10051
zbx_host: "test001"
zbx_key: "sender_load1"

To specify ``zbx_host`` depending on the available elasticsearch field, zabbix alerter has ``zbx_host_from_field`` option.

Example usage::

alert:
- "zabbix"
zbx_sender_host: "zabbix-server"
zbx_sender_port: 10051
zbx_host_from_field: True
zbx_host: "hostname"
zbx_key: "sender_load1"

where ``hostname`` is the available elasticsearch field.
111 changes: 80 additions & 31 deletions elastalert/alerters/zabbix.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,53 @@
from pyzabbix import ZabbixSender, ZabbixMetric, ZabbixAPI

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


class ZabbixClient(ZabbixAPI):

def __init__(self, url='http://localhost', use_authenticate=False, user='Admin', password='zabbix',
sender_host='localhost', sender_port=10051):
def __init__(
self,
url="http://localhost",
use_authenticate=False,
user="Admin",
password="zabbix",
sender_host="localhost",
sender_port=10051,
):
self.url = url
self.use_authenticate = use_authenticate
self.sender_host = sender_host
self.sender_port = sender_port
self.metrics_chunk_size = 200
self.aggregated_metrics = []

super(ZabbixClient, self).__init__(url=self.url,
use_authenticate=self.use_authenticate,
user=user,
password=password)
super(ZabbixClient, self).__init__(
url=self.url,
use_authenticate=self.use_authenticate,
user=user,
password=password,
)

def send_metric(self, hostname, key, data):
zm = ZabbixMetric(hostname, key, data)
if self.send_aggregated_metrics:
self.aggregated_metrics.append(zm)
if len(self.aggregated_metrics) > self.metrics_chunk_size:
elastalert_logger.info("Sending: %s metrics" % (len(self.aggregated_metrics)))
elastalert_logger.info(
"Sending: %s metrics" % (len(self.aggregated_metrics))
)
try:
ZabbixSender(zabbix_server=self.sender_host, zabbix_port=self.sender_port) \
.send(self.aggregated_metrics)
ZabbixSender(
zabbix_server=self.sender_host, zabbix_port=self.sender_port
).send(self.aggregated_metrics)
self.aggregated_metrics = []
except Exception as e:
elastalert_logger.exception(e)
else:
try:
ZabbixSender(zabbix_server=self.sender_host, zabbix_port=self.sender_port).send([zm])
ZabbixSender(
zabbix_server=self.sender_host, zabbix_port=self.sender_port
).send([zm])
except Exception as e:
elastalert_logger.exception(e)

Expand All @@ -46,18 +59,21 @@ class ZabbixAlerter(Alerter):
# You can ensure that the rule config file specifies all
# of the options. Otherwise, ElastAlert will throw an exception
# when trying to load the rule.
required_options = frozenset(['zbx_host', 'zbx_key'])
required_options = frozenset(["zbx_host", "zbx_key"])

def __init__(self, *args):
super(ZabbixAlerter, self).__init__(*args)

self.zbx_sender_host = self.rule.get('zbx_sender_host', 'localhost')
self.zbx_sender_port = self.rule.get('zbx_sender_port', 10051)
self.zbx_host = self.rule.get('zbx_host', None)
self.zbx_key = self.rule.get('zbx_key', None)
self.timestamp_field = self.rule.get('timestamp_field', '@timestamp')
self.timestamp_type = self.rule.get('timestamp_type', 'iso')
self.timestamp_strptime = self.rule.get('timestamp_strptime', '%Y-%m-%dT%H:%M:%S.%f%z')
self.zbx_sender_host = self.rule.get("zbx_sender_host", "localhost")
self.zbx_sender_port = self.rule.get("zbx_sender_port", 10051)
self.zbx_host_from_field = self.rule.get("zbx_host_from_field", False)
self.zbx_host = self.rule.get("zbx_host", None)
self.zbx_key = self.rule.get("zbx_key", None)
self.timestamp_field = self.rule.get("timestamp_field", "@timestamp")
self.timestamp_type = self.rule.get("timestamp_type", "iso")
self.timestamp_strptime = self.rule.get(
"timestamp_strptime", "%Y-%m-%dT%H:%M:%S.%f%z"
)

# Alert is called
def alert(self, matches):
Expand All @@ -67,29 +83,62 @@ def alert(self, matches):
# the aggregation option set
zm = []
for match in matches:
if ':' not in match[self.timestamp_field] or '-' not in match[self.timestamp_field]:
if (
":" not in match[self.timestamp_field]
or "-" not in match[self.timestamp_field]
):
ts_epoch = int(match[self.timestamp_field])
else:
try:
ts_epoch = int(datetime.strptime(match[self.timestamp_field], self.timestamp_strptime)
.timestamp())
ts_epoch = int(
datetime.strptime(
match[self.timestamp_field], self.timestamp_strptime
).timestamp()
)
except ValueError:
ts_epoch = int(datetime.strptime(match[self.timestamp_field], '%Y-%m-%dT%H:%M:%S%z')
.timestamp())
zm.append(ZabbixMetric(host=self.zbx_host, key=self.zbx_key, value='1', clock=ts_epoch))
ts_epoch = int(
datetime.strptime(
match[self.timestamp_field], "%Y-%m-%dT%H:%M:%S%z"
).timestamp()
)
if self.zbx_host_from_field:
zbx_host = lookup_es_key(match, self.rule["zbx_host"])
else:
zbx_host = self.zbx_host
zm.append(
ZabbixMetric(host=zbx_host, key=self.zbx_key, value="1", clock=ts_epoch)
)

try:
response = ZabbixSender(zabbix_server=self.zbx_sender_host, zabbix_port=self.zbx_sender_port).send(zm)
response = ZabbixSender(
zabbix_server=self.zbx_sender_host, zabbix_port=self.zbx_sender_port
).send(zm)
if response.failed:
elastalert_logger.warning("Missing zabbix host '%s' or host's item '%s', alert will be discarded"
% (self.zbx_host, self.zbx_key))
if self.zbx_host_from_field and not zbx_host:
elastalert_logger.warning(
"Missing term '%s' or host's item '%s', alert will be discarded"
% (self.zbx_host, self.zbx_key)
)
else:
elastalert_logger.warning(
"Missing zabbix host '%s' or host's item '%s', alert will be discarded"
% (zbx_host, self.zbx_key)
)
else:
elastalert_logger.info("Alert sent to Zabbix")
elastalert_logger.info(
"Alert sent to '%s:%s' zabbix server, '%s' zabbix host, '%s' zabbix host key"
% (
self.zbx_sender_host,
self.zbx_sender_port,
zbx_host,
self.zbx_key,
)
)
except Exception as e:
raise EAException("Error sending alert to Zabbix: %s" % e)

# get_info is called after an alert is sent to get data that is written back
# to Elasticsearch in the field "alert_info"
# It should return a dict of information relevant to what the alert does
def get_info(self):
return {'type': 'zabbix Alerter'}
return {"type": "zabbix Alerter"}
Loading

0 comments on commit 3b200e8

Please sign in to comment.