PromQL基礎・クエリ実践
はじめに
Part 3-1では、4つのメトリクスタイプを学びました。ここからは、収集したメトリクスを効果的にクエリするための言語「PromQL(Prometheus Query Language)」を学びます。PromQLを習得することで、メトリクスから価値のある情報を引き出し、Grafanaでの可視化やアラート定義に活かせるようになります。
PromQL基本文法
セレクタと時系列の指定
PromQLの最も基本的な形は、メトリクス名またはラベルマッチで時系列を指定することです。
# メトリクス名だけで指定
http_request_total
# ラベルで条件を絞り込み
http_request_total{job="api"}
# 複数のラベルで指定
http_request_total{job="api", method="GET"}ラベルマッチには4つの演算子があります。
=: 完全一致(例:method="GET")!=: 完全不一致(例:status!="200")=~: 正規表現マッチ(例:status=~"[45]..")!~: 正規表現否定(例:endpoint!~"/admin.*")
# 複数ジョブを正規表現で指定
http_request_total{job=~"api|web"}
# "api"を含まないエンドポイント
http_request_total{endpoint!~".*api.*"}レンジベクトルとインスタントベクトル
PromQLには2つの時系列データ表現があります。
インスタントベクトルは最新の1つの値を表します。上記の例はすべてインスタントベクトル。
レンジベクトルは過去の時間範囲のデータを表します。括弧内に期間を指定します。
# 過去5分間のデータ
http_request_total[5m]
# 過去1時間のデータ
memory_usage_bytes[1h]レンジベクトルはデータの時間範囲を表すため、単独では1つの値を返せません。集計関数(rate()、avg_over_time()など)で処理してインスタントベクトルに変換し、初めてグラフ化や計算に使えるようになります。
基本的なクエリパターン
パターン1:単純な時系列取得
# サーバーの現在のメモリ使用量
memory_usage_bytes{instance="server1"}このクエリは、指定インスタンスの最新のメモリ使用量を返します。Grafana上でグラフ化すると、その時点の値が表示されます。
パターン2:ラベル条件での絞り込み
# ステータスコード200のリクエスト数
http_request_total{status="200"}単一のラベル値で絞り込む場合は = を使います。複数の値から選ぶ場合は正規表現 =~ が便利です。
# ステータスコード4xxと5xxのリクエスト
http_request_total{status=~"[45].."}パターン3:集計関数による計算
# 過去5分間のリクエスト数の増加率(リクエスト/秒)
rate(http_request_total[5m])rate() 関数は、Counterメトリクスの時間当たりの変化率を計算します。ほぼすべてのCounter型メトリクスは rate() で処理するのが標準です。
パターン4:複数時系列の集約
# 全インスタンスのメモリ使用量の合計
sum(memory_usage_bytes)
# インスタンスごとのメモリ使用量の平均(ラベルごとに集約)
avg(memory_usage_bytes) by (instance)sum()、avg()、max()、min() などの集計関数で、複数のラベル値を持つ時系列を集約できます。デフォルトではすべての時系列が1つの値に集約されますが、by() 句を使うことで、指定したラベルごとに別々の値として計算できます。
時系列データの加工
増加量の計算
# 過去1時間でのリクエスト数の増加量
increase(http_request_total[1h])increase() は rate() に似ていますが、「単位時間あたりの増加率」ではなく「期間内の総増加量」を計算します。
増分差の計算
# 最新値と1時間前の値の差
delta(temperature_celsius offset 1h)delta() は期間内の増減量を計算します。Gauge型メトリクスに対して、時間経過による変化量を知りたい場合に使われます。
時系列の平滑化
# 過去5分間のCPU使用率の移動平均
avg_over_time(cpu_usage_percent[5m])avg_over_time() は期間内の平均値を計算し、ノイズの多いメトリクスを平滑化するのに便利です。他に max_over_time() や min_over_time() があります。
複合クエリと応用
複数メトリクスの結合
# エラー率(エラー数 ÷ 全リクエスト数)
rate(http_request_total{status="500"}[5m]) / rate(http_request_total[5m])分子と分母の時系列がラベル構造を共有していれば、演算結果は自動的に合致するラベルで集約されます。
時間軸での比較
# 現在と1日前のメトリクスを比較
cpu_usage_percent / (cpu_usage_percent offset 24h)offset で過去のデータとの差分を計算できます。前週比や前月比などの分析に便利です。
条件分岐
# CPU使用率が80%を超えたら1、以下なら0
cpu_usage_percent > 80比較演算(>、<、==、!=)は、マッチした時系列に1を、マッチしなかったら0を返します。この結果をアラート条件として使うことで、閾値に基づく監視ができます。
よくある落とし穴とベストプラクティス
1. ラベルマッチの正規表現が遅い
# 避けるべき: ワイルドカード
http_request_total{endpoint=~".*api.*"}
# 推奨: 固定文字列を最初に置く
http_request_total{endpoint=~"^/api/.*"}正規表現はシンプルに保つことがPrometheuサーバーの負荷を減らします。
2. クエリ時のカーディナリティ管理
メトリクス定義時にラベルカーディナリティに注意することが重要ですが、クエリ段階でも同様です。不必要に細かいラベルで by() 句を使うと、Prometheusサーバーが数千以上の時系列を計算することになり、パフォーマンスが低下します。
# 避けるべき: ユーザーIDやタイムスタンプなど、高カーディナリティラベルでの集約
sum(http_request_total) by (user_id, timestamp, method, endpoint)
# 推奨: 必要な粒度に限定(通常は method や endpoint など固定的なラベルのみ)
sum(http_request_total) by (method, endpoint)3. rate()とincrease()の使い分け
Counterメトリクスの分析では、ほぼ常に rate() を使い、「単位時間あたり」の値を扱うのが標準です。increase() は「期間内の総増加量」が必要な特殊なケースに限定されます。
4. レスポンス時間の計算誤り
# 誤り: 時系列の平均(値そのものが異なるため意味不明)
avg(request_duration_seconds)
# 正解: Histogramを使い、パーセンタイルを計算
histogram_quantile(0.95, rate(request_duration_seconds_bucket[5m]))レスポンス時間のような「分布を持つ」メトリクスは、単純な平均ではなく、Histogramのパーセンタイル計算で分析します。
次のステップ
ここまで、PromQLの基本から応用パターンまでを学びました。次のPart 3-3では、これらのPromQLクエリをGrafanaで可視化し、実運用的なダッシュボードを構築する方法を学びます。PromQLとGrafanaを組み合わせることで、メトリクス活用の全体像が完成します。
ナビゲーション
前のパート:Part 3-1 - メトリクスの種類と理解