Help us understand the problem. What is going on with this article?

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

More than 3 years have 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が乱立するなんてことになる前に一元管理ができないか計画をしよう!

0Delta
インフラエンジニアからプログラマーへ再転生したひと。 Golangはいいぞ
infra-workshop
インフラ技術を勉強したい人たちのためのオンライン勉強会です
https://wp.infra-workshop.tech/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away