prometheus-label-strategy について
Prometheusのラベル設計を評価・改善するためのガイドです。計装やスクレイプ設定の担当者向けに、時系列を区別するラベルを削除せず、発生源でカーディナリティを抑える方法を示します。
主な機能
- 01ラベルのカーディナリティとクエリ用途の評価
- 02ターゲットラベルとサンプルラベルの区別
- 03ラベル名と値の一貫性確認
- 04ヒストグラムのカーディナリティ影響の説明
- 05高頻度で変わるメタデータにinfoメトリクスを使用
活用シーン
- 01Prometheusメトリクスのラベル設計監査
- 02高カーディナリティを防ぐ計装の計画
- 03ラベル削除によるデータ異常の診断
- 04ヒストグラムとバージョンメタデータ設計の改善
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ grafana/ skills --skill prometheus-label-strategyインストール後、Claude Code で/prometheus-label-strategyを入力して読み込まれたか確認します。
詳細
Prometheus ラベル戦略の評価
Prometheus のラベル戦略に関する専門知識を持っています。Prometheus のラベルスキーマの評価、監査、設計、改善を求められた場合、またはカーディナリティの高騰を発生源で防ぐ方法について質問された場合は、このガイドに沿って、体系的で実行可能なアドバイスを提供してください。
このスキルの目的は、アプリケーションの計装とスクレイプの ターゲット ラベルにおいて、不適切なラベルが発生源から出ないようにして、ストレージに取り込まれる前に防ぐことです。メトリクスの出力後にラベルを取り除くことを目的とするものではありません。スクレイプ時に系列を一意にするラベルを削除すると、データがひそかに壊れるためです(以下の唯一のルールを参照)。Grafana Cloud にすでに存在する系列のコストを削減するには、ユーザーを adaptive-metrics スキルに案内してください。発生中のカーディナリティ急増を診断する場合は、prometheus-cardinality-troubleshooter に案内してください。
唯一のルール:系列を一意にするラベルは決して削除しない
スクレイプ時に、系列を一意にするラベルを削除することはできません。 pod も、instance も、実際の系列を区別するものは何も削除できません。これには、action: labeldrop を指定した metric_relabel_configs と、Alloy の同等の prometheus.relabel ルールも含まれます。
カーディナリティの削減につながるように見えますが、そうではありません。データをひそかに、そして永久に壊します。
- カウンターのリセットが混ざります。 2 つの Pod のカウンターが 1 つの系列にまとめられると、それぞれ独立した再起動が統合後の系列上で交互に記録されます。その結果、
rate()とincrease()は不正な値を返します。多くの場合、各 Pod の再起動がカウンターのリセットとして扱われるため、異常に大きな値になります。 - DPM は減るどころか増加します。 同じスクレイプで複数のサンプルが同一の系列に記録されるようになり、サンプルの重複、順不同エラー、1 分あたりのサンプル数の増加が発生します。数週間後に「DPM がこんなに高いのはなぜか?」や「
rate()が異常な値を返すのはなぜか?」と尋ねられても、データにはどこで壊れたのかを示す証拠が残っていません。 - 集計は粗くなるだけでなく、誤ったものになります。 削除したラベルに対する
sumは、系列がどのように統合されたかによって、ひそかに二重計上したり、過少計上したりします。
厄介なのは、設定時に何のエラーも発生しないことです。パイプラインは稼働し続けますが、数値がひそかに誤ったものになり、問題が発生した時点は後から特定できません。
正しい対処法は、次の順です。
- 不適切なラベルを最初から出力しない — アプリケーションコードを修正してください。系列がそもそもそのラベルによって一意になっていなければ、影響なくラベルを削除できる唯一の方法です。
- すでに Grafana Cloud に送られていて、発生源で修正できない系列には → Adaptive Metrics。 まさにそのための機能です。ラベルを無差別に削除するのではなく、カウンターのリセットを考慮し、監査証跡を記録し、元に戻せる形で、系列を正しく集約します。ユーザーを
adaptive-metricsスキルに案内してください。
metric_relabel_configs にも、限定的ながら安全な用途がいくつかあります(不要なメトリクスを全体ごと削除する、ターゲットラベルと完全に重複するラベルを削除するなど)。これらは発生源での防止で説明しています。ただし、識別用ラベルを削除してカーディナリティを下げることは、決して安全な用途ではありません。
コア概念
時系列は Prometheus の基本単位です。メトリクス名とラベルのキーと値のペアの組み合わせが異なると、それぞれ新しいアクティブな時系列が作成されます。時系列が多すぎると、メモリへの負荷、クエリの遅延、取り込みへの負荷、請求額の増加につながります。
カーディナリティとは、ラベルが取り得る一意な値の数です。メトリクスの時系列の合計数は、ラベルごとのカーディナリティの積とほぼ等しくなります。path(100 個の値)、status_code(10 個の値)、method(5 個の値)、instance(50 個の値)を持つメトリクスの場合、メトリクスあたり 250,000 個の時系列になります。カーディナリティの高いラベルをもう 1 つ追加すると、件数が 10~100 倍になることもよくあります。
二重影響のルール:カーディナリティの高いラベルは、次の両方の処理経路に悪影響を及ぼします。
- 取り込み経路:アクティブな時系列の増加 → head ブロックの拡大、WAL の増大、メモリ使用量の増加、remote_write ペイロードの増大、Grafana Cloud の請求額増加(アクティブな時系列 + DPM)
- クエリ経路:PromQL 演算子(
sum by、rate、結合)は、一致する時系列をメモリ上に展開する必要があります。カーディナリティが高いと、クエリのメモリ使用量とレイテンシが急増します。
時系列の入れ替わりは、気づかれにくい厄介な問題です。ラベル値が頻繁に変わる場合(デプロイバージョン、ポッド名、一時的な ID など)、変更のたびに新しい時系列が作成され、古い時系列は時間の経過とともに消えていきます。1 日あたりの入れ替わり率が 100%の場合、保持期間中は定常状態の時系列数のおよそ 2 倍を抱えることになります。
ラベルを追加する際に確認すべき重要な問い:「このメトリクスを使うクエリでは、このラベルを確実に指定するか、集約するか?」答えが「いいえ」なら、そのラベルを追加してはいけません。
ラベル評価フレームワーク
ラベルセットを監査するときは、各ラベルを次の基準で評価してください。
カーディナリティの評価
| ラベルの例 | カーディナリティ | 判定 |
|---|---|---|
env(prod/staging/dev) | 2~5 個の値 | ✅ 適切 |
job(Prometheus のスクレイプジョブ) | 5~50 個の値 | ✅ 適切 |
cluster、region | 数十個 | ✅ 適切 |
namespace(K8s) | 数十~数百個程度 | ✅ 許容範囲 |
service、workload、container | 数十~数百個 | ✅ 許容範囲 |
instance(host:port) | 数百~数千個程度 | ⚠️ 評価が必要 — インスタンス単位のメトリクスでは問題ありませんが、集約されたメトリクスではリスクがあります |
pod(K8s) | 数千個以上 + 一時的な値による高い入れ替わり | ⚠️ K8s の監視と時系列の一意性に必要なため、維持してください。pod 単位の時系列のコストが高すぎる場合は、Adaptive Metrics で削減してください。スクレイプ時に絶対に削除しないでください |
path / route(HTTP) | テンプレート化されていれば上限あり、生の URL では上限なし | ⚠️ テンプレート化された値(/users/:id)の場合に限ります |
version、image_tag、git_sha | デプロイごとに増加 → 入れ替わり | ⚠️ 必要な場合にのみ使用し、info メトリクスパターンを検討してください |
user_id、request_id、trace_id | 上限なし | ❌ ラベルとしては絶対に使用しないでください。代わりにエグゼンプラーを使用してください |
customer_id、tenant_id | 多くの場合、上限なし | ❌ テナント数が少なく固定されている場合に限り許容できます |
error_message、query、sql | 上限のないテキスト | ❌ 絶対に使用しないでください |
アクセスパターンとの整合性
各ラベルについて、次の点を確認してください。
- このメトリクスへのクエリでは、このラベルによる集約やフィルタリングが確実に行われますか?
- このラベルは、ユーザーが考える方法でメトリクスを論理的に区分しますか?
- このラベルを削除すると、ユーザーは代わりにエグゼンプラー、ログ、トレースを使う必要がありますか?まれな検索ケースで、それを許容できますか?
静的なラベル値と動的なラベル値
- 静的ラベル/ターゲットラベル(例:
relabel_configsでスクレイプ対象ごとに一度設定するenv=prod、cluster=us-east、team=payments)は、リクエスト数ではなくターゲット数に比例してカーディナリティを増やします。低コストで価値が高いため、自由に使用してください。 - 動的ラベル/サンプルラベル(例:アプリケーションが計測ごとに出力する
status_code、method、cache_hit)は、値の数に応じてカーディナリティを増大させます。値の候補は一桁、または数十個程度に抑えてください。信頼できる情報源はアプリケーションコードです。Prometheus ではなく、アプリケーションコードを修正してください。
一貫性の確認
- ラベルの名前はサービス間で一貫していますか?(
status、status_code、http_statusのように異なると、別々のラベル群になり、結合が壊れます) - ラベルの値は正規化されていますか?(
200と"200"、GETとget、Errorとerror) - 命名規則は一貫していますか?Prometheus の規約では、メトリクス名とラベル名の両方に
snake_caseを使用します。 - 同じ概念には、サービス間で同じ名前を使っていますか?(
service、svc、app_name)
ヒストグラムのバケット管理(重要、見落とされがち)
すべてのヒストグラムメトリクスでは、基本カーディナリティに (バケット数 + 3) が乗算されます。バケットは _bucket{le="..."} に加え、_sum、_count、_created(Prometheus 2.39+)で構成されます。
- デフォルトの
prometheus.DefBucketsはバケットが11個あるため、14倍の乗数になります。 method、path、statusを持つヒストグラムがすでに1,000シリーズある場合、ヒストグラムのカーディナリティを加えると 14,000シリーズになります。- まず、ヒストグラムのラベルカーディナリティを必ず削減してください。ヒストグラムでは、ラベルの影響はカウンターやゲージの14倍です。
- バケットごとに1つのシリーズを使う代わりに、単一のスパースシリーズを使うネイティブヒストグラム(Prometheus 2.40+)を検討してください。高解像度のレイテンシー追跡で、カーディナリティを大幅に削減できます。
情報メトリクスのパターン(頻繁に変わるメタデータ向け)
version、git_sha、image_tag などのラベルをすべてのメトリクスに付けずに、その情報を把握したい場合は、情報メトリクスを使用します。
# A single low-cardinality counter/gauge of value 1, with the metadata attached
app_build_info{app="payment-api", version="2.4.1", git_sha="a1b2c3"} 1
次に、クエリ時に結合します。従来の方法では、group_left を使ってベクトルマッチを行います。
sum by (version) (
rate(http_requests_total{app="payment-api"}[5m])
* on (app) group_left (version) app_build_info
)
version ラベルはビルドごとに1つだけ存在するシリーズに付き、すべてのメトリクスには付きません。
info() 関数(より簡単な結合)
PromQL の info() 関数(実験的機能、Prometheus 3.0+。--enable-feature=promql-experimental-functions で有効化)は、情報メトリクスの結合を自動化するため、* on (...) group_left (...) マッチを手書きする必要がありません。
info(
rate(http_requests_total{app="payment-api"}[5m]),
{version=~".+"}
)
info(v, [labelselector]) はレンジベクトルまたはインスタントベクトル v を受け取り、各シリーズに対して一致する情報メトリクスを検索し、そのラベルを追加します。省略可能な第2引数は、付与する情報ラベルを制限するラベルマッチャーです(ここでは version のみ)。デフォルトでは、info() は標準の target_info メトリクスを対象に結合し、識別ラベル(例:instance、job)でマッチするため、OpenTelemetry 形式の target_info では特に使いやすくなっています。app_build_info などのカスタム情報メトリクスでは、上記の明示的な group_left 形式が依然として最も移植性に優れています。
Prometheus 3.x を使用し、target_info と結合する場合は info() を優先してください。それ以前のバージョン、カスタム情報メトリクス、または実験的機能のフラグが有効になっていない場合は、明示的な group_left マッチを使用してください。
評価結果の形式
ラベルセットを監査する際は、次の形式でレポートを作成してください。
## Prometheus Label Strategy Audit
### Summary
[1-2 sentence overall assessment — total estimated active series, biggest risks]
### Per-Label Analysis
| Metric Family | Label | Cardinality | Used in Queries? | Verdict | Action |
|---|---|---|---|---|---|
| http_requests_total | path | Unbounded (raw URLs) | Sometimes | ❌ Remove | Template in code: `/users/:id` not `/users/12345` |
| http_requests_total | pod | High + churn | Rarely | ⚠️ Keep — makes the series unique | If too expensive, aggregate away with Adaptive Metrics; query by `workload` for the common case |
### Histogram-Specific Findings
[Highlight any histograms with high label cardinality — these are 14×+ amplified]
### Estimated Impact
- Active series reduction: [X series → Y series]
- DPM reduction: [X DPM → Y DPM] (samples-per-minute = series × ~6 at 10s scrape)
- Memory impact: [if measurable]
### Recommended Label Set
[Final recommended labels per metric family]
### Implementation Plan
1. [Code changes — instrumentation hygiene: stop emitting bad labels at the source]
2. [Scrape target labels — relabel_configs (additive: env, cluster, team, workload)]
3. [Post-ingest cost reduction on series you can't fix at the source — Adaptive Metrics]
4. [Recording rules to materialize useful aggregates]
推奨される共通ターゲットラベル
これらはターゲットラベルとして設定してください(アプリケーションから出力するのではなく、スクレイプジョブの relabel_configs を使います)。ターゲットごとに設定し、カーディナリティが低く、クエリでの価値が高いラベルです。
| ラベル | 用途 | 備考 |
|---|---|---|
job | Prometheus のスクレイプジョブ名 | Prometheus によって自動設定されます |
instance | ターゲットのエンドポイント(host:port) | 自動設定されます。必要に応じて、relabel_configs でより分かりやすい値に変更できます |
env | 環境(prod、staging、dev) | static_configs のラベルまたはサービスディスカバリーで設定します |
cluster | 複数クラスターの区別 | フェデレーション/Mimir のマルチテナント構成では不可欠です |
region | 地理的リージョン | |
team / squad | 所有者。アクセス制御にも役立ちます | |
service | 論理サービスの識別 | 1つのサービスが複数のジョブにまたがる場合があります |
これらをアプリケーションから再出力しないでください。アプリが cluster ラベルを出力すると、ターゲットラベルと重複して衝突が発生し、避けたい honor_labels の判断が必要になります。
Kubernetes のパターン
推奨ラベル(kubernetes_sd_configs から)
| ラベル | ソース | 備考 |
|---|---|---|
namespace | Pod メタデータ | 必ず保持します |
container | Pod spec | カーディナリティが低く、複数コンテナの Pod で役立ちます |
workload | 派生値:{controller_kind}/{controller_name} | podと併せて安定した集約キーとして追加します。静的で予測可能です。これは追加であり、置き換えではありません。podを削除する口実にしてはいけません |
service | K8s Service | Service 経由でスクレイピングする場合 |
podラベルの扱い
podはカーディナリティが高く、一時的なラベルです。デプロイや再起動のたびに変わるため、変動と系列数が大幅に増加します。一方で、K8s の系列を一意にするラベルでもあり、Kubernetes のモニタリング(Pod ごとのリソース割り当て、kube-state-metrics との結合)には欠かせません。唯一のルールに従い、**スクレイピング時にpodを削除してはいけません。**Pod を1つの系列にまとめると、カウンターのリセットが混在し、rate()が正しく動作しなくなります。
代わりに、次のようにします。
relabel_configsを使って、{controller_kind}/{controller_name}のworkloadをターゲットラベルとして追加します。これにより、podに触れることなく、ダッシュボードやアラートで安定したワークロード ID を使って集約(sum by (workload))できます。これは追加であり、何も削除しません。- **アプリケーションコードから
podを出力しないでください。**Kubernetes サービスディスカバリーから取得することで、信頼できる情報源を1つだけにします(下記参照)。 - Grafana Cloud で
podレベルの系列が本当に高コストな場合は、Adaptive Metricsを使って正しく(取り込み後に、カウンターのリセットを考慮し、元に戻せる形で)podを集約し、スクレイピング時に生データを破損させないようにします。adaptive-metricsスキルに振り分けてください。
エフェメラルなフィールドを最初からラベルにマッピングしない
**uid**は Pod を再作成するたびに再生成され、正当なクエリ用途がありません。対処法は、ラベルにマッピングしないことです。relabel_configsから除外してください。(明示的に対象にしない限り、デフォルトのkubernetes_sd_configs出力には含まれません。)後からlabeldropしようとしてはいけません。その時点ではすでに系列を区別しており、削除するとほかの一意なラベルを削除した場合と同じようにデータが破損します。
ターゲット ID の情報源は1つにする
instance、pod、node、hostは、アプリケーションコードではなく、スクレイピングターゲットのラベルから取得してください。アプリケーションが独自のinstanceやnodeも出力すると、重複が発生し、honor_labelsとの衝突が起きます。対処法はアプリケーション側でそれらの出力を停止することであり、スクレイピング時にlabeldropすることではありません。(ターゲットラベルと完全に重複するラベルを削除する場合に限り、狭い範囲で例外となります。metric_relabel_configsを参照してください。)
kube-state-metrics のラベル伝播 ⚠️
kube_pod_labels{label_app_kubernetes_io_*=...}には、数十個のメタデータラベルが含まれることがあります- Pod のラベルの組み合わせが一意になるたびに、新しい系列が作成されます
- kube-state-metrics の
--metric-labels-allowlistを使ってソース側で制限してください。これにより、そもそも出力される内容が制御されます。つまり、後から破壊的に削除するのではなく、事前に防止できます
ソース側での防止:何をどこで修正するか
5つの対処方法があり、推奨順に並んでいます。
1. アプリケーションで修正する(最善)
アプリケーションが出力する不適切なラベルが根本原因です。例:
- HTTP パス:生のパスではなく、テンプレート化されたルート(
/users/:id)を使います - エラーメトリクス:エラーメッセージの文字列ではなく、小規模な列挙型(
error_type="timeout")を使います - ユーザー単位のメトリクス:
user_idを含めず、エグザンプラーでログやトレースを参照します - 自由形式の入力:ユーザーが指定した文字列をラベル値として出力してはいけません
コードを管理している場合、これが常に適切な修正方法です。これにより、下流のあらゆるシステム(Prometheus、remote_write、Mimir、Grafana Cloud)でコストを削減できます。
2. relabel_configs(ターゲット時の再ラベル付け)
スクレイプの前に実行されます。次の用途に使います。
- 検出されたターゲットにターゲットラベル(
env、cluster、team)を設定する - スクレイプしたくないターゲット全体を除外する
instanceをわかりやすい値に書き換える- サービスディスカバリのメタデータから識別情報を追加する
scrape_configs:
- job_name: my-app
kubernetes_sd_configs:
- role: pod
relabel_configs:
# Set workload from controller metadata
- source_labels: [__meta_kubernetes_pod_controller_kind, __meta_kubernetes_pod_controller_name]
target_label: workload
separator: /
# Set env from a pod label
- source_labels: [__meta_kubernetes_pod_label_env]
target_label: env
# Only scrape pods explicitly opted in
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
regex: "true"
action: keep
3. Adaptive Metrics(Grafana Cloud — 取り込み後にカーディナリティを安全に削減する方法)
カーディナリティが構造に起因し、ソース側では修正できない場合、つまりラベルが正当に存在して系列を一意にしているものの、すべての値をフル解像度で必要としていない場合は、Adaptive Metrics が適切なツールであり、すでに存在する系列のコストを安全に削減する唯一の方法です。
取り込み後に、Grafana Cloud で集約ルールとして適用されます。重要なのは、系列を正しく集約することです。
- カウンターのリセットを適切に処理するため、
rate()とincrease()の精度が維持されます。 - 何が集約されたかが記録されるため、監査証跡が残り、後から「なぜこれが変わったのか?」を確認できます。
- 元に戻せます。ルールを削除すると、フル解像度の系列が復元されます。
これは、「データのコストが下がった」(Adaptive Metrics)ことと、「データが不正確になった」(スクレイプ時の labeldrop)ことの違いです。ルールの設計には、ユーザーを adaptive-metrics スキルに案内してください。
4. metric_relabel_configs(限定的かつ安全な用途のみ)
スクレイプの後、ストレージへの保存の前に実行されます。
⚠️ 系列を区別するラベル(
pod、instance、user_id、pathなど)を削除するために、metric_relabel_configs(または Alloy のprometheus.relabel)を使わないでください。 唯一のルールを参照してください。カーディナリティの修正に見えますが、rate()を気づかれないまま壊し、DPM を増加させ、集約を破損させます。代わりにアプリケーションコード(レバー 1)または Adaptive Metrics(レバー 3)を使ってください。同じ注意は、スクレイプ時にラベル値を正規化する場合(たとえばstatus_codeを2xxにまとめる場合)にも当てはまります。異なる系列が統合され、サンプル重複エラーが発生します。この処理はコード内または Adaptive Metrics で行い、ここでは決して行わないでください。
本当に安全な用途は次のとおりです。
- 保存したくないメトリクス全体を除外する — 異なる系列を 1 つにまとめるのではなく、メトリクス全体を破棄します。
metric_relabel_configs: - source_labels: [__name__] regex: my_app_request_details action: drop - ターゲットラベルと完全に重複するラベルを削除する。 アプリが独自の
cluster/instanceを出力していて、それがスクレイプターゲットからすでに取得されている場合、ターゲットラベルが引き続き一意性を保つため、重複を削除しても問題はありません。アプリを修正するのが望ましいですが、これは安全な暫定措置です。
以上がすべてです。系列数を減らすために metric_relabel_configs を使おうとしているなら、ほぼ間違いなく代わりに Adaptive Metrics を使うべきです。
5. Recording Rules(クエリ時のカーディナリティ削減)
コストの高い系列を、カーディナリティの低い記録済み系列に事前集約します。同じデータポイント密度で保存しながら、系列数を大幅に減らせます。
groups:
- name: http-requests-aggregates
interval: 30s
rules:
# Drop pod/instance dimension; keep only service-level rollup
- record: service:http_requests:rate5m
expr: sum by (service, env, cluster, status_code) (rate(http_requests_total[5m]))
ロールアップを対象とするクエリは、大幅に低コストになります。元の系列は引き続き存在します。Recording Rules は取り込みコストを削減しません(その場合はAdaptive Metricsを使ってください — スクレイプ時の labeldrop ではありません)。Recording Rules が削減するのはクエリコストです。
インストルメンテーションの衛生管理(アプリ開発者向け)
ユーザーがインストルメンテーションコードを記述する場合は、次のルールに従ってください。
| ルール | 理由 |
|---|---|
| 上限のないユーザー入力をラベル値として使わない | email、user_id、query string、error message は、カーディナリティ問題の最大の原因です |
| 記録する前に HTTP パスをテンプレート化する | /users/12345 ではなく /users/{id} を使います。多くのフレームワークではルーティングメタデータを使ってこれを実現できます |
| エラーラベルの値は小規模な列挙型に制限する | error="connection to db-shard-7 timed out at 14:32:09" ではなく、error_type="timeout" を使います |
すべてのメトリクスに version / git_sha / build_id を付けない | 情報メトリクスを使い、クエリ時に結合してください |
コードから pod / node / host を出力しない | スクレイプターゲットから取得されます。重複させると衝突が発生します |
| 動的に構築されるラベルの名前(キー)は避ける | metric{[user]=1} は上限を設定できません。固定キーを使ってください |
| ヒストグラムは控えめに使い、先にラベルを絞り込む | カーディナリティが 14 倍に増幅されます |
| トレースとの関連付けにはラベルよりエグザンプラーを優先する | エグザンプラーはカーディナリティを増やさずに trace_id を保持します |
エグザンプラー(最後の手段)
エグザンプラーは、特定のサンプルに trace_id(または任意のキーと値のペア)を、ラベルのディメンションにせずに付加します。カーディナリティの高い関連データを格納するのに最適です。
OpenMetrics 形式、Prometheus 2.26+、スクレイプ設定が必要です:
scrape_configs:
- job_name: my-app
enable_protobuf_negotiation: true
# Or for text-format:
follow_redirects: true
また、Prometheus サーバー側では次の設定が必要です:
storage:
exemplars:
max_exemplars: 100000
エグザンプラーは次の用途に使います:
trace_idの関連付け(Tempo、Jaeger)- 特定のデバッグ検索に使う
request_id - 必要なときに役立つ、頻度の低いキー全般
エグザンプラーのクエリには、PromQL による集計ではなく、Grafana のグラフ上でエグザンプラーを表示する機能を使ってください。
80/20 の法則
最も大きな効果が得られる改善は、ほぼ常に次の 5 つです。
- アプリケーション層で上限のないラベルを削除する — テンプレート化されていない
path、user_id、error_messageが対象です。これが最も大きな効果をもたらします。 - 何よりも先にヒストグラムのラベルのカーディナリティを減らす — すべてのヒストグラムで 14 倍に増幅されます。
- アプリケーションコードから
pod/instance/nodeを出力しない — スクレイプターゲットから取得し、集計用に安定したworkloadターゲットラベルを追加します。(カーディナリティを下げるためにスクレイプ時に実際のpodを削除しないでください。代わりに Adaptive Metrics を使います。) version/git_sha/image_tagには情報メトリクスを使う — デプロイごとに発生する変動をなくせます。- ターゲットラベルはアプリケーションコードではなく
relabel_configsで設定する —env、cluster、team、serviceをアプリケーションから出力してはいけません。
何よりもまず、これらに取り組んでください。
避けるべきラベル — クイックリファレンス
| ラベル | 理由 | 代替手段 |
|---|---|---|
user_id、customer_id(テナント数が多い場合) | 上限がありません | エグザンプラーを使う。tenant_tier で集計する |
request_id、trace_id | 上限がありません | エグザンプラーを使う |
path / route(未加工の URL) | 上限がありません | コード内でテンプレート化する:/users/:id |
error_message、query、sql | 上限のないテキストです | 値を制限した error_type 列挙型を使う |
version、git_sha、image_tag(すべてのメトリクスに付与) | デプロイごとに変動します | 情報メトリクスのパターンを使う |
アプリケーションから出力する pod(SD と重複) | コードではなく、K8s サービスディスカバリーから取得する必要があります | コードからの出力をやめ、検出された pod は保持します。カーディナリティを下げるために実際の pod を削除しないでください。Adaptive Metrics を使ってください |
uid(K8s) | 上限がなく、再起動時に再生成されます | そもそもラベルにマッピングしないでください(relabel_configs に含めないでください) |
アプリケーションから出力する instance、node、host | スクレイプターゲットから取得する必要があります | コードからの出力をやめてください(スクレイプ時に削除しても安全なのは、ターゲットラベルとの完全一致の重複だけです) |
| 動的に命名されるラベルキー | 値の上限を設定できません | 固定キーと、値の上限設定を使ってください |
ヒストグラムの未加工の status_code | 14 倍に増幅されます | status_class(2xx、4xx、5xx)にまとめてください |
別のスキルに切り替えるタイミング
- 「Grafana Cloud の請求額を減らしたい」/「すでに取り込まれた系列のカーディナリティを下げたい」 →
adaptive-metricsスキルを活用します(取り込み後の集約ルールです。安全で、カウンターのリセットを考慮した方法です。スクレイプ時に区別用のラベルへlabeldropを決して適用しないでください) - 「DPM を増加させているメトリクスはどれですか?」 →
dpm-finderスキルを活用します - 「Prometheus がメモリ不足で停止する/現在スクレイプに失敗している」 →
prometheus-cardinality-troubleshooterスキルを活用します - 「問題のあるメトリクスを見つけるクエリはどう書けばよいですか?」 →
promqlスキルを活用します - 「Alloy でリラベルルールを設定するにはどうすればよいですか?」 →
alloyスキルを活用します
このスキルが担当するのは戦略と設計です。ほかのスキルは診断と運用上の修正を担当します。