クエリの基本

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

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

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

他のプログラムは、HTTP API経由でPromQL式の結果を取得できます。

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

式言語のデータ型

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

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

ユースケース(例:グラフ表示時と式の結果表示時)に応じて、これらの型の一部のみがユーザー指定の式の結果として有効です。インスタントクエリの場合、上記すべてのデータ型が式のルートとして許可されます。範囲クエリは、スカラー型とインスタントベクトル型の式のみをサポートします。

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

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

リテラル

文字列リテラル

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

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

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

1_000_000
.123_456_789
0x_53_AB_F3_82

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

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

10進整数値に上記単位のいずれかを付加することは、裸の浮動小数点リテラルと同じ秒数を表す別の表現です。

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.

複数の単位は、サフィックス付き整数を連結することで組み合わせることができます。単位は、最も長いものから最も短いものの順に並べる必要があります。指定された単位は、浮動小数点リテラルごとに一度だけ出現する必要があります。

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$"`として扱われます。

たとえば、これは`staging`、`testing`、および`development`環境の`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:.*"}

メトリック名は、キーワード`bool`、`on`、`ignoring`、`group_left`、`group_right`のいずれかであってはなりません。以下の式は不正です。

on{} # Bad!

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

{__name__="on"} # Good!

範囲ベクトルセレクタ

範囲ベクトルリテラルは、現在のインスタンスからさかのぼってサンプルの範囲を選択する点を除けば、インスタントベクトルリテラルと同様に機能します。構文的には、結果として得られる各範囲ベクトル要素に対して何秒前の値をフェッチするかを指定するために、ベクトルセレクタの末尾に角括弧(`[]`)で囲まれた浮動小数点リテラルが追加されます。一般的に、浮動小数点リテラルは1つ以上の時間単位を持つ構文、例えば`[5m]`を使用します。範囲は左開きの右閉じた区間、つまり範囲の左境界のタイムスタンプと一致するサンプルは選択から除外され、範囲の右境界のタイムスタンプと一致するサンプルは選択に含まれます。

この例では、`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構文を使用します。

正規表現の一致は常に完全に固定されます。

落とし穴

陳腐化

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

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

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

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

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

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

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

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

このページの内容