Grafana AlertingやAlert Managerと連携して警告灯を点灯

これまでいくつか警告灯に関する記事を書いてきましたが、今回はGrafana Alerting(またはPrometheusのAlert Manager)からwebhookで通知を受け取り、警告灯が点灯する仕組みを作りました。

前回の記事ではwebhookで受け取った内容をそのままログファイルに書き出すだけにしていましたが、今回はwebhookの内容を一切見ません。webhookを受け取ったことをきっかけ(トリガー)として、Grafana Alerting(およびAlert Manager)から現在のアラートのステータスを直接取得し、その内容に基づいて警告灯を光らせるようにしました。webhookの内容だけを見ても、その時点での他のアラートの状態がわからないため、どのように灯りを制御すればよいかが非常に難しくなります。専用のデータベースを用意して状態を管理するのも面倒なので、この方法にしました。

超簡略版のコード例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
<?php

// 自身のGrafanaのAlertステータス取得URL
$url = "http://grafana_user:grafana_password@grafana_server:3000/api/alerts/";
$logFile = __DIR__ . '/warn.log';

if ($_SERVER["REQUEST_METHOD"] == "POST") {
    //$body = file_get_contents('php://input');
    //$json = json_decode($body);

    $json = json_decode(get_curl($url), true);
    //file_put_contents($logFile, print_r($json), FILE_APPEND);

    $warn = false;
    $alert = false;

    foreach($json as $ealert) {
        $log =  date("Y-m-d H:i:s "). $ealert['name'] . " " . $ealert['state'] . "\n";

        //Systel Load alertがalertingならアラートではなく警告とする
        if ($ealert['name'] =='System Load alert'){
            if ($ealert['state'] =='alerting'){
                $warn = true;
            }
        }

        file_put_contents($logFile, $log, FILE_APPEND);
    }

    //ライト点灯
    if ($alert) {
        light(3);
    } elseif ($warn) {
        light(2);
    } else {
        light(1);
    }
}

function get_curl($url) {
    $c = curl_init();
    curl_setopt($c, CURLOPT_URL, $url);
    curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
    $res =  curl_exec($c);
    //$res = var_dump($res);
    curl_close($c);

    return $res;
}

function light($c) {
    switch ($c) {
        case 0:
            //警告灯 消灯
            $code = "0f";
            break;
        case 1:
            //警告灯 緑
            $code = "0b";
            break;
        case 2:
            //警告灯 黄
            $code = "0d";
            break;
        case 3:
            //警告灯 赤
            $code = "0e";
            break;
    }

    $cmd = 'echo "' .  $code . '" | xxd -r -p > /dev/cuaU0';
    exec($cmd , $error);
    //echo $error;
}
?>

上の例は大幅に簡略化したもので、System Load alertという1つの警告パターンしか扱っていません(21〜25行目あたり)。

処理の概要

  • Grafana Alertingのステータスで、**1つでも「alerting」(深刻な異常)**があれば赤色で点灯
  • アラートはなく、警告相当のものが1つでもあれば黄色で点灯
  • どちらもない場合は緑色で点灯(正常)

アラート発生後の持続表示について

警告状態から正常に戻った場合は、素直に緑色に戻しても問題ありません。しかし、アラート(深刻な異常)が発生した後に警告や正常に戻った場合でも、すぐに黄・緑に変わってしまうと「問題が解決したように見えてしまう」のが良くない、という考え方もあります。

実際の運用では、アラートが発生したときに「アラート名+発生インスタンス名」の空ファイルを作成しています。そのファイルが存在する限り、Grafana側でアラートが解消されていても赤色を保持するようにしています。本当に問題が解決・確認できたときに、管理者が手動でそのファイルを削除する運用です。

その他の機能

警告灯とは別に、各インスタンスのステータスをPrometheusからcurlで取得してAmazon Pollyで音声読み上げさせる処理も作っています。
今回は警告・アラートも読み上げるように拡張しました(コードは割愛)。

いい歳をしたおっさんが中2病のようなの作ってて少し恥ずかしい、うん。

関連記事: