sensu slack連携


# Goal

* sensuが検知したイベントをアラートとしてslackのスレッドに投稿する

# Manual

現時点ではslackの公式なsensuサポートはないみたいなので、webhook urlを使う.

## sensu => slackへの通信の口を開ける

### slack incoming webhook urlを作成

https://{slackのドメイン}/services/new/incoming-webhook

チャンネルを選んでwebhook urlを作成する.
`https://hooks.slack.com/services/.../.../...`のような形式になっている.
このURLに対する認証の仕組みはないらしい. URLを知っていればどのホストからもそのチャンネルへ投稿ができる.
webhook urlが有効になったかどうかは上記サポートページにも記載あるが以下のコマンドで単体確認できる.

```
## 
## testチャンネルに
## webhookbotというユーザで
## ゴーストアイコンで投稿したい場合
## 
curl -X POST --data-urlencode 'payload={"channel": "#test", "username": "webhookbot", "text": "This is posted to #test and comes from a bot named webhookbot.", "icon_emoji": ":ghost:"}' "https://上記手順で取得したincoming webhook url"
```

## sensu => slack通知の設定

### slack設定ファイルを追加

sensuサーバのconf.d以下にslack.jsonを配置する.
https://github.com/sensu/sensu-community-plugins/issues/571

```json:/etc/sensu/conf.d/slack.json
{
  "handlers": {
    "slack": {
      "type": "pipe",
      "command": "/etc/sensu/handlers/slack.rb"
     }
  },
  "slack": {
    "webhook_url": "https://上記手順で取得したincoming webhook url",
    "channel": "#チャンネル名",
    "message_prefix": "",
    "markdown_enabled": false,
    "timeout": 10
  }
}
```

### slack handlerを追加

sensuサーバのhandlers以下にslack.rbを追加.
slack.rbはcommunity pluginsから取得する.
https://github.com/sensu/sensu-community-plugins
https://github.com/sensu/sensu-community-plugins/blob/master/handlers%2Fnotification%2Fslack.rb

### sensu checkのhandlerにslackを追加する

イベント発生時にslackに投下したいsensu checkの設定ファイルに、handlersを追加する.
:exclamation: sensu check設定にはhandlerとhandlersがあって、配列形式で指定できるのはhandlersのみです

```json:/etc/sensu/conf.d/check_cron.json
{
  "checks": {
    "cron": {
      "command": "/etc/sensu/plugins/check-procs.rb -p cron",
      "subscribers": [ "production" ],
      "interval": 60,
      "handlers": ["slack"]
    }
  }
}
```

### sensu server再起動

```
service sensu-server restart
```

起動時に`/var/log/sensu/sensu-server.log`を`tail`して、handlersにslackが出てくれば認識されている. ここに出てこない場合は、slack.jsonのパーミッションやjson syntaxなどのエラーが発生している可能性がある.

■sensu-server.log例 

```
{"timestamp":"2015-05-02T16:39:04.375398+0900","level":"warn","message":"loading config file","file":"/etc/sensu/conf.d/slack.json"}
{"timestamp":"2015-05-02T16:39:04.375706+0900","level":"warn","message":"config file applied changes","file":"/etc/sensu/conf.d/slack.json","changes":{"handlers":{"slack":[null,{"type":"pipe","command":"/etc/sensu/handlers/slack.rb"}]},"slack":[null,{"webhook_url":"https://上記手順で取得したincoming webhook url","channel":"#チャンネル名","username":"sensu","message_prefix":"","markdown_enabled":false,"timeout":10}]}}
```

![sensu-alert.png](https://qiita-image-store.s3.amazonaws.com/0/36978/917f28cc-132a-9fad-413e-e0fcd08000d5.png "sensu-alert.png")


## 検証・デバッグ

今回の手順ではcrondデーモン監視スクリプトにslack handlerを設定したので監視対象サーバのcrondを落としてみて通知がくるか確認.
うまくいっている場合は以下のようなログが出て、`"handlers":["slack"]`がセットされている.

```
{"timestamp":"2015-04-22T17:09:15.534475+0900","level":"info","message":"processing event","event":{"id":"7df9d41e-d57f-429f-b55b-bfc0f8f224f0","client":{"name":"rvprov-agile","address":"","subscriptions":["production"],"version":"0.17.2","timestamp":1429690142},"check":{"command":"/etc/sensu/plugins/check-procs.rb -p cron","subscribers":["production"],"interval":10,"handlers":["slack"],"name":"cron","issued":1429690155,"executed":1429690155,"duration":0.078,"output":"CheckProcs CRITICAL: Found 0 matching processes; cmd /cron/\n","status":2,"history":["2","2","2","2","2","2","2","2","2","2","2","2","2","2","2","2","2","2","2","2","2"],"total_state_change":0},"occurrences":143,"action":"create"}}
```

:exclamation: イベントが発生しても必ずhandlerが実行されるわけではない!!
デーモンの監視などは1分に1回とか高頻度で監視するものだけど、一旦プロセスが落ちて毎分アラートが出続けるとあまりにもうざいので、handlerは空気を読んでもっと緩いペースで実行されるようになっている.
handlerのデバッグなどのために必ずhandlerを実行させたければ、sensu-dashboardやuchiwaなどのクライアントからイベントのresolvを実行すればリセットされるので次のイベント発生時に必ずhandlerが実行されるようになる.
イベントのresolveはsensu-apiからでも可能.

http://sensuapp.org/docs/0.17/api-events
:exclamation: resolveのAPIエンドポイントはsensuの最近のバージョンで変更になっているので注意

```
curl --dump-header - -X POST -d '{"check":"cron","client":"rvprov-agile"}' http://{sensu apiホスト名}:4567/resolve
```

handlerも実行されているのに、sensu=>slack間の連携が疑われる場合は、slack.jsonのコマンドに以下のように記述してログを出してみるとデバッグが進むかも.

```json:/etc/sensu/conf.d/slack.json
(省略)
"command": "/etc/sensu/handlers/slack.rb &>> /tmp/sensu-slack.log"
(省略)
```

# slack incoming webhookのchannelを変更したい場合

https://{slackのドメイン}/services/
のincoming webhooksにアクセスして設定編集できる.