sensuで録画状況をslackに通知する

# はじめに

chinachuとPT3で快適な録画環境はできた。ただし、mirakurunが停止していたことで録画できていなかったという悲しい事件が発生。

仕方がないので監視環境を整えることにした。本ページは以下の動きを実装した際に読み解いたhandlerのフィルタの仕方や、slackへの通知書式方法を残すために記す。

- 検知までの動き
    - 録画開始
        - chinachuの実行ログであるoperatorログを監視し、sensuのイベントを発生させる
        - sensuで監視したイベント処理
            - handlerのactionがcriateのイベントのみを通知対象とするようにfilterを通す。
            - filterを通ったイベントがslackに指定書式で通知される。
    - 録画終了
        - 同様

<img width="740" alt="slack.png" src="https://qiita-image-store.s3.amazonaws.com/0/125552/92713285-f984-37a7-8ddc-66b6a6597b20.png">


# sensu/uchiwaについて

## 公式ドキュメント
自由度の高い監視ができるのれ、公式ドキュメント参照が必須。
特に、handler,check,filterの動きを認識するためには各項目のリファレンスをちゃんと読むこと。

- [事前準備](https://sensuapp.org/docs/0.28/installation/installation-prerequisites.html)
- [リファレンス](https://sensuapp.org/docs/0.28/reference/)

## plugins

細かい使い方は載っていないので、ソースコードからオプションを読み解いて使いこなすガッツが必要。
- [sensu-plugin](http://sensu-plugins.io/plugins/)

### 使用した plugin
- [check-log.rb](https://github.com/sensu-plugins/sensu-plugins-logs)
- [handler-slack.rb](https://github.com/sensu-plugins/sensu-plugins-slack)

sensu enterpriseであれば、ネイティブでslackへの通知機能があるが、通常版は上記プラグインを利用して実装する。

# 設定ファイル
## sensuサーバ側

```shell-session:/etc/sensu配下
# tree
.
├── conf.d
│   ├── api.json
│   ├── chinachu_record.json
│   ├── client.json
│   ├── filter.json
│   ├── handler-slack-chinachu.json
│   ├── rabbitmq.json
│   ├── redis.json
│   ├── slack_payload
│   │   ├── attachement_chinachu-err.erb
│   │   ├── attachement_chinachu-fin.erb
│   │   └── attachement_chinachu-record.erb
│   └── transport.json
├── config.json
├── dashboard.d
├── extensions
├── plugins
│   └── handler-slack.rb
└── uchiwa.json
```

### ポイント
- サーバ側にslack通知用のプラグインを配置する
- ほぼ全てのコンフィグファイルがサーバ側に記述される。

### 各種ファイル

```shell-session:chinachu_record.json
{
  "checks": {
    "chinachu-record-record": {
      "command": "check-log.rb -f /home/chinachu/chinachu/log/operator --pattern 'RECORD:' --name=record --return",
      "interval": 60,
      "subscribers": [ "chinachu" ],
      "handlers": ["slack-chinachu-record"]
    },
    "chinachu-record-fin": {
      "command": "check-log.rb -f /home/chinachu/chinachu/log/operator --pattern 'FIN:' --name=fin --return",
      "interval": 60,
      "subscribers": [ "chinachu" ],
      "handlers": ["slack-chinachu-fin"]
    },
    "chinachu-record-err": {
      "command": "check-log.rb -f /home/chinachu/chinachu/log/operator --pattern 'ERROR:' --name=err --return",
      "interval": 60,
      "subscribers": [ "chinachu" ],
      "handlers": ["slack-chinachu-err"]
    }
  }
}
```
- chinachu_record.jsonのポイント
    - return オプションを付けることでマッチした行がoutputに含まれる
    - nameオプションをつけることで、キャッシュを/var/cache/chech_log/配下に別ファイルで持つことで1つのログファイルに対して複数のpatternを網羅できるようにしている。

```shell-session:handler-slack-chinachu.json
{
  "handlers": {
    "slack-chinachu-record": {
      "type": "pipe",
      "command": "/etc/sensu/plugins/handler-slack.rb -j slack-chinachu-record",
      "filter": "action_create_only"
    },
    "slack-chinachu-fin": {
      "type": "pipe",
      "command": "/etc/sensu/plugins/handler-slack.rb -j slack-chinachu-fin",
      "filter": "action_create_only"
    },
    "slack-chinachu-err": {
      "type": "pipe",
      "command": "/etc/sensu/plugins/handler-slack.rb -j slack-chinachu-err",
      "filter": "action_create_only"
    }
  },
  "slack-chinachu-record": {
    "webhook_url": "https://hooks.slack.com/services/○○",  <----ここに webhook用のアドレスをいれる。
    "payload_template": "/etc/sensu/conf.d/slack_payload/attachement_chinachu-record.erb"
  },
  "slack-chinachu-fin": {
    "webhook_url": "https://hooks.slack.com/services/○○",  <----ここに webhook用のアドレスをいれる。
    "payload_template": "/etc/sensu/conf.d/slack_payload/attachement_chinachu-fin.erb"
  },
  "slack-chinachu-err": {
    "webhook_url": "https://hooks.slack.com/services/○○",  <----ここに webhook用のアドレスをいれる。
    "payload_template": "/etc/sensu/conf.d/slack_payload/attachement_chinachu-err.erb"
  }
}
```
- handler-slack-chinachu.jsonのポイント
    - そのままだとログ出力でアラート検知した後に、復旧通知まで来てしまうので filter設定をいれてる。
    - payload_templateで細かい通知内容を定義してる。
    - erbファイルは絶対パスで記載すること。


```shell-session:attachement_chinachu-record.erb
{
  "channel": "#○○", <---- ここにチャンネル名をいれる。
  "username": "<%= @event["client"]["name"] %>",
  "attachments": [
    {
      "fallback": "テレビの録画を開始しました",
      "pretext": "sensuよりメッセージです。録画開始しました。",
      "title": "chinachu dashboard",
      "title_link": "http://192.168.1.30:10000/#!/dashboard/top/",
      "fields": [
          {
             "title": "action",
             "value": "<%= @event["action"] %>",
             "short": true 
          },
          {
             "title": "name",
             "value": "<%= @event["check"]["name"] %>",
             "short": true 
          },
          {
             "title": "output",
             "value": "<%= @event["check"]["output"] %>",
             "short": false
          }
      ],
      "color": "warning"
    }
  ]
}
```
- attachement_chinachu-record.erbのポイント
    - eventから変数を取得し、通知内容に反映している。
    - outputはvalueにしか入れれない。textには入れれないので注意。

```shell-session:filter.json
{
  "filters": {
    "action_create_only": {
      "negate": false,
      "attributes": {
          "action": "create"
      }
    }
  }
}
```
- attachement_chinachu-record.erbのポイント
    - eventのattributesの中にあるactionが、createのやつだけ通すフィルタ。
    - 復旧通知だけ通したければ、resolveにすればよい。

## sensuクライアント側(chinachu側)
```shell-session:/etc/sensu配下
$ tree
.
├── conf.d
│   ├── client.json
│   ├── rabbitmq.json
│   └── transport.json
├── config.json
├── extensions
└── plugins
```

### ポイント
- ローカルで稼働するためのcheck-log.rb を入れておく