Posted at

ZabbixAPI投げて障害情報をSlackに投げるpythonプログラム書いた

More than 1 year has passed since last update.


Zabbixサーバが乱立してしまった

諸事情によりZabbixサーバが数台立っており、それぞれ管理しないといけない事態になった。

日々のチェックが非常に面倒だったのでAPI使って一発で情報が受け取れるようなモノを作った。

image.png


優先度に応じて赤-黄-緑に色分けされる。見やすい…!

黒塗r###この先は文字が掠れている###



前提


  • python3

  • SlackAPI使える


やったこと


ZabbixAPI叩く

Zabbix API の仕組みを理解する

この記事のZabbixAPIクラスを使って各ZabbixのAPIを叩く。


先人のコードは偉大である。 ありがとうございます…!


trigger.getで "filter": {"status": 0,"value": 1}を指定することで現在起こっている障害だけを取得できる。

更に"selectHosts": ["name"]を指定することでホスト名も取得。

# http://qiita.com/Trickey/items/d51d93d525443baa496f

# のZabbixAPIクラスを利用。
zabapi= ZabbixApi(url,"Admin","zabbix")
zabapi.request('trigger.get', {
"output": ["triggerid","description","priority","lastchange"],
"selectHosts": ["name"],
"monitored": "true",
"filter": {
"status": 0,
"value": 1
}})
if 'result' in response:
for alert in response['result']:
if int(alert['lastchange']) < time.time()-(31*24*60*60):
# 一ヶ月以上前のアラートを無視
continue
# 加工してリストに追加
datetime_s = str(datetime.fromtimestamp(float(alert['lastchange']))) # UNIXTIMEなので変換
hostname = alert['hosts'][0]['name'] # ホスト名はlistの下にdictがぶら下がっているので[0]を噛ませる
description = alert['description'].replace('{HOST.NAME}', hostname)
uri = "http://{0}/".format(url)
ret.append({"description": description, "hostname": hostname, "time":datetime_s, "priority":alert['priority'],"url":uri})
return ret


優先度別に分類したかったのでソート関数自作。

from functools import cmp_to_key

## カスタムソート機構
def cmp(a,b):
a = int(a)
b = int(b)
return (a>b)-(a<b)

def cmp_len(s1, s2):
# 優先度順、同じならホスト名の頭一文字コード順
ret = cmp(s1['priority'], s2['priority'])
if ret == 0:
return cmp(s1['hostname'].encode('utf-8')[0], s2['hostname'].encode('utf-8')[0])
else:
return ret

def main():
<>
# 優先度順にソート
errlist = sorted(errlist, key=cmp_to_key(cmp_len), reverse=True)


SlackのAttachment機能を使って見やすくする。

Attaching content and links to messages

jsonで投げるだけで冒頭の画像みたいな表示になってくれる。


dict形式で返す関数なので使う時はパースをお忘れなく


def createAttachment(hostname,description,time_s,priority,uri=""):

""" Slackに投げるAttachmentを作成する """
# 優先度別で色を付ける
colorlist = {
'5':"#FF2222",
'4':"#FF9922",
'3':"#FFFF22",
'2':"#CCFF22",
'1':"#22FF22"
}
color = colorlist[priority]

# https://api.slack.com/docs/message-attachments
return {
"color": color,
"author_name": hostname,
"author_link": uri,
"text": description,
"fields": [
{
"title": "time",
"value": time_s,
"short": True
},
{
"title": "Priority",
"value": priority,
"short": True
}
]
}


後は集計してSlackAPIへポン。

def main():

# 調査するZabbixのURLリスト
serverlist = [ "url/to/zabbix1",
"url/to/zabbix2"
]
errlist = []

# 障害をリストして優先度順にソート
for srv in serverlist:
errlist.extend(getErrorSummary(srv))
errlist = sorted(errlist, key=cmp_to_key(cmp_len), reverse=True)

# Attachment作成ついでに優先度別に集計
att = []
priority_count = [0,0,0,0,0]
for err in errlist:
priority_count[int(err["priority"])-1] += 1
att.append(createAttachment(err["hostname"],err["description"],err["time"],err["priority"],err["url"]))

# メッセージ作成
mes = "いまのZabbixアラートだよ!\n Summary : "
for pcidx in range(4, -1, -1):
if priority_count[pcidx] > 0:
mes = mes + (str(pcidx+1)+':'+str(priority_count[pcidx])+' ')

# SlackへPOST (自作関数)
post_message(username="ZabbixSummary",message=mes,attachments=att)


定期的に確認する

linux機に突っ込んでcronに登録するだけ。


おしまい。

Tips的に書いているので全コードは乗っけてません。

動いているコードから抜粋したりコメント追加したりして掲載しているので、

利用する際は各自で不足分補ってください(丸投げ)


最後に

Zabbixが乱立するなんてことになる前に一元管理ができないか計画をしよう!