Prometheusのクエリ

Prometheusは、ユーザーが時系列データをリアルタイムで選択および集計できる、PromQL (Prometheus Query Language) と呼ばれる関数型クエリ言語を提供します。

Prometheusにクエリリクエストを送信する際、それはある時点で評価されるインスタントクエリであるか、または開始時刻と終了時刻の間で等間隔のステップで評価されるレンジクエリのいずれかです。PromQLはどちらの場合でもまったく同じように機能します。レンジクエリは、異なるタイムスタンプで複数回実行されるインスタントクエリのようなものです。

Prometheus UIでは、「Table」タブはインスタントクエリ用、「Graph」タブはレンジクエリ用です。

他のプログラムは、HTTP APIを介してPromQL表現の結果を取得できます。

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

表現言語のデータ型

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

  • インスタントベクター - 各時系列に単一のサンプルを含み、すべて同じタイムスタンプを共有する時系列のセット。
  • レンジベクター - 各時系列について、一定期間にわたるデータポイントの範囲を含む時系列のセット。
  • スカラー - 単純な数値浮動小数点値。
  • 文字列 - 単純な文字列値。現在は未使用。

ユースケース(例:グラフ化する場合と表現の出力を表示する場合)に応じて、これらの型の一部のみがユーザー指定の表現の結果として合法です。インスタントクエリの場合、上記のデータ型はいずれも表現のルートとして許可されます。レンジクエリは、スカラー型およびインスタントベクター型の表現のみをサポートします。

実験的なネイティブヒストグラムに関する注意事項

  • ネイティブヒストグラムの取り込みは、機能フラグを介して有効にする必要があります。
  • ネイティブヒストグラムがTSDBに取り込まれると(機能フラグを再度無効にした後でも)、インスタントベクターとレンジベクターの両方に、単純な浮動小数点数(浮動小数点サンプル)ではなく、完全なヒストグラム(ヒストグラムサンプル)であるサンプルが含まれる場合があります。ベクターには、浮動小数点サンプルとヒストグラムサンプルの両方が混在して含まれる場合があります。PromQLドキュメントにおける「ヒストグラムサンプル」という用語は、常にネイティブヒストグラムを指すことに注意してください。従来のヒストグラムは、多数の浮動小数点サンプル系列に分割されます。PromQLの観点から見ると、「従来のヒストグラムサンプル」は存在しません。
  • 浮動小数点サンプルと同様に、ヒストグラムサンプルもカウンターまたはゲージにすることができます。それぞれカウンターヒストグラムまたはゲージヒストグラムとも呼ばれます。
  • ネイティブヒストグラムは異なるバケットレイアウトを持つことができますが、一般的にバイナリおよび集計操作を適用するために互換性のあるバージョンに変換可能です。ただし、これはすべてのバケットスキーマに当てはまるわけではありません。操作中に互換性のないヒストグラムが検出された場合、対応する出力ベクター要素は結果から削除され、警告レベルのアノテーションが付けられます。詳細については、ネイティブヒストグラム仕様を参照してください。

リテラル

文字列リテラル

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

PromQLはGoと同じエスケープルールに従います。シングルクォートまたはダブルクォート内の文字列リテラルの場合、バックスラッシュはエスケープシーケンスを開始し、その後ろにa, b, f, n, r, t, v, または\が続くことがあります。特定の文字は、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

さらに、アンダースコア(_)を10進数または16進数の間に使用して、読みやすさを向上させることができます。

1_000_000
.123_456_789
0x_53_AB_F3_82

浮動小数点リテラルは、秒単位の期間を指定するためにも使用されます。便宜上、10進整数は以下の時間単位と組み合わせて使用できます。

  • ms – ミリ秒
  • s – 秒 – 1秒は1000ミリ秒に等しい
  • m – 分 – 1分は60秒に等しい(うるう秒は除く)
  • h – 時間 – 1時間は60分に等しい
  • d – 日 – 1日は24時間に等しい(いわゆる夏時間は除く)
  • w – 週 – 1週は7日に等しい
  • y – 年 – 1年は365日に等しい(うるう日は除く)

10進整数に上記のいずれかの単位を接尾辞として付けることは、素の浮動小数点リテラルとして equivalent な秒数を表す別の表現です。

1s # Equivalent to 1.
2m # Equivalent to 120.
1ms # Equivalent to 0.001.
-2h # Equivalent to -7200.

以下の例は機能**しません**

0xABm # No suffixing of hexadecimal numbers.
1.5h # Time units cannot be combined with a floating point.
+Infd # No suffixing of ±Inf or NaN.

複数の単位は、接尾辞付き整数を連結することで組み合わせることができます。単位は長いものから短いものの順に並べる必要があります。特定の単位は、1つの浮動小数点リテラルにつき1回のみ現れる必要があります。

1h30m # Equivalent to 5400s and thus 5400.
12h34m56s # Equivalent to 45296s and thus 45296.
54s321ms # Equivalent to 54.321.

時系列セレクター

これらは、PromQLにどのデータをフェッチするかを指示する基本的な構成要素です。

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

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

返される値は、クエリの評価タイムスタンプ(インスタントクエリの場合)またはクエリ内の現在のステップ(レンジクエリの場合)における、その時点またはそれ以前の最新のサンプルの値になります。@修飾子を使用すると、選択が行われる相対的なタイムスタンプを上書きできます。時系列は、その最新のサンプルがルックバック期間以内である場合にのみ返されます。

この例は、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環境におけるすべてのhttp_requests_total時系列と、GET以外のHTTPメソッドを選択します。

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!

レンジベクターセレクター

レンジベクターリテラルは、インスタントベクターリテラルと同様に機能しますが、現在のインスタントから過去の一定範囲のサンプルを選択する点が異なります。構文的には、浮動小数点リテラルが角括弧([])でベクターセレクターの末尾に付加され、結果として得られる各レンジベクター要素に対して、何秒前の値を取得すべきかを指定します。通常、浮動小数点リテラルは、[5m]のように1つ以上の時間単位を含む構文を使用します。範囲は左開きの右閉じ区間、すなわち範囲の左境界のタイムスタンプと一致するサンプルは選択から除外され、右境界のタイムスタンプと一致するサンプルは選択に含まれます。

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

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

オフセット修飾子

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(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(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 <float_literal> ]

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

演算子

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

関数

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

コメント

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

    # This is a comment

正規表現

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

正規表現のマッチは常に完全にアンカーされます。

注意点

鮮度

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

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

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

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

一部のエクスポーターは、サンプルに独自のタイムスタンプを付けるため、異なる動作を示します。エクスポートが停止した系列は、(デフォルトで) 5分間最後の値を保持してから消滅します。track_timestamps_staleness設定でこれを変更できます。

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

クエリが大量のデータを操作する必要がある場合、グラフ化するとタイムアウトしたり、サーバーやブラウザをオーバーロードさせたりする可能性があります。したがって、未知のデータに対してクエリを構築する際は、常にPrometheusの式ブラウザの表形式ビューでクエリを構築し始め、結果セットが妥当な範囲(最大で数百、数千ではない時系列)になるまで続けます。データを十分にフィルタリングまたは集計した場合にのみ、グラフモードに切り替えてください。式がアドホックにグラフ化するのにまだ時間がかかりすぎる場合は、記録ルールを介して事前に記録してください。

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

このドキュメントはオープンソースです。課題の登録やプルリクエストの提出によって改善にご協力ください。