コンテンツにスキップ

PromQL クイックスタート

PromQLPrometheus モニタリングシステム のクエリ言語であり、シンプルな構文と強力な機能を備えています。従来の SQL 言語とは異なり、PromQL の構文構造は非常に独特です。

この記事では、PromQL の一般的なクエリの使用方法を紹介します。

PromQL で時系列を選択する

PromQL では、時系列を選択するのは非常に簡単で、系列名を直接記述するだけです。例えば、以下のクエリは、node_network_receive_bytes_total という名前のすべての時系列を返します。

node_network_receive_bytes_total

この名前は node_exporter メトリクス に対応し、さまざまなネットワークインターフェースが受信したバイト数を記録します。単純なクエリでは、例えば eth0eth1eth2 のネットワークインターフェースに対して、次のようなラベルを持つ時系列が返される可能性があります。

node_network_receive_bytes_total{device="eth0"}
node_network_receive_bytes_total{device="eth1"}
node_network_receive_bytes_total{device="eth2"}

異なるラベルは中括弧で囲まれます。例:{device="eth0"}{device="eth1"}{device="eth2"}

メジャーメント

Guance では、すべてのメトリクスはメジャーメントに属し、メジャーメント単位でメトリクスのライフサイクルを管理します。一方、Prometheus にはメジャーメントという概念はありません。Datakit を介してデータを報告する際には、手動でメジャーメントを設定するか、プレフィックスに基づいて自動生成することができます。

node_network_receive_bytes_total メトリクスを例にとると、Datakit の自動ルールで生成すると仮定した場合、このメトリクスはメジャーメントとフィールドの 2 つの部分に分割され、それぞれ nodenetwork_receive_bytes_total になります。

クエリ時にも若干の変更があります。引き続き異なるネットワークインターフェースを例にとります。

node:network_receive_bytes_total{device="eth0"}
node:network_receive_bytes_total{device="eth1"}
node:network_receive_bytes_total{device="eth2"}

メトリクス名のフィルタ形式が measurement:field になり、コロンで接続されていることがわかります。

ラベルによるフィルタリング

上記の例のように、単一のメトリクス名が異なるラベルセットを持つ複数の時系列に対応する場合があります。{device="eth1"} にのみ一致する時系列を選択するにはどうすればよいでしょうか。クエリで必要なラベルを指定するだけです。

node:network_receive_bytes_total{device="eth1"}

eth1 以外のデバイスのすべての時系列を選択する場合は、クエリ内の =!= に置き換えます。

node:network_receive_bytes_total{device!="eth1"}

eth で始まるデバイスの時系列を選択するにはどうすればよいでしょうか。正規表現を使用します。

node:network_receive_bytes_total{device=~"eth.+"}

フィルターには、Go 互換の任意の正規表現(RE2 とも呼ばれます)を含めることができます。

eth で始まらないデバイスのすべての時系列を選択するには、=~!~ に置き換えます。

node:network_receive_bytes_total{device!~"eth.+"}

複数ラベルによるフィルタリング

ラベルフィルターを組み合わせて使用できます。例えば、以下のクエリは、eth で始まるデバイスの node42:9100 インスタンス上の時系列のみを返します。

node:network_receive_bytes_total{instance="node42:9100", device=~"eth.+"}

ラベルフィルターは and 演算子で組み合わされます。つまり、「このフィルターに一致 かつ あのフィルターに一致する時系列を返す」という意味になります。or 演算子を実現するにはどうすればよいでしょうか。現在、PromQL にはラベルフィルターを組み合わせるための or 演算子がありませんが、ほとんどの場合、正規表現で代用できます。例えば、以下のクエリは eth1 または lo デバイスの時系列を返します。

node:network_receive_bytes_total{device=~"eth1|lo"}

正規表現によるメトリクス名またはメジャーメント名のフィルタリング

メジャーメントとメトリクス名は、実際には特別な名前を持つ通常のラベルです。__measurement____field__ です。したがって、これらのラベルに正規表現を適用して、必要なデータをフィルタリングできます。

例えば、node メジャーメント内で、network_receive_bytes_total または network_transmit_bytes_total というメトリクス名を持つすべての時系列をクエリします。

{__measurement__="node", __field__=~"network_(receive|transmit)_bytes_total"}

または、node1node2 の 2 つのメジャーメントに分散している network_receive_bytes_total または network_transmit_bytes_total というメトリクス名を持つ時系列をクエリします。

{__measurement__=~"node1|node2", __field__=~"network_(receive|transmit)_bytes_total"}

現在のデータと過去のデータの比較

PromQL は、履歴データをクエリし、現在のデータと組み合わせたり比較したりすることを可能にします。クエリに offset を追加するだけです。例えば、以下のクエリは、node:network_receive_bytes_total という名前のすべての時系列の 1 週間前のデータを返します。

node:network_receive_bytes_total offset 7d

以下のクエリは、現在の GC オーバーヘッドが 1 時間前の GC オーバーヘッドの 1.5 倍を超えるポイントを返します。

go:memstats_gc_cpu_fraction > 1.5 * (go:memstats_gc_cpu_fraction offset 1h)

レートの計算

上記のすべてのクエリに対して、グラフが増加し続ける線を描画していることに気付くかもしれません。

このようなグラフは、解釈が難しい増加し続けるカウンター値を示しているため、実用性はほぼゼロです。ネットワーク帯域幅のグラフを描画する必要があります。PromQL には、一致するすべての時系列の 1 秒あたりのレートを計算する関数 rate があります。

rate(node:network_receive_bytes_total[5m])

これで、グラフが理解できるようになりました。

クエリ内の [5m] は何を意味するのでしょうか。これは時間の継続時間(d)です。

この場合は 5 分で、各グラフポイントの 1 秒あたりのレートを計算する際に、後方を見ます。各ポイントの簡略化されたレート計算は次のとおりです。(Vcurr-Vprev) / (Tcurr-Tprev)。ここで、Vcurr は現在のポイントの値 -TcurrVprev は時間 Tprev = Tcurr-d の値です。

複雑に感じる場合は、d が大きいほどグラフが平滑化され、d が小さいほどグラフにノイズが増えることを覚えておいてください。

Guance は PromQL 拡張構文 MetricsQL を使用しています(VictoriaMetrics のオープンソースに感謝!)。この場合、[d] は省略できます。省略すると、グラフ上の連続する 2 点間の継続時間(「ステップ」とも呼ばれます)と等しくなります。

rate(node:network_receive_bytes_total)

したがって、rate の後の継続時間をどのように記述すればよいかわからない場合は、安心して省略してください。

rate に関する注意事項

rate はメトリクス名を削除しますが、内部の時系列のすべてのラベルは保持します。

rate を上下に変動する可能性のある時系列に適用しないでください。このような時系列はゲージと呼ばれます。rate は、常に上昇するが、リセットされる可能性がある(例えば、サービス再起動時)カウンターにのみ適用する必要があります。

rate の代わりに irate を使用しないでください。ピークをキャプチャできずrate よりもそれほど高速ではないためです。

算術演算子

PromQL は、すべての基本的な算術演算をサポートしています。

  • 加算(+)
  • 減算(-)
  • 乗算(*)
  • 除算(/)
  • 剰余(%)
  • 指数(^)

これにより、さまざまな変換を実行できます。例えば、バイト/秒をビット/秒に変換します。

rate(node:network_receive_bytes_total[5m]) * 8

さらに、これにより、時系列間の計算を実行できます。例えば、Flux クエリ は、以下の PromQL クエリに簡略化できます。

co2 * (((temp_c + 273.15) * 1013.25) / (pressure * 298.15))

算術演算子を使用して複数の時系列を組み合わせる場合は、マッチングルールを理解する必要があります。そうしないと、クエリがエラーになったり、不正な結果になる可能性があります。マッチングルールの基本は簡単です。

  • PromQL エンジンは、左右のすべての時系列からメトリクス名を削除しますが、ラベルは保持します。
  • 左側の各時系列について、PromQL エンジンは右側で同じラベルセットを持つ対応する時系列を検索し、各データポイントに操作を適用し、同じラベルセットを持つ結果の時系列を返します。一致するものがない場合、その時系列は結果から削除されます。

マッチングルールは、ignoringongroup_leftgroup_right 修飾子を使用して拡張できます。これらの修飾子の使用は複雑ですが、ほとんどの場合、使用する必要はありません。

PromQL 比較演算子

PromQL は、以下の比較演算子をサポートしています。

  • 等しい(==)
  • 等しくない(!=)
  • より大きい(>)
  • 以上(>=)
  • より小さい(<)
  • 以下(<=)

これらの演算子は、算術演算子と同様に、任意の PromQL 式に適用できます。比較演算の結果は、一致するデータポイントを持つ時系列です。例えば、以下のクエリは、帯域幅が 2300 バイト/秒未満の時系列のみを返します。

rate(node:network_receive_bytes_total[5m]) < 2300

これにより、帯域幅が 2300 バイト/秒を超える部分にギャップのあるグラフが生成されます。

rate(node:network_receive_bytes_total[5m]) < 2300

比較演算子の結果は、bool 修飾子を使用して拡張できます。

rate(node:network_receive_bytes_total[5m]) < bool 2300

この場合、結果には、比較が true の場合は 1、false の場合は 0 が含まれます。

rate(node:network_receive_bytes_total[5m]) < bool 2300

集約関数とグループ化関数

PromQL では、時系列の集約とグループ化が可能です。時系列は指定されたラベルセットでグループ化され、各グループに指定された集約関数が適用されます。例えば、以下のクエリは、node_exporter がインストールされているすべてのノードで、インスタンスごとにグループ化された受信トラフィックの合計を返します。

sum(rate(node:network_receive_bytes_total[5m])) by (instance)

ゲージの使用

ゲージは、メモリ使用量、温度、圧力など、いつでも上下に変動する可能性のある時系列です。ダッシュボードにグラフを描画する場合、通常、各ポイントの最小値、最大値、平均値、パーセンタイル値を表示する必要があります。PromQL は、これらの要件を実現するための以下の関数を提供しています。

例えば、以下のクエリは、グラフ上の各ポイントに空きメモリの最小値を描画します。

min_over_time(node:memory_MemFree_bytes[5m])

MetricsQL は PromQL に rollup_* 関数を追加しており、ゲージに適用すると、minmaxavg の値を自動的に返します。例えば、次のようになります。

rollup(node:memory_MemFree_bytes)

ラベルの操作

PromQL は、ラベルの変更、美化、削除、作成のための 2 つの関数を提供しています。

これらの関数の使用は複雑ですが、選択した時系列のラベルを強力かつ動的に操作できます。MetricsQL は、より便利なラベル操作関数 でこれらの機能を拡張しています。

  • label_set:時系列に追加のラベルを設定します。
  • label_del:時系列から指定されたラベルを削除します。
  • label_keep:指定されたラベル以外を時系列から削除します。
  • label_copy:ラベル値を別のラベルにコピーします。
  • label_move:ラベル名を変更します。
  • label_transform:指定された正規表現に一致するすべての部分文字列をテンプレート置換に置き換えます。
  • label_values:指定されたラベルから数値を返します。

単一のクエリから複数の結果を返す

単一の PromQL クエリから複数の結果を返す必要がある場合があります。これは、or 演算子 を使用して実現できます。例えば、以下のクエリは、metric1metric2metric3 という名前のすべての時系列を返します。

metric1 or metric2 or metric3

MetricsQL は、複数の結果を返すプロセスを 簡略化 し、() 内に列挙するだけです。

(metric1, metric2, metric3)

任意の PromQL 式をそこに配置できることに注意してください。メトリクス名だけではありません。

式の結果を組み合わせる際には、一般的な落とし穴があります。ラベルセットが重複する結果はスキップされます。例えば、以下のクエリは sum(b) をスキップします。sum(a)sum(b) はどちらも同じラベルセット(ラベルがまったくない)を持っているためです。

sum(a) or sum(b)

結論

PromQL は、使いやすく強力な時系列データベースクエリ言語です。SQL、InfluxQL、Flux と比較して、一般的な TSDB クエリを簡潔かつ明確に記述できます。

このチュートリアルでは、PromQL のすべての機能をカバーしているわけではありません。一部の機能はあまり一般的に使用されないためです。

この PromQL チートシート を使用して、PromQL の学習を続けることができます。

この記事の主な内容は、PromQL tutorial for beginners and humans から翻訳されたものです。Guance は、VictoriaMetrics がオープンソース化した MetricsQL エンジンの実装も使用しています。VictoriaMetrics に感謝します!

参考資料

フィードバック

このページは役に立ちましたか?