運用しやすい Datadog カスタムメトリクス収集方法

# 概要
Datadog でカスタムメトリクスを収集したい場合には、カスタムチェックを書いて Docker コンテナとしてパッケージングしてデプロイすると運用しやすいよ、という話。

# 背景
Datadog を利用していると、Datadog でサポートされていないものをモニタリングし、そのデータを Datadog に入れたいというケースが出てくる。

自分の例だと [Resque](https://github.com/resque/resque) という Redis を利用した Ruby 製のバッググラウンドジョブシステムに関するメトリクスを収集したかったが、公式にはサポートされていなかった。

Datadog にカスタムメトリクスを送る方法は 2 種類あり、

- Datadog カスタムチェックを書く
- DogStatsD を利用したメトリクス収集/送信スクリプトを書く

それぞれやり方が公式ドキュメントに載っている

- [Writing an Agent Check](http://docs.datadoghq.com/guides/agent_checks/)
- [Sending Metrics with DogStatsD](http://docs.datadoghq.com/guides/metrics/) 

自分は、運用面を考慮するとほとんどのケースで前者の方が良いと思っている。

## DogStatsD を利用したメトリクス収集/送信スクリプトの問題点
DogStatsD を利用したメトリクス収集/送信スクリプトを書く方法は手軽だが、運用が煩雑になる。

まずそのスクリプトコードはどのリポジトリで管理するのか？ すぐ思いつくのは Gist である。しかし、スクリプトが増えてきたり、PullRequest&Review したいと思ったら Gist はダメだ。では専用のリポジトリを作ろうとなる。

cron 運用やジョブ管理システムがちゃんと整備されてる環境であれば、そこで実行するコードを管理しているリポジトリがあると思う。そこに置くのは悪くない。ただ、実行するのはシェルスクリプトではなく Python/Ruby スクリプトだ。 cron/ジョブ管理システムサーバに Datadog クライアントライブラリをインストールする必要があるし、他のスクリプトとの依存関係が衝突したりすることもある。

例えば内製ミドルウェアがあったとして、それが 2, 3 つインスタンスがある場合、カスタムメトリクス収集ロジック自体は共通だが、接続先は違うというケースもある。そういう場合設定は別に切り出したい。それが cron/ジョブ管理システムで巻き取れるのか。

# 運用しやすいカスタムメトリクス収集方法
DogStatsD を利用したメトリクス収集/送信スクリプトを cron/ジョブ管理システムで定期実行するよりも、Datadog カスタムチェックを利用した方がいい理由は以下である:

- dd-agent 自体が定期実行の仕組みを持っている
- メトリクス収集ロジックと設定を分ける仕組みを持っている
- 別途 DogStatsD をインストールする必要がない

どうやってカスタムチェックを書くかを簡単に説明すると、dd-agent は `/etc/dd-agent/checks.d` 以下のチェックスクリプトを読み込んで定期実行するという仕組みになっており、それが Datadog ビルトインのスクリプトかどうかは関係ない。そして各チェックスクリプトに対応した設定を `/etc/dd-agent/conf.d` 以下の設定ファイルから読む。これもビルトインの設定ファイルかどうかも関係ない。

自分のケースを例に出すと、`/etc/dd-agent/checks.d/resque.py` と `/etc/dd-agent/conf.d/resque.yaml` を作ればいいということだ。詳しくは公式ドキュメント [Writing an Agent Check](http://docs.datadoghq.com/guides/agent_checks/) を参照。

では、自分が書いたカスタムチェックスクリプトと設定ファイルをどうデプロイすると良いか。自分のオススメは、公式 Docker コンテナ版 dd-agent をラップする方法だ。

まずは、カスタムチェックスクリプトを管理するリポジトリを作る。中身は簡略化するとこんな感じ。

```
$ tree
.
├── Dockerfile
├── README.md
├── checks.d
│   └── resque.py
├── conf.d
│   └── resque.yaml
└── docker-compose.yml

2 directories, 9 files
```

公式 Docker コンテナ版 dd-agent には、datadog-agent パッケージがインストールされていて、`/etc/dd-agent/checks.d/` も `/etc/dd-agent/conf.d` もあるので、それを継承したイメージをビルドする際に、カスタムチェックスクリプトを置くだけである。

```Dockerfile:Dockerfile
FROM datadog/docker-dd-agent:latest

COPY checks.d/resque.py /etc/dd-agent/checks.d/resque.py
COPY conf.d/resque.yaml.tmpl /etc/dd-agent/conf.d/resque.yaml
```

あとはこのイメージを元にしたコンテナをどこかのサーバ上で実行するだけ。
カスタムチェックスクリプトを更新したり、追加したりする際は、

0. PullRequest, Review
0. Test (Build, Deploy to staging)
0. Merge, Build, Deploy to production

というステップを踏めばよい。

# まとめ
この話は、要はアプリケーション内部からメトリクスを送信するケースでは DogStatsD を使うべきだが、内製ミドルウェアや未サポートのミドルウェア/SaaS のメトリクスを外部から収集するケースではカスタムチェックを使うべきという話で、ドキュメントもそういう意図で書いてあるように思う。

だけど Google で「Datadog custom metrics」と検索すると DogStatsD のドキュメントが上位に来るので、未サポートのミドルウェアのメトリクス収集したいというケースなのに、DogStatsD 使ってやろうというする人が結構いるんじゃないかな(自分も最初そうだった) ということもあって書いたみた。

あと、余談がいくつかあって。まず自分の場合はあのコンテナで以下のことも行っている。

- RDS や Elasticache インスタンスのネイティブモニタリング
- [Entrykit](http://qiita.com/spesnova/items/bae6406bf69d2dc6f88b) を使って、カスタムチェックの設定項目を環境変数経由で変更できるようにしてポータビリティを上げる

全サーバに配置してる dd-agent とは別物で、特定のプロダクト用にカスタムチェックや専用の設定を持たせた dd-agent として全体で 1 台起動している。カスタムチェックや専用の設定が必要なプロダクトが増えたらまた、専用 dd-agent が全体で 1 台増える、ということになる。

似たようなことをやっている例として Datadog のリーディングユーザである Stripe の例も紹介しておこう:

https://github.com/stripe/datadog-checks

この話が誰かの参考になればと思います :smiley: