リントは静かだったのにバケットが逆さまだった
目標
規約に違反したエクスポーターの出力をpromtoolのリンターで診断して直し、ヒストグラムの公開を元データから数え直し、OpenMetricsでTSDBに取り込んで時系列の数を確認したうえで、標準ライブラリだけでエクスポーターを作って、実際にスクレイプしてみます。
なぜ重要なのか
Prometheusは、エクスポーターが出すテキストをそのまま信じます。カウンターに_totalがなかったり、単位がミリ秒で混ざっていたりすると、ダッシュボードとルールが違う意味で読み、バケットが累積でなければ、分位数が静かに間違います。ラベル1つとバケット数個が、時系列をいくつに増やすのかも、取り込んでみるまで実感がわきません。リンターが捕まえるものと捕まえられないものを区別することが、計装レビューの出発点です。
用意されている環境
python3 /opt/fixtures/pca_exposition_lab.py initが、/root/pca-exposition/にlegacy.prom(規約に違反した古いエクスポーターの出力)とpayload-sizes.csv(リクエストサイズ40件)を置きます。lab-k8sイメージのpromtool 3.0.1で、check metrics(リント)とtsdb create-blocks-from openmetrics(ブロックの生成)を実際に実行します。Prometheusサーバーは起動しません。ステップ6・7のエクスポーターは、採点ツールが空きポートで一時的に起動してから終了するので、あなたが起動したプロセスは採点と無関係です。
ステップ
python3 /opt/fixtures/pca_exposition_lab.py initで材料を作ってから、promtool check metrics < /root/pca-exposition/legacy.promを実行します。/root/pca-exposition/01-lint.txtに、problems=(指摘された行数)、metrics=(指摘された指標名を、カンマ区切りで、重複なく)、missed_by_lint=(リントは静かだが、バケットが累積でないために間違っている系列の名前)を書いてください。/root/pca-exposition/fixed.promを作成して、legacy.promの5つの系列を移します。http_requestsはカウンターhttp_requests_totalにし(2つのサンプルは維持)、request_latency_msの212は、ゲージrequest_latency_secondsの0.212にし(HELPを追加)、queueDepthはqueue_depthに、cache_hits_totalはゲージcache_entriesに、job_duration_countはゲージbatch_jobs_runningにします。payload_bytesは移しません。promtool check metricsが、何も指摘しない状態にします。/root/pca-exposition/payload-sizes.csvのリクエストサイズで、ヒストグラムhttp_request_size_bytesを作成して、fixed.promの末尾に追加します。境界は100、1000、10000、+Infで、_sum・_countも書きます。各バケットは、その境界以下(境界を含む)のリクエストの累積個数です。リントは、引き続き指摘なしの状態にします。- fixed.promと同じサンプルを、OpenMetrics形式の
/root/pca-exposition/scrape.omに移します。すべてのサンプルの末尾にタイムスタンプ(秒、例: 1700000000)を付け、最後の行は# EOFです。promtool tsdb create-blocks-from openmetrics /root/pca-exposition/scrape.om /root/pca-exposition/tsdbで取り込んでから、/root/pca-exposition/04-import.txtに、series=(NUM SERIES)とsamples=(NUM SAMPLES)を書いてください。 /root/pca-exposition/cardinality.omに、http_request_size_bytesヒストグラムを、routeラベルの/checkout、/search、/uploadの3つの値で、有限の境界12個と+Infで書きます(パスごとに_sum・_countを含め、タイムスタンプと# EOFを付けます)。取り込む前に時系列の数を計算して、/root/pca-exposition/05-cardinality.txtのpredicted_series=に書き、取り込んだ結果をimported_series=に書いてください。/root/pca-exposition/exporter.pyを、標準ライブラリだけで作成します。環境変数PORT(なければ9464)の127.0.0.1で待ち受け、GET /work?d=초(プレースホルダーは秒数です)のたびに、カウンターdemo_jobs_processed_totalを1増やし、ヒストグラムdemo_job_duration_seconds(境界0.1、0.5、1、5)にdを記録します。GET /metricsは、Content-Type: text/plain; version=0.0.4で、HELP・TYPEを備えた公開形式を返します。採点ツールは、空きポートで新しく起動して、d=0.05、0.5、2、7を送ったあとでスクレイプし、リント・カウンターの増加・累積バケット・_sumを確認して終了します。- exporter.pyのカウンターに、
queueラベルを付けます。GET /work?d=초&queue=이름(プレースホルダーは秒数とキュー名です)のキュー名を使い、なければdefaultです。ラベルの値は、公開形式のルールに従って、バックスラッシュ・二重引用符・改行をエスケープします。採点ツールは、exports、say "hi"、c:\tmp、改行を含む名前を送り、promtoolが公開内容を受け入れるか、4つの名前が元の値のままで1回ずつ読み戻されるかを確認します。
参考
- テキスト形式では、カウンターのTYPE行に、
_totalまで含めた名前を書きます。OpenMetricsは、系列名とサンプル名を区別し、# EOFで終わります。 - よくある間違い: バケットを区間ごとの個数として書いてしまうこと、境界と同じ値を次のバケットに入れてしまうこと、ラベルの値をエスケープせずに行が壊れてしまうことです。
- promtoolのリントルールは、このバージョン(3.0.1)で見た結果です。他のバージョンでは、指摘の文言が異なることがあります。
- Exposition formats ・ Metric and label naming ・ Writing exporters
promtoolが拒否した6行
python3 /opt/fixtures/pca_exposition_lab.py initで材料を作ってから、promtool check metrics < /root/pca-exposition/legacy.promを実行します。/root/pca-exposition/01-lint.txtに、problems=(指摘された行数)、metrics=(指摘された指標名を、カンマ区切りで、重複なく)、missed_by_lint=(リントは静かだが、バケットが累積でないために間違っている系列の名前)を書いてください。
リンターは、名前・HELP・サフィックスの規約を見ます。ヒストグラムのバケットが累積かどうかは見ないので、_bucketの値をleの順に自分で読んでください。
名前と単位を規約に合わせる
/root/pca-exposition/fixed.promを作成して、legacy.promの5つの系列を移します。http_requestsはカウンターhttp_requests_totalにし(2つのサンプルは維持)、request_latency_msの212は、ゲージrequest_latency_secondsの0.212にし(HELPを追加)、queueDepthはqueue_depthに、cache_hits_totalはゲージcache_entriesに、job_duration_countはゲージbatch_jobs_runningにします。payload_bytesは移しません。promtool check metricsが、何も指摘しない状態にします。
カウンターだけが_totalで終わります。_count・_sum・_bucketは、ヒストグラムとサマリーが使うサフィックスです。単位は基本単位(秒・バイト)に変えて、値も一緒に換算します。
CSVから累積バケットを数え直す
/root/pca-exposition/payload-sizes.csvのリクエストサイズで、ヒストグラムhttp_request_size_bytesを作成して、fixed.promの末尾に追加します。境界は100、1000、10000、+Infで、_sum・_countも書きます。各バケットは、その境界以下(境界を含む)のリクエストの累積個数です。リントは、引き続き指摘なしの状態にします。
legacyのpayload_bytesは、区間ごとの個数を書いていて、累積ではありませんでした。le="+Inf"は、常に_countと同じです。
OpenMetricsで取り込んで時系列を数える
fixed.promと同じサンプルを、OpenMetrics形式の/root/pca-exposition/scrape.omに移します。すべてのサンプルの末尾にタイムスタンプ(秒、例: 1700000000)を付け、最後の行は# EOFです。promtool tsdb create-blocks-from openmetrics /root/pca-exposition/scrape.om /root/pca-exposition/tsdbで取り込んでから、/root/pca-exposition/04-import.txtに、series=(NUM SERIES)とsamples=(NUM SAMPLES)を書いてください。
OpenMetricsは、# EOFがなかったり、タイムスタンプがなかったりすると、取り込みを拒否します。ヒストグラム1つは、バケットごとに、そして_sum・_countがそれぞれ、時系列になります。
ラベル1つとバケット12個の価値
/root/pca-exposition/cardinality.omに、http_request_size_bytesヒストグラムを、routeラベルの/checkout、/search、/uploadの3つの値で、有限の境界12個と+Infで書きます(パスごとに_sum・_countを含め、タイムスタンプと# EOFを付けます)。取り込む前に時系列の数を計算して、/root/pca-exposition/05-cardinality.txtのpredicted_series=に書き、取り込んだ結果をimported_series=に書いてください。
時系列の数は、ラベル値の組み合わせの積です。ヒストグラム1つは、(境界の数 + 1)個のバケットと、_sum、_countを出します。
自作のエクスポーターをスクレイプしてみる
/root/pca-exposition/exporter.pyを、標準ライブラリだけで作成します。環境変数PORT(なければ9464)の127.0.0.1で待ち受け、GET /work?d=초(プレースホルダーは秒数です)のたびに、カウンターdemo_jobs_processed_totalを1増やし、ヒストグラムdemo_job_duration_seconds(境界0.1、0.5、1、5)にdを記録します。GET /metricsは、Content-Type: text/plain; version=0.0.4で、HELP・TYPEを備えた公開形式を返します。採点ツールは、空きポートで新しく起動して、d=0.05、0.5、2、7を送ったあとでスクレイプし、リント・カウンターの増加・累積バケット・_sumを確認して終了します。
バケットは、境界以下を累積して数えます。1つのリクエストは、自分より大きいすべての境界と+Infに加算されます。採点ツールがPORTを渡すので、ポートを固定しないでください。
キュー名に引用符が入ってきた
exporter.pyのカウンターに、queueラベルを付けます。GET /work?d=초&queue=이름(プレースホルダーは秒数とキュー名です)のキュー名を使い、なければdefaultです。ラベルの値は、公開形式のルールに従って、バックスラッシュ・二重引用符・改行をエスケープします。採点ツールは、exports、say "hi"、c:\tmp、改行を含む名前を送り、promtoolが公開内容を受け入れるか、4つの名前が元の値のままで1回ずつ読み戻されるかを確認します。
公開形式のラベル値でエスケープする文字は、3つだけです。順序が重要です。バックスラッシュを先に変換しないと、新しく入れたバックスラッシュが、もう一度変換されてしまいます。