Sensu client for Windows の Tips

# Sensu client for Windows の Tips

Windows環境でもSensuClientはそのままでそれなりに動くのだが、ちょっとしたことをやろうと思うと結構ハマるポイントがあるので随時更新しながらまとめてみる。

### インストール

インストール自体は特に問題はないのだがSensuのドキュメントから進んでいくとリンク先がおかしいので、以下のリンクから進んでいくといい。

Sensu Package Repos: http://repos.sensuapp.org/index.html

### サービスへの登録

Windowsでは動かすまでにサービスへの追加とサービスの起動が必要だが、以下のバッチで処理。

``` bat:sensu-sutart.bat
net stop sensu-client
sc delete sensu-client
del %~dp0..\sensu-client.log
del %~dp0sensu-client.wrapper.log
sc create sensu-client start= delayed-auto binPath= %~dp0sensu-client.exe DisplayName= "Sensu Client"
net start sensu-client
```

バッチ化しておけば、定期的にこのバッチを流すことでログの肥大化も防げる(ログのローテーションが必要ない場合)。

### GraphiteへのMetric送信

これは環境によるのかもしれないけど、ドキュメント通りGraphiteへ送信するようにしてもうまくいかない。

Carbonの `listener.log` に下のようなエラーが出る。

`07/10/2014 13:13:31 :: invalid line received from client 127.0.0.1:45346, ignoring`

Carbonで受け取る形式で送れてなさそうなので、以下のように `mutators/graphite.rb` を修正。

``` diff:mutators/graphite.rb.diff
root@sensu:/etc/sensu/mutators# diff -u ../community-plugins/mutators/graphite.rb ./graphite.rb
--- ../community-plugins/mutators/graphite.rb   2014-10-17 10:21:25.542594822 +0900
+++ ./graphite.rb       2014-10-17 10:18:17.898601532 +0900
@@ -31,8 +31,10 @@
 # parse event
 event = JSON.parse(STDIN.read, :symbolize_names => true)

-if ARGV[0] == "-r" || ARGV[0] == "--reverse"
-  puts event[:check][:output].gsub(event[:client][:name], event[:client][:name].split('.').reverse.join("."))
-else
-  puts event[:check][:output].gsub(event[:client][:name], event[:client][:name].gsub('.', '_'))
+event[:check][:output].split(/\r?\n/).each do |l|
+  if ARGV[0] == "-r" || ARGV[0] == "--reverse"
+    puts l.gsub(event[:client][:name], event[:client][:name].split('.').reverse.join("."))
+  else
+    puts l.gsub(event[:client][:name], event[:client][:name].gsub('.', '_'))
+  end
 end
```

多分改行コードの問題かなんかで出力が全部一緒に渡ってるのだと思う。
なので、元のデータを改行で区切って一行づつに分けて処理させたらCarbonが受け取ってくれた。

### WMIでの定期的なデータ取得

LinuxでいうところのvmstatはWindowsだとWMIで取得することになるんだけど、例えば10s毎にデータを取りたいとなるといちいち子プロセスを立ち上げるPluginの方式だと負荷が気になる。
たとえ軽いRubyだとしても。たとえ軽いWMIだとしても。たとえ処理能力の高いWindowsサーバーだとしても。

となると、常時立ち上がってて定期的に出力させる方法が欲しくなるわけだが、Sensuにもそのやり方が準備してある。
それが [Sensu extensions](http://sensuapp.org/docs/0.14/extensions) なんだけど、Ver.0.14時点ではCheckExtensionsのドキュメントがTODOになってて未だ記載されてない。

それでもコミュニケーションプラグインにはWindowsのWMIを利用したCheckExtensionsが用意されている。
[extensions / checks / wmi_metrics.rb](https://github.com/sensu/sensu-community-plugins/blob/master/extensions/checks/wmi_metrics.rb)

動かし方の説明がないので conf.d に適当に書き込んだりしてたのだが、全然動く気配が無い。そんな中で以下のディスカッションを発見してやっと動作させることが出来た。
[sensu-users / Check Extensions](https://groups.google.com/forum/#!topic/sensu-users/G8g9SDsW4oo)

要はサービス起動用の `sensu-client.xml` にExtensionsのパスを指定するだけ。そのパスに入ってるExtensionsはサービスの起動とともに読み込まれて、イベントマシンの中でループするみたい。

ということで、 `sensu-client.xml` は以下のように設定。

```xml:sensu-client.xml
<!--
  Windows service definition for Sensu
-->
<service>
  <id>sensu-client</id>
  <name>Sensu Client</name>
  <description>This service runs a Sensu client</description>
  <executable>C:\opt\sensu\embedded\bin\ruby</executable>
  <arguments>C:\opt\sensu\embedded\bin\sensu-client -l C:\opt\sensu\sensu-client.log -d C:\opt\sensu\conf.d -e C:\opt\sensu\extensions</arguments>
</service>
```

Extensionの中でIntervalが10に設定されてあるから特に設定しなくてもこれだけでデータを取り出す。Standaloneモードで立ち上がるのでGraphiteへ送信するだけだったらサーバーでの設定もいらない。

### Ruby実行パスなどの指定

WindowsだとEmbeddedRubyを使うのが手っ取り早いんだけど、他にもRubyを使ってるサービスが有ったりするとRubyの実行パスの指定がちょっと厄介。
Rubyファイルを関連付けして直接起動するようにしてもいいんだけどちょっとそれはやりたくないし、他のサービスの邪魔もしたくないから環境変数にPATHを登録するのもちょっと...

となると、起動させるコマンドの指定が問題になってくる。フルパスだと長すぎない？サーバーによってドライブレターが違う場合はどうする？そんなところを吸収させるのが　`conf.d\client.json` で指定するやり方。

例えばクライアント側の `conf.d\client.json` には以下のように設定し、

```json:conf.d\client.json
{
  "client": {
    "name": "client",
    "address": "localhost",
    "subscriptions": [ "windows", "common" ],
    "ruby": "c:/opt/sensu/embedded/bin/ruby",
    "plugins": "c:/opt/sensu/plugins"
  }
}
```

サーバー側の `conf.d\check.json` には以下のように設定する。

```json:conf.d\check.json
{
  "checks": {
    "check": {
      "command": ":::ruby::: :::plugins:::/check.rb",
      "interval": 60,
      "subscribers": [ "windows" ]
    }
  }
}
```

そうするとWindowsクライアントの設定に合わせてRubyが実行される。実際は `cmd /c` に続けて実行されてるみたいなんで、 `c:/opt/sensu` を環境変数に登録して `%SENSU%` でアクセスさせてもいいかもしれない。

### クライアント側のログ抑制

ログのローテーションが堅くないwindowsでは安定稼働しだしたらログを絞りたくなるのだが、ログレベルの指定も `sensu-client.xml` で出来る模様。

`<arguments>` に 「`-L warn`」 を追加すれば警告以上に絞れる。