Nagiosのpassive checkとrsyslogを組み合わせてみた(2)

前回で、Nagios に対して、アラート通知を行う方法を書いたので、今回は、rsyslog の内容をNagios のアラート形式に書き換える方法について書いていく。

Nagios の理解できる形式は、次のようなものになる。

echo "[$(date +%s)] PROCESS_SERVICE_CHECK_RESULT;localhost;Current Load;1;testtest"

このうち、Current Load の部分にはNagios で service として指定されているものが入り、上の例ではNagios コンソール上で、Current Load が変更される。
筆者の環境では、 ログの確認を一律に行うため、他のサービスとは分割し、次のようなログを確認するためのサービスを加えた。

define service {
        hostgroup_name                  logcheck-servers
        service_description             check_log
        active_checks_enabled           0
        check_command                   check_ping!100.0,20%!500.0,60%
        use                             generic-service
        notification_interval           0 ; set > 0 if you want to be renotified
}
define hostgroup {
        hostgroup_name  logcheck-servers
               alias           logcheck servers
               members         localhost
}

service の中でcheck_ping で監視を行っているように見えるが、実際には、active_checks_enabled 0 の設定によってpingチェックは行わないようになっており、実質ではpassive check 専用となっている。デフォルトの設定からコピペした部分があるので、最小の設定にはなっていないかもしれない ,,,


check_log に対して、ログを書き込むものとすると、 rsyslog を編集する PythonスクリプトNagios のパイプに次のような文字列を書き込むことになる。

[$(date +%s)] PROCESS_SERVICE_CHECK_RESULT;localhost;check_log;1;testtest

testtestはエラーメッセージの本体で、syslogのメッセージから転載する。 その前の1は、Nagiosの状態を表し、 1はWARN, 2 はCRITICAL を指すが、syslog からの変換では、crit 以上をCRITICAL, warn 以上をWARNあたりに割り振ればよいのではなかろうか。。

問題はsyslog形式の時刻を Epoch へ変換する方法だが、Pythonのドキュメントを確認したところ、timeモジュールの strptime (フォーマット文字列をtimeを表すタプルへと変換する )を使うとそのまま解析できそうなことが分かった。ただ、筆者はrsyslog 側で少し工夫させることにした。(テキスト形式を経由すると、parsing のところでコストがかかるかと思ったため。もっとも以下のやりかたでもあまり状況は変わらないのだが。。。)

rsyslog ではテンプレートの機能を使い、syslogの出力フォーマットを変更できるが、ログの発生時刻については、オプションを設定することで、いくつかの形式で出力することができる。ここでは、 timereported:::date-mysql のフォーマットを使った。

$template preciseaaa,"%syslogpriority%,%syslogfacility%,%timereported:::date-mysql%,%HOSTNAME%,%syslogtag%,%msg%\n"
 *.*;auth,authpriv.none	    /tmp/aaa;preciseaaa

サンプルのpreciseからコピペしたため、いらないものも混じっているが、大体出力は次のようになる。

6,5,20091002001346,localhost,rsyslogd:, [origin software="rsyslogd" swVersion="1.19.12" x-pid="6257"]
[x-configInfo udpReception="Yes" udpPort="514" tcpReception="Yes" tcpPort="514"] restart

dateの出力が 2009/10/02 00:13:46 だと上のように"20091002001346"という出力になるため、Pythonでの解析がやりやすくなる。実際、timestamp として上の形式(YYYYMMDDhhmmss)を取り込んだ後、

 year=int(timestamp[0:4])
 month=int(timestamp[4:6])
 day=int(timestamp[6:8])
 hour=int(timestamp[8:10])
 minute=int(timestamp[10:12])
 second=int(timestamp[12:14])
 t=time.mktime( (year,month,day,hour,minute,second,0,0,0) )

のようにすることで、Epochからの秒数 t を得ることができた。ちなみに、 time.mktime は、 秒数を表すタプルを受け取って、 Epochからの秒数とする関数である。

ここまでで、rsyslog の出力をNagios 形式に変換する方法がわかったので、次回は、rsyslog の出力をPythonに渡す方法について書いていく。これがわかれば、後は機械的にsyslogの出力をNagiosに渡すだけである。