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 サーバの設定などでベーシック認証の設定をやっておくとよいでしょう。

まとめ

Nagios の情報を抜くところはアドホックですが、Stoplight 自体はたった 18 行のコードを追加するだけで Nagios 対応することができるようになりました。

同様に、なにかの失敗を検知して、メンバーにアラートしたいときには Stoplight の Provider を作成すれば、さくっと対応できそうです。

今回のコードは @mallowlabs さんに Gist に上げてもらったので何かの参考になれば。

https://gist.github.com/4165821