ローファイ日記

出てくるコード片、ぼくが書いたものは断りがない場合 MIT License としています http://udzura.mit-license.org/

PrometheusのExporter周りをまとめる

Mackerelの3周年(おめでとうございます!)、OSSではPrometheusの隆盛もあり、監視やモニタリング周りが話題になっているのを観測している。皆さんは、監視されていますか?

個人的にも最近はロリポップ!マネージドクラウド周りの開発などでPrometheusを触っているので、今日はPrometheusの肝とも言えるExporterに関してまとめる。

Prometheusその他監視周りについて、以前、スライドも作りはしたが、割と自分向けのメモ書きに毛が生えたような感じではあったので、もう少し詳細なメモ書きを残すなど。

Exporterの選択肢について

既存Exporter

基本的に、Prometheusのコミュニティは強く、たいていの監視には既存のExporterが存在する。なのでまずはWikiのリストをチェックするのが良さそう。

prometheus.io

その中でもGitHubprometheusオーガニゼーションにあるexporterは、公式ということでメンテも活発な印象を受ける。node_exporterが代表的。また、後述する自作時の実装のサンプルとしても非常に参考になる。

また、興味深い例として、Kubernetesのように直接Prometheus互換のExporterを実装しているミドルや基盤ソフトウェア、カーネルFreeBSDすごい...)も存在するので、そういうものについてはいきなりPrometheusと連携できて便利そう。

Pushgateway

Pushgatewayは、以下のような挙動をするExporter。

  • 何かイベントが起こったらPushgatewayにパラメータをプッシュする
  • PrometheusはPushgatewayのExporterエンドポイントからメトリックを取る

github.com

挙動を軽く試してみる。Dockerで持ってくる。

docker pull prom/pushgateway
docker run -d -p 9091:9091 prom/pushgateway

値を突っ込むとmetricとして取得できることがわかる。

$ echo "wanted_money_by_trillion_yen 5000.0" | \
>   curl --data-binary @- http://localhost:9091/metrics/job/example/wanter/udzura
$ curl -s localhost:9091/metrics | grep trillion
# TYPE wanted_money_by_trillion_yen untyped
wanted_money_by_trillion_yen{instance="",job="example",wanter="udzura"} 5000

ただし、想定している唯一の用途として、「サービスレベルでのバッチ処理の結果などのキャプチャ」という旨が書いてある。もっと色々と使えそうに見えるが、この「When to use the Pushgateway」に想定される各種用途での問題点が整理されているし、READMEにも「アグリゲータや分散カウンターではない」とされているので、あまりハックした使い方はしない方がいいかもしれない。

mtail

github.com

mtailは、googleリポジトリで公開されている強靭なtailで、具体的には、DSLに従ってログをパース、集計し、その結果をそのままExportまでしてくれる強いコマンド。

Nginxの例などGitHubに散見される。検索して出てきたものだが、抜粋してみる。

github.com

counter http_requests_total by vhost, method, code, content_type
# ...

/^/ +
/(?P<vhost>[0-9A-Za-z\.\-:]+) / +
/(?P<remote_addr>[0-9A-Za-z\.\-:]+) / +
/- / +
/(?P<remote_user>[0-9A-Za-z\-]+) / +
/(?P<time_local>\[\d{2}\/\w{3}\/\d{4}:\d{2}:\d{2}:\d{2} \+\d{4}\]) / +
/"(?P<request_method>[A-Z]+) (?P<request_uri>\S+) (?P<http_version>HTTP\/[0-9\.]+)" / +
/(?P<status>\d{3}) / +
/(?P<bytes_sent>\d+) / +
/(?P<request_seconds>\d+)\.(?P<request_milliseconds>\d+) / +
/"(?P<http_referer>\S+)" / +
/"(?P<http_user_agent>[[:print:]]+)" / +
/"(?P<content_type>[^;]+)(;.*)?"/ +
/$/ {
  http_requests_total[$vhost][tolower($request_method)][$status][$content_type]++
  http_request_duration_milliseconds_sum[$vhost][tolower($request_method)][$status][$content_type] += $request_seconds * 1000 + $request_milliseconds
  http_response_size_bytes_sum[$vhost][tolower($request_method)][$status][$content_type] += $bytes_sent
}

こういう正規表現、個人的にも既視感があるのだけれど、たとえばFluentdのin_tailのサンプルのようにも思える。なので、頑張れば色々やれるという雰囲気は感じ取っていただけたと思います...。

手元でも動かしてみる。ラインカウンターの例。

docker pull jaymedh/docker-mtail
cat test.mtail
counter syslog_line_count
/$/ {
  syslog_line_count++
}

docker run -p3903:3903 -d --rm -v`pwd`:/progs -v/var/log:/var/log -ti jaymedh/docker-mtail -progs=/progs/test.mtail -logs=/var/log/syslog

syslogが太るたびに行数がカウントされていくのを観察できる。

$ curl localhost:3903/metrics
# TYPE syslog_line_count counter
syslog_line_count{prog="test.mtail",instance="515dbe3601f7"} 12
$ curl localhost:3903/metrics
# TYPE syslog_line_count counter
syslog_line_count{prog="test.mtail",instance="515dbe3601f7"} 16
$ curl localhost:3903/metrics
# TYPE syslog_line_count counter
syslog_line_count{prog="test.mtail",instance="515dbe3601f7"} 36

自作

ここまでの既存ソリューションでも取れないような値であれば、自作を検討する必要がある。

Exporter自作に関しても、各言語でライブラリがあるようだが、やっぱりGoで書くのが一番良さそうに思われる。

Goで書く場合、Prometheus提供のライブラリを使うと、必要なインターフェースだけ実装すれば動かせるようになるので比較的楽。

具体的には、以下のインターフェースを実装する。Godoc

type prometheus.Collector interface {
    Describe(chan<- *prometheus.Desc)
    Collect(chan<- prometheus.Metric)
}

ご覧の通り、チャンネルを引数に取る関数で、そこにMetricインタフェースを実装した構造体を投入していけば集計してくれる(し、簡単な集計なら prometheus.MustNewConstMetric() を使える)。すなわち集計処理が非同期になってくれるので良い。

この辺、コードを見るのが一番早いと思うのでPrometheus公式のConsul Exporterのポインタを示す。

github.com

また、拙作(色々調整をまだできていない...)、cgroupのpidsコントローラーの値をExportするサンプルも晒す。

github.com

いざ実装したり公開する場合は、公式にガイドもあるので一読をお勧めする。

prometheus.io

総括

Prometheusのカスタムメトリックは、要するにHTTPサーバを実装しないといけないので敷居が高い印象もあるかもしれない。とはいえ、エコシステムが強く、コードを書かなくてもDSLでどうにかできたり、あるいはいざ実装するときもある程度レールが敷かれている。

[PR]

そういえば東京でしゃべります。監視というか相変わらずコンテナの話をします。まだかなり枠がありますので是非。

connpass.com

というか、参加者の一部は、僕の話を聞きに来たというより"""圧"""をかけに来たのではないかという説もありますので、圧をかけられる僕を見に来てください。

また、Geeks Who Drinkにも再びお招きいただきました(そのうち更新されるでしょう)。こっちでは上掲のスライドのうちで、コンテナに特化したことをまとめ直して喋ろうと思います。

nulab.connpass.com

そーだいさん先輩から圧をかけられる僕を見に来てください...!!!!231。