Prometheusの共同作成者であるJuliusVolzの記事

序章

Prometheusは、オープンソースの監視システムおよび時系列データベースです。 Ubuntu 14.04 Part 1 でPrometheusをクエリする方法では、合成メトリックをPrometheusサーバーに公開する3つのデモサービスインスタンスを設定しました。 次に、これらのメトリックを使用して、Prometheusクエリ言語を使用して時系列を選択およびフィルタリングする方法、ディメンションを集計する方法、およびレートとデリバティブを計算する方法を学習しました。

このチュートリアルの第2部では、第1部からのセットアップに基づいて構築し、より高度なクエリ手法とパターンを学習します。 このチュートリアルを終えると、値ベースのフィルタリング、セット操作、ヒストグラムなどを適用する方法がわかります。

前提条件

このチュートリアルは、 Ubuntu 14.04 Part1でPrometheusをクエリする方法で概説されているセットアップに基づいています。 少なくとも、そのチュートリアルのステップ1とステップ2に従って、Prometheusサーバーと3つの監視対象デモサービスインスタンスをセットアップする必要があります。 ただし、最初の部分で説明したクエリ言語の手法にも基づいているため、完全に実行することをお勧めします。

ステップ1—値によるフィルタリングとしきい値の使用

このセクションでは、値に基づいて返された時系列をフィルタリングする方法を学習します。

値ベースのフィルタリングの最も一般的な使用法は、単純な数値アラートしきい値です。 たとえば、合計が多いHTTPパスを検索したい場合があります 500-過去15分間の平均で、1秒あたり0.2を超えるステータス要求率。 これを行うには、単にすべてをクエリします 500-ステータスリクエストレートを追加してから、 > 0.2 式の最後にあるフィルター演算子:

rate(demo_api_request_duration_seconds_count{status="500",job="demo"}[15m]) > 0.2

Console ビューでは、結果は次のようになります。

ただし、バイナリ演算と同様に、Prometheusは単一のスカラー数によるフィルタリングをサポートするだけではありません。 別の時系列セットに基づいて、ある時系列セットをフィルタリングすることもできます。 この場合も、要素はラベルセットによって照合され、一致する要素間にフィルター演算子が適用されます。 フィルタを通過する右側の要素およびと一致する左側の要素のみが出力の一部になります。 The on(<labels>), group_left(<labels>), group_right(<labels>) ここでは、句は算術演算子の場合と同じように機能します。

たとえば、 500-任意のステータス率 job, instance, method、 と path の組み合わせ 200-ステータス率は、 500-このようなステータス率:

    rate(demo_api_request_duration_seconds_count{status="500",job="demo"}[5m]) * 50
> on(job, instance, method, path)
    rate(demo_api_request_duration_seconds_count{status="200",job="demo"}[5m])

これは次のようになります。

その上 >、プロメテウスも通常をサポートしています >=, <=, <, !=、 と == フィルタリングで使用するための比較演算子。

これで、単一の数値に基づいて、またはラベルが一致する別の時系列値のセットに基づいて、時系列のセットをフィルタリングする方法がわかりました。

ステップ2—集合演算子を使用する

このセクションでは、Prometheusのセット演算子を使用して、時系列のセットを相互に関連付ける方法を学習します。

多くの場合、別のセットに基づいて時系列の1つのセットをフィルタリングする必要があります。 このために、プロメテウスは and 演算子を設定します。 オペレーターの左側にあるすべてのシリーズについて、同じラベルの右側にあるシリーズを見つけようとします。 一致するものが見つかった場合、左側の系列が出力の一部になります。 右側に一致する系列が存在しない場合、その系列は出力から省略されます。

たとえば、90パーセンタイルのレイテンシが50ms(0.05s)を超えるHTTPエンドポイントを選択したい場合がありますが、1秒あたり複数のリクエストを受信するディメンションの組み合わせに対してのみです。 を使用します histogram_quantile() ここでパーセンタイル計算のための関数。 次のセクションで、この機能が正確に機能することを説明します。 今のところ、重要なのは、各サブディメンションの90パーセンタイルレイテンシを計算することだけです。 結果として生じる不良レイテンシをフィルタリングし、1秒あたり複数のリクエストを受信するレイテンシのみを保持するために、次のクエリを実行できます。

    histogram_quantile(0.9, rate(demo_api_request_duration_seconds_bucket{job="demo"}[5m])) > 0.05
and
    rate(demo_api_request_duration_seconds_count{job="demo"}[5m]) > 1

共通部分を取得する代わりに、2セットの時系列からユニオンを構築したい場合があります。 プロメテウスは or このための演算子を設定します。 これにより、操作の左側のシリーズと、左側に一致するラベルセットがない右側のシリーズが作成されます。 たとえば、10未満または30を超えるすべてのリクエストレートを一覧表示するには、次のクエリを実行します。

    rate(demo_api_request_duration_seconds_count{job="demo"}[5m]) < 10
or
    rate(demo_api_request_duration_seconds_count{job="demo"}[5m]) > 30

結果はグラフで次のようになります。

ご覧のとおり、グラフで値フィルターとセット操作を使用すると、グラフに沿った任意のタイムステップでフィルターと一致するかどうかに応じて、同じグラフ内で時系列が表示および非表示になる可能性があります。 一般に、この種のフィルターロジックの使用は、アラートルールにのみ推奨されます。

これで、ラベル付けされた時系列から交差点と和集合を構築する方法がわかりました。

ステップ3—ヒストグラムの操作

このセクションでは、ヒストグラムメトリックを解釈する方法と、それらから分位数(パーセンタイルの一般化された形式)を計算する方法を学習します。

Prometheusは、サービスが一連の値の分布を記録できるようにするヒストグラムメトリックをサポートしています。 ヒストグラムは通常、リクエストのレイテンシや応答サイズなどの測定値を追跡しますが、基本的に、何らかの分布に従って大きさが変動する値を追跡できます。 Prometheusは、クライアント側の sample データをヒストグラム化します。つまり、構成可能な数を使用して観測値をカウントします(例: レイテンシー)バケットを作成し、それらのバケットを個別の時系列として公開します。

内部的には、ヒストグラムは時系列のグループとして実装され、それぞれが特定のバケットのカウントを表します(例: 「10ms未満のリクエスト」、「25ms未満のリクエスト」、「50ms未満のリクエスト」など)。 バケットカウンターは累積的です。つまり、値が大きいバケットには、値の小さいすべてのバケットのカウントが含まれます。 ヒストグラムの一部である各時系列で、対応するバケットは特別な le (以下)ラベル。 これにより、すでに追跡している既存のディメンションに追加のディメンションが追加されます。

たとえば、デモサービスはヒストグラムをエクスポートします demo_api_request_duration_seconds_bucket APIリクエスト期間の分布を追跡します。 このヒストグラムは、追跡されたサブディメンションごとに26個のバケットをエクスポートするため、このメトリックには多くの時系列があります。 まず、1つのインスタンスから、1つのタイプのリクエストのみの生のヒストグラムを見てみましょう。

demo_api_request_duration_seconds_bucket{instance="localhost:8080",method="POST",path="/api/bar",status="200",job="demo"}

それぞれが1つの観測バケットを表す26のシリーズが表示されます。 le ラベル:

ヒストグラムは、「リクエストの完了までに100ミリ秒以上かかるものはいくつありますか?」などの質問に答えるのに役立ちます。 (ヒストグラムに100msの境界を持つバケットが構成されている場合)。 一方、「クエリが99 % o f完了するまでのレイテンシはどれくらいですか?」などの関連する質問に答えたいと思うことがよくあります。 ヒストグラムバケットが十分にきめ細かい場合は、を使用してこれを計算できます。 histogram_quantile() 関数。 この関数は、ヒストグラムメトリック( le バケットラベル)を入力として、対応する分位数を出力します。 0パーセンタイルから100パーセンタイルの範囲のパーセンタイルとは対照的に、ターゲット分位数の仕様は、 histogram_quantile() 関数は、入力範囲が 01 (したがって、90パーセンタイルは次の分位数に対応します 0.9).

たとえば、次のように、すべてのディメンションについて、すべての時間で90パーセンタイルのAPIレイテンシを計算することができます。

# BAD!
histogram_quantile(0.9, demo_api_request_duration_seconds_bucket{job="demo"})

これはあまり有用でも信頼性もありません。 バケットカウンターは、個々のサービスインスタンスが再起動されるとリセットされます。通常、メトリックの全時間ではなく、レイテンシが「現在」(たとえば、過去5分間で測定)を確認する必要があります。 あなたはこれを適用することによって達成することができます rate() 基になるヒストグラムバケットカウンターに対して機能します。これは、カウンターリセットを処理し、指定された時間枠での各バケットの増加率のみを考慮します。

次のように、過去5分間の90パーセンタイルAPIレイテンシを計算します。

# GOOD!
histogram_quantile(0.9, rate(demo_api_request_duration_seconds_bucket{job="demo"}[5m]))

これははるかに優れており、次のようになります。

ただし、これはすべてのサブディメンションの90パーセンタイルを示しています(job, instance, path, method、 と status). 繰り返しになりますが、これらのすべてのディメンションに関心があるわけではなく、それらの一部を集約したい場合があります。 幸いなことに、プロメテウスの sum 集計演算子は、 histogram_quantile() クエリ時にディメンションを集計できるようにする関数!

次のクエリは90パーセンタイルのレイテンシを計算しますが、結果を次のように分割するだけです job, instancepath 寸法:

histogram_quantile(
  0.9,
  sum without(status, method) (
    rate(demo_api_request_duration_seconds_bucket{job="demo"}[5m])
  )
)

:常に le 適用する前の集計のバケットラベル histogram_quantile() 関数。 これにより、バケットのグループを操作し、それらから分位数を計算できるようになります。

グラフは次のようになります。

ヒストグラムから分位数を計算すると、常にある程度の統計誤差が発生します。 このエラーは、バケットサイズ、観測値の分布、および計算するターゲット分位数によって異なります。 これについて詳しくは、Prometheusのドキュメントの分位数推定のエラーをお読みください。

これで、ヒストグラムメトリックを解釈する方法と、さまざまな時間範囲でヒストグラムメトリックから分位数を計算する方法を理解し、その場でいくつかのディメンションを集計することもできます。

ステップ4—タイムスタンプメトリックの操作

このセクションでは、タイムスタンプを含むメトリックを使用する方法を学習します。

Prometheusエコシステムのコンポーネントは、タイムスタンプを頻繁に公開します。 たとえば、これは、バッチジョブが正常に完了した最後の時間、構成ファイルが正常に再ロードされた最後の時間、またはマシンが起動されたときの場合があります。 慣例により、時間は1970年1月1日UTCからの秒単位のUnixタイムスタンプとして表されます。

たとえば、デモサービスは、シミュレートされたバッチジョブが最後に成功した時間を公開します。

demo_batch_last_success_timestamp_seconds{job="demo"}

このバッチジョブは、1分に1回実行されるようにシミュレートされていますが、すべての試行で25% ofで失敗します。 失敗した場合、 demo_batch_last_success_timestamp_seconds メトリックは、別の実行が成功するまで最後の値を保持します。

生のタイムスタンプをグラフ化すると、次のようになります。

ご覧のとおり、通常、生のタイムスタンプ値はそれ自体ではあまり役に立ちません。 代わりに、タイムスタンプ値の古さを知りたいことがよくあります。 一般的なパターンは、メトリックのタイムスタンプを現在の時刻から差し引くことです。 time() 関数:

time() - demo_batch_last_success_timestamp_seconds{job="demo"}

これにより、最後に成功したバッチジョブの実行からの時間が秒単位で生成されます。

この年齢を秒から時間に変換したい場合は、結果を次のように割ることができます。 3600:

(time() - demo_batch_last_success_timestamp_seconds{job="demo"}) / 3600

このような式は、グラフ化とアラートの両方に役立ちます。 上記のようにタイムスタンプの経過時間を視覚化すると、直線的に増加する線と定期的にリセットされる鋸歯状のグラフが表示されます。 0 バッチジョブが正常に完了したとき。 鋸歯状のスパイクが大きくなりすぎる場合、これはバッチジョブが長期間完了していないことを示します。 追加することでこれについて警告することもできます > 式に対するしきい値フィルターと、結果の時系列に対するアラート(ただし、このチュートリアルではアラートルールについては説明しません)。

過去1.5分間にバッチジョブが完了しなかったインスタンスを単純に一覧表示するには、次のクエリを実行できます。

time() - demo_batch_last_success_timestamp_seconds{job="demo"} > 1.5 * 60

これで、生のタイムスタンプメトリックを相対的な年齢に変換する方法がわかりました。これは、グラフ化とアラートの両方に役立ちます。

ステップ5— topk/bottomk関数の並べ替えと使用

このステップでは、クエリ出力を並べ替える方法、または一連のシリーズの最大値または最小値のみを選択する方法を学習します。

表形式のConsoleビューでは、出力系列を値で並べ替えると便利なことがよくあります。 これは、 sort() (昇順)および sort_desc() (降順)関数。 たとえば、パスごとのリクエストレートを値で並べ替えて表示するには、次のクエリを実行できます。

sort_desc(sum by(path) (rate(demo_api_request_duration_seconds_count{job="demo"}[5m])))

ソートされた出力は次のようになります。

または、すべてのシリーズを表示することすら興味がなく、K個の最大または最小のシリーズのみを表示することもできます。 このために、プロメテウスは topk()bottomk() 機能。 それらはそれぞれ、K値(選択するシリーズの数)と、フィルタリングする必要のある時系列のセットを返す任意の式を取ります。 たとえば、パスとメソッドごとの上位3つのリクエスト率のみを表示するには、次のクエリを実行できます。

topk(3, sum by(path, method) (rate(demo_api_request_duration_seconds_count{job="demo"}[5m])))

コンソールビューではのみの並べ替えが役立ちますが、 topk()bottomk() グラフでも役立つ場合があります。 出力には、グラフの時間範囲全体で平均された上位または下位のK系列が表示されないことに注意してください。代わりに、出力は、グラフに沿ったすべての解像度ステップについて、上位または下位のK系列を再計算します。 したがって、上部または下部のKシリーズは実際にはグラフの範囲全体で変化する可能性があり、グラフには合計でKシリーズより多くが表示される場合があります。

ここで、K個の最大または最小のシリーズを並べ替える方法または選択する方法を学びました。

ステップ6—スクレイプされたインスタンスの状態を検査する

このステップでは、インスタンスのスクレイプヘルスを経時的に検査する方法を学習します。

このセクションをさらに面白くするために、3つのバックグラウンドデモサービスインスタンスの最初のインスタンス(ポート8080でリッスンしているインスタンス)を終了しましょう。

  1. pkill -f -- -listen-address=:8080

Prometheusがターゲットをスクレイプするたびに、メトリック名を持つ合成サンプルが保存されます up そしてその jobinstance 削り取られたインスタンスのラベル。 スクレイプが成功した場合、サンプルの値は次のように設定されます。 1. に設定されています 0 スクレイプが失敗した場合。 したがって、現在「アップ」または「ダウン」しているインスタンスを簡単に照会できます。

up{job="demo"}

これで、1つのインスタンスがダウンとして表示されます。

のみのダウンインスタンスを表示するには、値をフィルタリングできます 0:

up{job="demo"} == 0

これで、終了したインスタンスのみが表示されます。

または、ダウンインスタンスの総数を取得するには:

count by(job) (up{job="demo"} == 0)

これにより、 1:

これらの種類のクエリは、基本的なスクレイプヘルスアラートに役立ちます。

:ダウンインスタンスがない場合、このクエリは、カウントが 0. それの訳は count() は、入力として一連の次元時系列を期待し、次のように出力系列をグループ化できる集計演算子です。 by また without 句。 すべての出力グループは、既存の入力系列にのみ基づくことができます。入力系列がまったくない場合、出力は生成されません。

これで、インスタンスのヘルス状態を照会する方法がわかりました。

結論

このチュートリアルでは、 Ubuntu 14.04 Part 1 でPrometheusをクエリする方法の進捗状況に基づいて構築し、より高度なクエリ手法とパターンについて説明しました。 値に基づいて系列をフィルタリングする方法、ヒストグラムから分位数を計算する方法、タイムスタンプベースのメトリックを処理する方法などを学びました。

これらのチュートリアルでは、考えられるすべてのクエリのユースケースを網羅することはできませんが、Prometheusを使用して実際のクエリ、ダッシュボード、アラートを作成するときに、クエリの例が役立つことを願っています。 Prometheusのクエリ言語の詳細については、Prometheusクエリ言語のドキュメントを参照してください。