Carpe Diem

備忘録

PrometheusがStatsDより優れているところ

概要

新しい技術というのは既存の技術にある課題を解決するために生まれてきます。

はStatsD&Graphiteを中心に説明されており、同時期に読んだ

と比較して、メトリクス系ツールの古株であるStatsDより後発のPrometheusは、StatsD&Graphiteのどんな課題を解決しているかをまとめます。

Prometheusが優れているところ

大きく以下の3つが良いと思います。

  • ラベルベースの柔軟なメトリクス名
  • データ欠損しても推測可能
  • 充実したExporter

ラベルベースの柔軟なメトリクス名

メトリクス名など自由に設定できる名称は往々にして負債となりがちです。
あらかじめきちんとルール決めしておかないと乱立しますし、仮に決めても人の流入出でその文化が廃れるケースもよくあります。

StatsD

StatsDではドットベースでメトリクス名を決めます。

<myservice>.<request_type>.200.count
ex) app.login.200.count

Graphiteで集計する時は以下のようにします。

sumSeries(*.*.200.count)

しかしドットベースの名称は順序や命名を知っていないと集計クエリが効かなくなったりしてしまいます
また新しい要素を付け加えるのも大変なため拡張性に欠けます。

# 新しい要素。インスタンス毎に取得したくなったため。しかし前述の集計クエリが使えない。
instance.service_name.request_type
# 異なる順序。別の人が定義してしまう。↑と同じはずが集計クエリが効かなくなる。
service_name.instance.request_type

Prometheus

一方Prometheusはラベルベースです。

http_requests{service="myservice",request="request_type",response_code="200"}
ex) http_requests{service="app",request="login",response_code="200"}

とすればよく、順序を気にする必要はありません
また集計するためのPromQLは柔軟で、

sum(rate(http_requests{response_code=200"}[1m]))

新しい要素が増えても既存のクエリが使えますし、新しい要素でフィルタしたい場合は

sum(rate(http_requests{instance="host001",response_code=200"}[1m]))

のようにすればよいです。

データ欠損しても推測可能

Pull型にしろPush型にしろ、ネットワークやプロセスなどの影響でデータ欠損することは往々にしてあります。
しかしPrometheusは仮に欠損しても推測可能でFault tolerantなツールです。

StatsD

StatsDはその時点でのデータを送信すると、内部カウンタをリセットします。
例として

Time 10:01 10:02 10:03 10:04 10:05 10:06
5xxエラー数 1 3 198 251 2 1

といったエラー数で、運悪く10:03, 10:04にネットワークの不調でデータ送信に失敗したとします。

Time 10:01 10:02 10:03 10:04 10:05 10:06
5xxエラー数 1 3 NULL NULL 2 1

するとこのように、本来障害が起きたはずなのにデータ欠損によって検知することができなくなります

Prometheus

一方Prometheusは全てがカウンタベースになっています。

Time 10:01 10:02 10:03 10:04 10:05 10:06
Prometheusカウンタ 1 4 202 453 455 456
5xxエラー数 1 3 198 251 2 1

そのためこのようにリセットされず常に増えていきます。
エラーは以下のようにカウンタから算出される仕組みです。

 (3 - 1) / (10:02 - 10:01) = 2/60 = 0.033 errors/sec

仮に10:03, 10:04にネットワークの不調でデータ受信に失敗した場合

Time 10:01 10:02 10:03 10:04 10:05 10:06
Prometheusカウンタ 1 4 NULL NULL 455 456

となります。その期間のデータが無いのでスキップしますが、10:02〜10:05のエラーレートを測ることで

 (455 - 4) / (10:05 - 10:02) = 451/180 = 2.506 errors/sec

このようにカウンタベースなためエラーレートが急激に上がったことが検知できます。

CPU使用率についてもPrometheusはその時点の使用率を保持するのではなく、プロセスが使用したCPU時間を保持することで計算可能なカウンタデータとして保持しています。

充実したExporter

監視対象のミドルウェアが増えると段々運用負荷が高くなってきます。
また人によって粒度のことなる項目になってしまったり、ちゃんとしたルールを決めておかないと属人性が強くなり技術負債となりがちです。

StatsD

ミドルウェアAPIに応じて個人が開発し、StatsDホストに送信する仕組みも自前で作成しがちです。
またそれによってメトリクス名などが共通化されておらず、ダッシュボードも自作しがちです。

Prometheus

Exporters and integrations | Prometheus

こちらのリストに多数あるように、公式・コミュニティ主導のExporterが多数あります。
OSSとして公開されることでより一般的な粒度の監視項目へと成長します。
このExporterの存在によりメトリクス名も共通化されています。

また多くのExporterに対し、対応するGrafanaのダッシュボードが公開されているため、わざわざ自前でダッシュボードを作成する必要もありません。

grafana.com

まとめ

PrometheusがStatsD&Graphiteに比べて良いと思う点を挙げてみました。
他にもいくつか優位な点はありますが、大きくこの3つが選定する上で重要と感じました。

参考