こんにちは。オブザーバビリティの深淵へようこそ。
システムが「動いている」だけでは不十分な時代になりました。今、私たちエンジニアに求められているのは、システムの「鼓動」を正確に聞き取り、未来の不調を予感することです。そのための最強の聴診器がPrometheusであり、その聴診器から流れてくる複雑な音を意味のある情報に変える魔法の呪文がPromQL(Prometheus Query Language)です。
「PromQLは難しそう」「関数の使い分けがわからない」と足踏みしていませんか? 大丈夫です。コツさえ掴めれば、これほど論理的で美しい言語はありません。
今回は、数々の修羅場を監視の力で解決してきた私が、PromQLの「本質」を初心者の方にも分かりやすく、かつ現場で即戦力として使えるレベルまで引き上げるガイドをお届けします。これをマスターすれば、あなたの運用監視は「勘」から「科学」へと進化しますよ。
—
1. PromQLの正体と、データを形作る4つの型
Prometheusが扱うデータは、すべて「時系列データ(Time Series)」です。メトリクス名があり、それを修飾するラベルがあり、値がある。PromQLはこのデータを自由自在に切り出すための言語です。
まず、PromQLを扱う上で絶対に避けて通れない「データ型」を理解しましょう。
- Instant Vector(瞬時ベクトル): 「今この瞬間」の値を、各時系列ごとに1つだけ持つ集合。グラフを描く時の「点」になります。
- Range Vector(範囲ベクトル): 「過去5分間」のように、一定期間の値を複数持っている集合。関数の計算材料になります。
- Scalar(スカラー): 単なる数値。
- String(文字列): あまり使いませんが、ラベルの指定などで登場します。
ここが肝心:
ダッシュボードにグラフを描画できるのはInstant Vectorだけです。Range Vectorはそのままではグラフになりません。後述する関数を使って「加工」する必要があります。
—
2. 瞬時ベクトル vs 範囲ベクトル:何が違うのか?
ここが初心者が最初につまずくポイントです。しかし、視覚的に考えれば簡単です。
瞬時ベクトル (Instant Vector)
シンプルにメトリクス名を書くだけ
http_requests_total
これは「今現在の、各エンドポイントごとのリクエスト総数」を返します。
範囲ベクトル (Range Vector)
末尾に [時間] をつける
http_requests_total[5m]
これは「過去5分間に計測されたすべてのデータポイント」を返します。
「5分間の平均を出したい」「5分間でどれだけ増えたか知りたい」という時、この `[5m]` が必要になります。
—
3. 現場で「これしか使わない」究極の関数 4選
PromQLには多くの関数がありますが、現場の8割は以下の4つで構成されています。これらを使いこなせれば、あなたも立派な監視エンジニアです。
① `rate()`:秒あたりの変化率(RPSなど)
最も重要です。カウンタ(増え続ける値)に対して使い、「1秒あたりどれくらい増えたか」を計算します。
過去5分間のデータに基づき、1秒あたりのリクエスト数(RPS)を計算
rate(http_requests_total[5m])
- プロの知見: `rate` はカウンタのリセット(プロセス再起動など)を自動で考慮してくれる優れものです。
② `irate()`:瞬時の変化率
`rate` が期間全体の平均を見るのに対し、`irate` は期間内の最後の2点だけを見て計算します。
非常に短期間の急激な変化を捉えたい場合
irate(http_requests_total[5m])
- プロの知見: グラフがギザギザになりやすいため、アラート設定には `rate`、調査時のスパイク確認には `irate` と使い分けるのが鉄則です。
③ `increase()`:期間中の増加量
「この1時間で何回エラーが起きたか?」を知りたい時に使います。
過去1時間で増えたエラー数
increase(http_errors_total[1h])
④ `sum by (…)`:集計とグループ化
Prometheusの真骨頂はラベルによる集計です。SQLの `GROUP BY` と同じです。
インスタンスごとではなく、パス(path)ごとにリクエスト数を合算する
sum by (path) (rate(http_requests_total[5m]))
—
4. 実戦!明日から使える「黄金のクエリ」サンプル
これらを組み合わせて、実際の運用でそのまま使えるクエリを作ってみましょう。
CPU使用率を計算する
`node_exporter` を使っている場合の定番です。
全体のCPU使用率(%)
idle(暇な時間)を引くことで、稼働率を算出
100 – (avg by (instance) (irate(node_cpu_seconds_total{mode=”idle”}[5m])) 100)
エラー率(Error Rate %)を算出する
「エラーの数」よりも「全体に対するエラーの割合」の方が、システムの健全性を表します。
500系エラーの割合(%)を算出
(
sum(rate(http_requests_total{status=~”5..”}[5m]))
/
sum(rate(http_requests_total[5m]))
) 100
- ポイント: `{status=~”5..”}` は正規表現によるマッチングです。
—
5. パフォーマンスを意識した「美しいクエリ」の書き方
最後に、Prometheusサーバーを悲鳴あげさせないための、プロの作法を伝授します。
1. ラベルで絞り込む: `rate({job=”api”}[5m])` のように、可能な限り早い段階でラベルフィルタリングを行い、計算対象の時系列を減らしてください。
2. 高カーディナリティを避ける: `user_id` のような、数万、数百万の種類がある値をラベルに入れたメトリクスを `sum` しようとすると、メモリを食いつぶします。
3. 範囲の指定([5m]など): スクレイプ(収集)間隔の少なくとも4倍以上を指定するのが定石です。15秒間隔で収集しているなら、`[1m]` 以上が安全です。
—
おわりに:オブザーバビリティの旅はここから始まる
PromQLは単なる検索言語ではなく、システムの健康状態を定義する「哲学」そのものです。
最初は `rate` と `sum by` だけで構いません。それだけで、今まで見えなかった「トラフィックの波」や「エラーの兆候」が、驚くほどクリアにダッシュボードに浮かび上がるはずです。
「このクエリで、チームの誰が、何を決断できるか?」
常にそれを自分に問いかけながら、クエリを磨いていってください。
もし迷ったら、いつでもこの記事に戻ってきてください。あなたの書く一行のクエリが、深夜の呼び出しを防ぎ、ユーザーに最高の体験を届ける鍵になります。
さあ、モニターの向こう側にある「真実」を掴みに行きましょう!応援していますよ。