MackerelでMac＆Bluetooth接続された周辺機器を監視してみる

クリスマスイブに書いた記事が途中で全部消えました。
というわけで、昨日はふて寝をしておりました・・・。

さて、気を取り直して！

開発に使うMacの負荷って気になったりしませんか？
キーボードやトラックパッドの充電が突然切れて困ったりしませんか？


![582bed14.png](https://qiita-image-store.s3.amazonaws.com/0/49238/6a553a7e-d827-8979-9524-ce887bf6ba93.png)

そんな悩みを持つ人のために、

「[Mackerel](https://mackerel.io/)を使って、**Macと周辺機器を監視して、電池が切れる前にアラームで通知しちゃおうぜ！**」

という素敵なお話です。

# Mackerelとは
エージェント常駐型のサーバ監視ツールです。
ホストのリソース状況などをグラフに可視化し、障害発生時には自動でアラートが記録されます。
作成されたアラートは、

* メール
* [Slack](https://slack.com/)

などと言った外部ツールと連携させ、通知することができます。
今回は、**Rubyを使ってオリジナルプラグインを作成**します。

# 監視項目
今回、監視する項目は以下の通りです。

* Mac
  * ファンの回転数
  * CPUの温度
  * バッテリーの温度
  * バッテリーの充電量
  * バッテリーのヘルスチェック
* Bluetooth接続された周辺機器
  * キーボードの充電量
  * トラックパットの充電量

それでは、プラグインを作成する前に、Mackerelをインストールしましょう。

# 事前準備

監視の通知をする[Slack](https://slack.com/)アカウントがない人は、アカウントやチームを作成しておきましょう。

次に、以下の記事の「MacにMackerelの導入！」項までを実施しましょう。

* [Mackerel（マカレル）を使って自分のMacを監視して、アラートが発生したらslackに通知させてみる](http://qiita.com/yn-misaki/items/8730797531b57fbad5fc)

「Mackerelの左メニューバー -> Hosts -> 監視対象のホストを選択」で以下の画面が見れるようになれば、事前準備完了です。

<img width="1035" alt="スクリーンショット 2016-12-24 13.43.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/49238/32ebfbc6-4c3a-7127-38db-973d1caeec39.png">

# プラグイン開発
## 基礎編
プラグイン開発は3Stepで終わります。

* 値を取得するプラグインを書く（Ruby）
* Mackerelの設定ファイルにプラグインを追加する

```sh:Mackerelの設定ファイルにプラグインの追記
$ vim /usr/local/etc/mackerel-agent.conf

# ファイルの最下部に追加
# command = "ruby <開発したプラグインのファイル場所>"
========================================
[plugin.metrics.hogehoge]
command = "/Users/yn-misaki/.rbenv/shims/ruby /Users/yn-misaki/dev/mackerel_plugin/hogehoge.rb"
========================================
```

`rbenv`でrubyを管理している方は、**rbenvのディレクトリを指定**、`rvmの`方は、**rvmのディレクトリを指定**しましょう。
バージョン管理していない方は、`ruby <開発したプラグインのファイル場所>`とそのまま書けばOKです。

また、`apikey`の前に、プラグイン設定を追記するとエラーが発生するので気をつけましょう。

* mackerel-agentを再起動する

```sh:mackerel-agentの再起動
$ launchctl stop homebrew.mxcl.mackerel-agent
$ launchctl start homebrew.mxcl.mackerel-agent
```

## Mac編
それでは、早速Macのプラグイン開発をします。
Linux系OSでは、`lm_sensors`を使うと簡単に取得できます。

* [LinuxでCPUの温度を取得する](http://qiita.com/koara-local/items/1fac13704123717f5cc8)

Macでは、残念ながら使えません・・・。
今回は、[iStats](https://github.com/Chris911/iStats)というgemを利用し、Macの監視項目の値を取得します。

```sh:iStatsのインストール
$ gem install iStats
```

gemのインストールが終わった後、CPUの温度が取得できることを確かめます。

```sh:iStatsでCPU温度を表示してみる
$ istats cpu

=========================
CPU temp: 40.88°C ▁▂▃▅▆▇    ← この温度だけ使いたい！
=========================
```

こんな感じで親切に表示してくれます。
`40.88`の部分だけ使いたいので、温度を測定するメソッドだけ使います。


では、実際に`cpu.rb`という名前でプラグインを作成します。

```rb:Macの充電量を取得するプラグイン
require 'iStats'
require 'json'

# iStatsのCPUに関する状態を取得するモジュールをinclude
include CPU_STATS

# Mackerelで表示するラベル、表の名前とかの設定
if ENV["MACKEREL_AGENT_PLUGIN_META"] == '1'
  meta = {
    :graphs => {
      'cpu' => {
        :label   => 'CPU Temp (℃)',
        :unit    => 'integer',
        :metrics => [
          {
            :name  => 'temp',
            :label => 'cpu'
          },
        ]
      }
    }
  }

  puts '# mackerel-agent-plugin'
  puts meta.to_json
  exit 0
end

# iStatsのメソッドget_cpu_tempでCPU温度を取得
puts [ 'cpu.temp',  get_cpu_temp.to_i, Time.now.to_i ].join("\t")
```

作成が終わった後、設定ファイルに`cpu.rb`を追記します。

```sh:設定ファイルをに追記する
$ vim /usr/local/etc/mackerel-agent.conf

# ファイルの最下部に追加
========================================
[plugin.metrics.cpu]
command = "/Users/yn-misaki/.rbenv/shims/ruby /Users/yn-misaki/dev/mackerel_plugin/cpu.rb"
========================================
```

続いて、mackerel-agentを再起動します。

```sh:mackerel-agentを再起動
$ launchctl stop homebrew.mxcl.mackerel-agent
$ launchctl start homebrew.mxcl.mackerel-agent
```

ログを確認して、エラーが出ていないことを確認します

```sh:ログの確認
$ tail -f /usr/local/var/log/mackerel-agent.log
```

続いて、Mackerelのページでカスタムメトリクスが追加されていることを確認します。
5分くらい待つと、グラフが描画されます。
詳しくは、iStatsのコードを読んでください・・・（心が折れました）

<img width="341" alt="スクリーンショット 2016-12-25 22.35.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/49238/44dac6b4-97d7-3c29-97a5-0a0f52fb0001.png">

`include`するモジュールと、メソッドを変更するだけで各監視項目を取得することができます。

<img width="1030" alt="スクリーンショット 2016-12-25 22.38.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/49238/03bf3569-c9dc-6f12-8e07-ced9b2de7393.png">


## 周辺機器編
続いて、Bluetooth接続されたキーボードとキーボードの充電残量を測ります。
Macに標準装備されている`ioreg`コマンドを使います。
このコマンドは、IOKit（ハードウェア寄りのシステム）に関する情報を取得することができます。

```sh:キーボードに関する情報を取得する
$ ioreg -c AppleBluetoothHIDKeyboard

# トラックパットの場合
# $ ioreg -c BNBTrackpadDevice
```

`-c`オプションを使うことで、指定したデバイスのプロパティ情報を取得できます。
情報量があまりにも多いので、実際に使うときは`grep`をします。（`ioreg -c AppleBluetoothHIDKeyboard | grep BatteryPercent`）


コマンドの使い方がわかったところで、プラグインを書いてみます。

```rb:キーボードの充電量を取得するプラグイン
require 'json'

# ioregでキーボードのバッテリー情報を取得し、整形するワンライナー・・・。
battery = `ioreg -c AppleBluetoothHIDKeyboard | grep BatteryPercent | grep -v ExtendedFeatures`.gsub(/[[:blank:]]|\|/, '').match(/"BatteryPercent"=(\d+)/)[1]

if ENV["MACKEREL_AGENT_PLUGIN_META"] == '1'
  meta = {
    graphs: {
      'keybord' => {
        :label   => 'Keyboard Battery Charge（%）',
        :unit    => 'percentage',
        :metrics => [
          {
            name: 'charge',
            label: 'Battery-0',
            stacked: false       # stackedをfalseに指定すると、積み上げグラフになります
          },
        ]
      }
    }
  }

  puts '# mackerel-agent-plugin'
  puts meta.to_json
  exit 0
end

puts [ 'keybord.battery_charge', battery, Time.now.to_i ].join("\t")
```

通常のコマンドを実行する場合、`（バッククオート）で囲むことで、Ruby上でもコマンドを実行することができます。
あとは、mackerel-agentの再起動をして・・・エラーが出ていないことをログから確認します。
（Bluetooth接続されていないと、値は取得できません）

こんな感じでグラフが描画されます。

![図1.png](https://qiita-image-store.s3.amazonaws.com/0/49238/bba183dd-49d2-e904-1146-3f1d176c013d.png)


# 監視＆Slackの設定

下記の「監視ルールを入れる」と「slackに通知させてみよう」項目を参考にして設定しましょう。

* [Mackerel（マカレル）を使って自分のMacを監視して、アラートが発生したらslackに通知させてみる](http://qiita.com/yn-misaki/items/8730797531b57fbad5fc)


こんな感じで通知がきます！これで、充電を忘れなくなります！
![図1.png](https://qiita-image-store.s3.amazonaws.com/0/49238/15f8b56f-7637-4989-49e3-5fbbb54c40c0.png)



# まとめ
Mackerelのプラグインを作成し、MacとBuetooth接続された周辺機器を監視できるようにしました。
特に、充電周りはSlackと連携すると非常に便利なので、ぜひ使ってみてください！！

## 参考
* [Mackerel（マカレル）を使って自分のMacを監視して、アラートが発生したらslackに通知させてみる](http://qiita.com/yn-misaki/items/8730797531b57fbad5fc)
* [ホストのカスタムメトリックを投稿する - Mackerel ヘルプ](https://mackerel.io/ja/docs/entry/advanced/custom-metrics)