MacのキーボードやマウスのログをKibanaで可視化する


[MacにKibanaとtd-agentをインストールする](http://qiita.com/edvakf@github/items/0b63ff71d32cafceb748)の続き。

Kibanaとか使ってみたいとは思ってるんだけど、流し込むログなんて無いし…と思っている人に贈る。

自分のパソコンのイベントログなら手元だけで完結するし、ログの量もそれなりにあって、データとしてもおもしろい。

## キーボードやマウスのログをsyslogに出すデーモンを作る

↓こういう50行ぐらいのプログラムを作った。

https://github.com/edvakf/macbooklog/blob/master/macbooklog.m

CGEventなんちゃらというのがMacの色々なイベントのコールバックを設定するインターフェイスで、aslなんちゃらというのがMacにおけるsyslogのラッパー。

これでコンパイルできる。

```
$ clang macbooklog.m -o macbooklog -framework Cocoa
```

または、[リポジトリ](https://github.com/edvakf/macbooklog)に `Makefile` を置いてあるので、

```
$ make
```

で良い。

**キーボードのログを取得するにはこれをrootで実行しないといけない。** （マウスだけならroot必要なし）

デーモンとして起動しておいてほしいので、plistを設置。

```
$ sudo cp macbooklog /usr/sbin/macbooklog
$ sudo cp macbooklog.plist /Library/LaunchDaemons/
```

デーモンを起動。

```
$ sudo launchctl load /Library/LaunchDaemons/macbooklog.plist
```

これで `/var/log/system.log` をtailすればログが見られる。

### キーコードも取得するには

[リポジトリ](https://github.com/edvakf/macbooklog)のコードのままではキーボードのイベントだけを出すようにしてて、キーコードをログに含めていない。含める場合はよしなにコメントを外したりすれば良いのだけど、キーログ出してるとパスワードを他人に知られる可能性があるので自己責任でやってね。

## syslog (ASL) の設定

上のままでも普通のsyslogにログが流れてくるが、1つ困ったことがあって、20秒以内に同じログがあった場合は

```
--- last message repeated 17 times ---
```

のようになってしまうらしい。(coalesceされるというらしい)

syslogの設定で、macbooklogの場合だけcoalesceをオフにしてついでに別のログファイルに出すようにしておこう。fluentdの設定でもそっちだけをtailすればいいので余計な処理しなくて良さそう。

ASLはsyslogのラッパー。`/etc/syslog.conf` とは別に `/etc/asl.conf` というのがある。両方使えるらしいが、asl.confのほうに設定がいくつか書いてあるのでそっちを使う。asl.confではログローテートの設定ができるのが便利。

`/etc/asl.conf` 自体に書いてしまうとOSのアップデートで上書きされる可能性があるため、 `/etc/asl/macbooklog` に↓のファイルを置く。

```
# write macbooklog's log to macbooklog.log and do not coalesce
? [= Facility macbooklog] claim only
* file /var/log/macbooklog.log file_max=1M all_max=5M coalesce=false
```

macbooklogのログは `/var/log/macbooklog.log` というファイルにかかれて、1MBごとにログローテートされて、全部で5MBになったら古いものから消される。coalesceはしないという意味。

あとはsyslogdを再起動。

```bash
$ sudo launchctl stop com.apple.syslogd
$ sudo launchctl start com.apple.syslogd
```

`/var/log/macbooklog.log` を見てみるとこんな感じにログが出ているはず。

```
Sep  6 10:25:32 Atsushis-MacBook-Pro.local macbooklog[22757] <Notice>: kCGEventKey:3
Sep  6 10:25:33 Atsushis-MacBook-Pro.local macbooklog[22757] <Notice>: kCGEventKey:36
Sep  6 10:25:33 Atsushis-MacBook-Pro.local macbooklog[22757] <Notice>: kCGEventMouseMoved
Sep  6 10:25:33 Atsushis-MacBook-Pro.local macbooklog[22757] <Notice>: kCGEventMouseMoved
Sep  6 10:25:33 Atsushis-MacBook-Pro.local macbooklog[22757] <Notice>: kCGEventMouseMoved
```

## 簡単にインストールできるようにした

ここまでのことを `make install` でやってくれるようにした。

```
$ sudo make install
cp macbooklog /usr/sbin/macbooklog
cp macbooklog.plist /Library/LaunchDaemons/macbooklog.plist
launchctl load /Library/LaunchDaemons/macbooklog.plist
launchctl stop macbooklog
launchctl start macbooklog
cp macbooklog.asl.conf /etc/asl/macbooklog
launchctl stop com.apple.syslogd
launchctl start com.apple.syslogd
```

アンインストールは `make uninstall`

```
$ sudo make uninstall
rm /usr/sbin/macbooklog
launchctl unload /Library/LaunchDaemons/macbooklog.plist
rm /Library/LaunchDaemons/macbooklog.plist
rm /etc/asl/macbooklog
launchctl stop com.apple.syslogd
launchctl start com.apple.syslogd
```

## fluentdでsyslogを読む

td-agentを使っているので、`/etc/td-agent/td-agent.conf` に以下のように書くと、syslogが読める。

```
<source>
  type tail
  path /var/log/macbooklog.log
  pos_file /tmp/macbooklog.pos
  tag macbooklog
  format syslog
</source>
```

ElasticSearchに流すところまで含めると、こうなった。

```
<source>
  type tail
  path /var/log/macbooklog.log
  pos_file /tmp/macbooklog.pos
  tag macbooklog
  format syslog
</source>

<match macbooklog>
  type rewrite_tag_filter
  rewriterule1 message ^kCGEventKey             macbooklog.key
  rewriterule2 message ^kCGEventScrollWheel$    raw_macbooklog.mouse.scroll
  rewriterule3 message ^kCGEventMouseMoved$     raw_macbooklog.mouse.move
  rewriterule4 message ^kCGEventLeftMouseDown$  macbooklog.mouse.click
  rewriterule5 message ^kCGEventRightMouseDown$ macbooklog.mouse.click
</match>

<match raw_macbooklog.**>
  type sampling_filter
  interval 10
  remove_prefix raw_macbooklog
  add_prefix macbooklog
</match>

<match macbooklog.**>
  type elasticsearch
  host localhost
  port 9200
  logstash_format true
  logstash_prefix macbooklog
  include_tag_key true
  tag_key event
</match>
```

マウスのログがキーボードに比べてだいぶ多いので、適当にサンプリングしてやる。（上の設定では10分の1）

fluent-plugin-sampling-filterが必要。

```
sudo /opt/td-agent/embedded/bin/fluent-gem install fluent-plugin-sampling-filter
```

キーコードもログに含める場合は fluent-plugin-parser を使ってよしなにやる。（[リポジトリ](https://github.com/edvakf/macbooklog)のREADMEに設定例を書いておいた）

## 以上

Kibanaのデフォルトのlogstash形式ダッシュボードの設定をいい感じに弄ると、簡単にこういうグラフが作れる。

![Kibana_3_-_macbooklog.png](https://qiita-image-store.s3.amazonaws.com/0/5978/f1fcb48f-963a-b862-12d1-bfa5a5fc7d08.png "Kibana_3_-_macbooklog.png")

いつ寝てるのか一目瞭然！

午前中はvimでコードを書いてたのでJKLが多かった。

これだけだとElasticSearchに溜まり続けるので、古いログは消したりしないといけない。https://github.com/elasticsearch/curator を検討してみましょう。