Stoplight に Nagios のアラートを表示する
複数の Jenkins と Travis のビルドの失敗が最速で分かる Stoplight を Heroku にデプロイ - すえひろがりっっっっ! の続き。
StoplightのIcinga,Monitプロバイダ書いたよー - cynipeと読む によると簡単に通知元を増やせるそうです。
前回も載せた iPad のこの画像。
実は Nagios の情報を表示しています。
今回は Nagios のアラートを表示するための方法についてメモしておきます。
上記記事によると Nagios の情報を Restful API で公開できるようにする GitHub - dmytro/nagira: NAGIos Restful Api というのがあるようですが、今回仕掛けるサーバにはもろもろの事情により Ruby が導入できません。
さらに稼働している Nagios のバージョン 2.x 系と古く、そもそも Nagira が対応していませんでした。
そこで今回はたまたま入っていた PHP で代用することにしました。
PHP による nagios の情報の公開
Nagios はサービス状況を status.dat というファイルに吐くので、これをもとに JSON 形式で公開できるようにします。
<?php // stoplight.php $lines = file("/var/log/nagios/status.dat"); echo "{\n"; $processing_service = false; $json = ""; $host_name = ""; $service_name = ""; for ($i = 0; $i < count($lines); $i++) { $line = $lines[$i]; if (strpos($line, "service {") === 0) { $processing_service = true; } else if ($processing_service && strpos($line, "\t}") === 0) { $processing_service = false; echo "\"" . $host_name . " - " . $service_name . "\" : { \n"; echo substr($json, 0, -2); echo "\n}"; if (count($lines) - 2 != $i) { echo ","; } echo "\n"; $json = ""; } if ($processing_service) { $array = split("=", $line); if (count($array) >= 2) { $left = trim($array[0]); $right = trim($array[1]); if (strcmp($left, "host_name") === 0) { $host_name = $right; } else if (strcmp($left, "service_description") === 0) { $service_name = "$right"; } $json .= " \""; $json .= $left; $json .= "\":\""; $json .= trim($array[1]); $json .= "\",\n"; } } } echo "}\n";
あと Apache などの Web サーバで適宜設定すれば、以下のような感じで HTTP 経由で以下のような感じで取得できるようになります。
{ "名前" : { ... "last_check":"1354097154", ... "current_state":"1", ... }, "名前" : { ... }, ... }
とくに PHP である必要はなく、status.dat を解析して HTTP で公開できるものであればなんでもいいと思います。
Provider の記述
Stoplight に 上記の JSON を取得するコードを追加します。
https://github.com/customink/stoplight#contributing によると Stoplight::Providers::Provider を継承し、projects メソッドを実装するだけの親切設計のようです。
# lib/stoplight/providers/nagios.rb require 'multi_json' module Stoplight::Providers class Nagios < Provider def projects JSON.parse(@response.body).map do |name, service| Stoplight::Project.new({ :name => name, :build_url => '', :last_build_id => '', :last_build_time => Time.at(service['last_check'].to_i).strftime('%Y-%m-%d %H:%M:%S'), :last_build_status => (service['current_state'].to_i > 0 ? 1 : 0), :current_status => 0, :culprits => [] }) end end end end
継承元の Provider クラスのほうで、設定通りに HTTP リクエストしてくれて、それに対するレスポンスが @response に入っているので、これを Stoplight::Project に変換して返してあげればOKです。
失敗か成功かの判断は :last_build_status の値で行われます。
https://github.com/customink/stoplight/blob/master/lib/stoplight/project.rb を見る限り、0 なら成功、1 なら失敗となります。
これは Nagios の status.dat の current_state の値とちょうど一致しているので、そのまま渡してあげるだけで期待通りに動作します。
設定
Stoplight の config/servers.yml に以下のように記述します。
- type: 'nagios' url: https://nagios.host.url/stoplight.php username: ベーシック認証ユーザ名 password: ベーシック認証パスワード
url は Nagios 側に設置した status.dat を解析する PHP の URL を設定します。
Stoplight の Provider はユーザ名とパスワードを設定してあると、ベーシック認証を通してくれます。
PHP 側の Web サーバの設定などでベーシック認証の設定をやっておくとよいでしょう。