Prometheusクエリ

Prometheusは、PromQL(Prometheus Query Language)と呼ばれる関数型クエリ言語を提供しており、ユーザーはリアルタイムで時系列データを選択および集計できます。式の結果は、グラフとして表示したり、Prometheusの式ブラウザで表形式データとして表示したり、HTTP APIを介して外部システムで使用したりできます。

このドキュメントは、Prometheusの基本言語リファレンスです。学習するには、いくつかのから始める方が簡単かもしれません。

式言語のデータ型

Prometheusの式言語では、式または部分式は4つの型のいずれかに評価されます。

  • インスタントベクター - 各時系列に単一のサンプルを含む時系列のセットで、すべて同じタイムスタンプを共有します。
  • 範囲ベクター - 各時系列について時間の経過に伴うデータポイントの範囲を含む時系列のセット。
  • スカラー - 単純な数値の浮動小数点値。
  • 文字列 - 単純な文字列値。現在使用されていません。

ユースケース(グラフ化と式の出力の表示など)によっては、ユーザー指定の式の結果として、これらの型のうち一部のみが有効です。たとえば、インスタントベクターを返す式は、グラフ化できる唯一の型です。

実験的なネイティブヒストグラムに関するメモ

  • 機能フラグを介して、ネイティブヒストグラムの取り込みを有効にする必要があります。
  • ネイティブヒストグラムがTSDBに取り込まれると(機能フラグを再び無効にした後も)、インスタントベクターと範囲ベクターの両方に、単純な浮動小数点数(floatサンプル)ではなく、完全なヒストグラム(ヒストグラムサンプル)を含むサンプルが含まれる可能性があります。ベクターには、floatサンプルとヒストグラムサンプルが混在している場合があります。

リテラル

文字列リテラル

文字列リテラルは、シングル引用符、ダブル引用符、またはバッククォートで指定されます。

PromQLは、Goと同じエスケープルールに従います。シングルまたはダブルクォートの文字列リテラルでは、バックスラッシュがエスケープシーケンスを開始し、その後にabfnrtv、または\が続く場合があります。特定の文字は、8進数(\nnn)または16進数(\xnn\unnnn\Unnnnnnnn)表記を使用して指定できます。

逆に、バッククォートで指定された文字列リテラルでは、エスケープ文字は解析されません。Goとは異なり、Prometheusはバッククォート内の改行を破棄しないことに注意することが重要です。

"this is a string"
'these are unescaped: \n \\ \t'
`these are not unescaped: \n ' " \t`

浮動小数点リテラル

スカラーの浮動小数点値は、次の形式でリテラルの整数または浮動小数点数として記述できます(可読性のために空白のみが含まれています)。

[-+]?(
      [0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?
    | 0[xX][0-9a-fA-F]+
    | [nN][aA][nN]
    | [iI][nN][fF]
)

23
-2.43
3.4e-9
0x8f
-Inf
NaN

バージョン2.54以降、浮動小数点リテラルは、時間期間の構文を使用して表現することもできます。この場合、時間期間は、時間期間を表す秒数に対応する浮動小数点値に変換されます。これは実験的な機能であり、変更される可能性があります。

1s # Equivalent to 1.0
2m # Equivalent to 120.0
1ms # Equivalent to 0.001

時系列セレクタ

時系列セレクタは、時系列と生のまたは推論されたサンプルのタイムスタンプと値を選択する役割を果たします。

時系列のセレクタは、時系列のセレクタを実行できる、インスタントクエリと範囲クエリというより高レベルの概念と混同しないでください。より高レベルのインスタントクエリは、特定の時点で指定されたセレクタを評価しますが、範囲クエリは、最小タイムスタンプと最大タイムスタンプの間の複数の異なる時間で、一定の間隔でセレクタを評価します。

インスタントベクターセレクタ

インスタントベクターセレクタを使用すると、時系列のセットと、特定のタイムスタンプ(時点)での各時系列の単一のサンプル値を選択できます。最も単純な形式では、メトリック名のみを指定し、これにより、このメトリック名を持つすべての時系列の要素を含むインスタントベクターが生成されます。

この例では、http_requests_totalメトリック名を持つすべての時系列を選択します。

http_requests_total

中括弧({})で区切られたラベルマッチャのコンマ区切りのリストを追加することで、これらの時系列をさらに絞り込むことができます。

この例では、http_requests_totalメトリック名を持ち、jobラベルがprometheusに設定され、groupラベルがcanaryに設定されている時系列のみを選択します。

http_requests_total{job="prometheus",group="canary"}

ラベル値を負で一致させるか、ラベル値を正規表現と一致させることも可能です。次のラベル一致演算子が存在します。

  • =:指定された文字列と完全に一致するラベルを選択します。
  • !=:指定された文字列と一致しないラベルを選択します。
  • =~:指定された文字列と正規表現が一致するラベルを選択します。
  • !~:指定された文字列と正規表現が一致しないラベルを選択します。

正規表現の一致は完全にアンカーされます。env=~"foo"の一致は、env=~"^foo$"として扱われます。

たとえば、これは、stagingtestingdevelopment環境と、GET以外のHTTPメソッドに関するすべてのhttp_requests_total時系列を選択します。

http_requests_total{environment=~"staging|testing|development",method!="GET"}

空のラベル値と一致するラベルマッチャは、特定のラベルがまったく設定されていないすべての時系列も選択します。同じラベル名に対して複数のマッチャを持つことができます。

たとえば、次のデータセットがあるとします。

http_requests_total
http_requests_total{replica="rep-a"}
http_requests_total{replica="rep-b"}
http_requests_total{environment="development"}

クエリhttp_requests_total{environment=""}は一致して返し、

http_requests_total
http_requests_total{replica="rep-a"}
http_requests_total{replica="rep-b"}

を除外します。

http_requests_total{environment="development"}

同じラベル名に対して複数のマッチャを使用できます。結果を返すには、すべてがパスする必要があります。

クエリ

http_requests_total{replica!="rep-a",replica=~"rep.*"}

は、次に一致します。

http_requests_total{replica="rep-b"}

ベクターセレクタは、名前、または空文字列と一致しない少なくとも1つのラベルマッチャを指定する必要があります。次の式は無効です。

{job=~".*"} # Bad!

対照的に、これらは、空のラベル値と一致しないセレクタが両方ともあるため、有効な式です。

{job=~".+"}              # Good!
{job=~".*",method="get"} # Good!

内部__name__ラベルと一致させることで、ラベルマッチャをメトリック名にも適用できます。たとえば、式http_requests_total{__name__="http_requests_total"}と同じです。=以外のマッチャ(!==~!~)も使用できます。次の式は、job:で始まる名前を持つすべてのメトリックを選択します。

{__name__=~"job:.*"}

メトリック名は、キーワードboolonignoringgroup_leftgroup_rightのいずれかであってはいけません。次の式は無効です。

on{} # Bad!

この制限の回避策は、__name__ラベルを使用することです。

{__name__="on"} # Good!

Prometheusのすべての正規表現は、RE2構文を使用します。

範囲ベクターセレクタ

範囲ベクターリテラルは、インスタントベクターリテラルと同様に機能しますが、現在の瞬間からさかのぼるサンプルの範囲を選択します。構文的には、時間期間が角括弧([])でベクターセレクタの最後に追加され、各結果の範囲ベクター要素についてどのくらい過去に値を取得する必要があるかを指定します。範囲は閉区間です。つまり、範囲の境界のいずれかと一致するタイムスタンプを持つサンプルは、選択に含まれます。

この例では、メトリック名http_requests_totaljobラベルがprometheusに設定されているすべての時系列について、過去5分間に記録したすべての値を選択します。

http_requests_total{job="prometheus"}[5m]

時間期間

時間期間は、数字の後に、次の単位のいずれかがすぐに続きます。

  • ms - ミリ秒
  • s - 秒
  • m - 分
  • h - 時間
  • d - 日 - 1日は常に24時間と仮定
  • w - 週間 - 1週間は常に7日と仮定
  • y - 年 - 1年は常に365日と仮定1

1 1年の日数については、うるう日は無視され、逆に、分については、うるう秒は無視されます。

時間期間は、連結によって組み合わせることができます。単位は、最長から最短の順序でなければなりません。特定の単位は、時間期間に1回だけ出現する必要があります。

有効な時間期間の例を以下に示します。

5h
1h30m
5m
10s

バージョン2.54から、時間の長さは浮動小数点リテラルの構文を使用して表すこともできます。これは時間の長さを秒数で示します。これは実験的な機能であり、変更される可能性があります。

1.0 # Equivalent to 1s
0.001 # Equivalent to 1ms
120 # Equivalent to 2m

オフセット修飾子

offset修飾子を使用すると、クエリ内の個々のインスタントベクトルと範囲ベクトルの時間オフセットを変更できます。

たとえば、次の式は、現在のクエリ評価時間から過去5分間のhttp_requests_totalの値を返します。

http_requests_total offset 5m

offset修飾子は常にセレクターの直後に配置する必要があります。つまり、以下は正しい記述です。

sum(http_requests_total{method="GET"} offset 5m) // GOOD.

一方、以下は正しくありません

sum(http_requests_total{method="GET"}) offset 5m // INVALID.

範囲ベクトルでも同様です。これは、1週間前のhttp_requests_totalの5分間のrateを返します。

rate(http_requests_total[5m] offset 1w)

過去におけるサンプルをクエリする場合、負のオフセットを指定すると、時間的に前方向の比較が可能になります。

rate(http_requests_total[5m] offset -1w)

これは、クエリが評価時間よりも未来の時点を参照できることを意味します。

@ 修飾子

@修飾子を使用すると、クエリ内の個々のインスタントベクトルと範囲ベクトルの評価時間を変更できます。@修飾子に指定する時間は、UNIXタイムスタンプであり、浮動小数点リテラルで記述されます。

たとえば、次の式は、2021-01-04T07:40:00+00:00時点のhttp_requests_totalの値を返します。

http_requests_total @ 1609746000

@修飾子は常にセレクターの直後に配置する必要があります。つまり、以下は正しい記述です。

sum(http_requests_total{method="GET"} @ 1609746000) // GOOD.

一方、以下は正しくありません

sum(http_requests_total{method="GET"}) @ 1609746000 // INVALID.

範囲ベクトルでも同様です。これは、2021-01-04T07:40:00+00:00時点のhttp_requests_totalの5分間のrateを返します。

rate(http_requests_total[5m] @ 1609746000)

@修飾子は、上記で説明されているすべての数値リテラルの表現をサポートします。オフセットが@修飾子の時間に対して適用されるoffset修飾子と連携します。修飾子の順序に関係なく、結果は同じになります。

たとえば、次の2つのクエリは同じ結果を生成します。

# offset after @
http_requests_total @ 1609746000 offset 5m
# offset before @
http_requests_total offset 5m @ 1609746000

さらに、start()end()は、特別な値として@修飾子の値として使用することもできます。

範囲クエリの場合、それぞれ範囲クエリの開始と終了に解決され、すべてのステップで同じままになります。

インスタントクエリの場合、start()end()はどちらも評価時間に解決されます。

http_requests_total @ start()
rate(http_requests_total[5m] @ end())

@修飾子を使用すると、クエリが評価時間よりも未来の時点を参照できることに注意してください。

サブクエリ

サブクエリを使用すると、指定された範囲と解像度に対してインスタントクエリを実行できます。サブクエリの結果は範囲ベクトルです。

構文: <instant_query> '[' <range> ':' [<resolution>] ']' [ @ <float_literal> ] [ offset <duration> ]

  • <resolution>はオプションです。デフォルトはグローバルな評価間隔です。

演算子

Prometheusは、多くの二項演算子と集計演算子をサポートしています。これらについては、式言語演算子ページで詳しく説明されています。

関数

Prometheusは、データ操作のためのいくつかの関数をサポートしています。これらについては、式言語関数ページで詳しく説明されています。

コメント

PromQLは、#で始まる行コメントをサポートしています。例:

    # This is a comment

注意点

陳腐化

クエリ中のデータのサンプリングを行うタイムスタンプは、実際の現在の時系列データとは独立して選択されます。これは主に、複数の集計された時系列が時間的に正確に一致しない場合(sumavgなど)の集計をサポートするためです。その独立性のために、Prometheusは、関連する各時系列について、これらのタイムスタンプに値を割り当てる必要があります。そのため、ルックバック期間内のこのタイムスタンプより前の最新のサンプルを使用します。ルックバック期間はデフォルトで5分です。

ターゲットのスクレイピングまたはルールの評価が、以前に存在していた時系列のサンプルを返すことができなくなった場合、その時系列は陳腐化したものとしてマークされます。ターゲットが削除されると、以前に取得された時系列は削除後すぐに陳腐化したものとしてマークされます。

時系列が陳腐化したものとしてマークされた後にサンプリングタイムスタンプでクエリが評価されると、その時系列の値は返されません。その後、その時系列に対して新しいサンプルが取り込まれると、期待どおりに返されます。

時系列は、エクスポートされなくなった場合、またはターゲットが存在しなくなった場合に陳腐化します。このような時系列は、最後に収集されたサンプルの時点でグラフから消え、陳腐化したものとしてマークされた後はクエリで返されません。

独自のタイムスタンプをサンプルに付けるエクスポーターの中には、異なる動作をするものがあります。エクスポートされなくなった系列は、消える前に(デフォルトで)5分間最後の値を保持します。track_timestamps_staleness設定でこれを変更できます。

遅いクエリとオーバーロードの回避

クエリが大量のデータに対して操作する必要がある場合、グラフ化するとタイムアウトしたり、サーバーまたはブラウザに過負荷がかかる可能性があります。そのため、不明なデータに対するクエリを作成する際には、常にPrometheusの式ブラウザの表形式ビューでクエリを作成し始め、結果セットが妥当な量(せいぜい数百の時系列、数千ではない)になるまで確認してください。データのフィルタリングまたは集計が十分に行われた場合にのみ、グラフモードに切り替えます。式が依然としてアドホックにグラフ化するのに時間がかかりすぎる場合は、レコーディングルールを使用して事前に記録してください。

これは、api_http_requests_totalのようなベアメトリック名のセレクターが、異なるラベルを持つ数千の時系列に展開される可能性のあるPrometheusのクエリ言語にとって特に重要です。また、多くの時系列を集計する式は、出力時系列が少量であっても、サーバーに負荷をかけることに注意してください。これは、出力値が単一の数字であっても、リレーショナルデータベースの列のすべての値を合計することが遅いことと同様です。

このドキュメントはオープンソースです。問題点やプルリクエストを提出して、改善にご協力ください。