mcpField
P
promql-validator

promql-validator

github.com/akin-ozerクラウド・DevOps329612 回インストール16 週間前に更新
リポジトリ

promql-validator について

promql-validatorは、PromQLクエリを検証して動作を説明するスキルです。構文・意味の確認、アンチパターン検出、最適化案の提示を行い、対話形式でクエリと目的を照合します。

主な機能

  1. 01PromQL構文の検査
  2. 02メトリクス型の使い方とクエリの意味を確認
  3. 03アンチパターンと性能上の問題を検出
  4. 04クエリと出力ラベルを説明
  5. 05対話形式でクエリを改善

活用シーン

  1. 01ダッシュボードに追加する前のクエリ検証
  2. 02非効率なフィルターや集約の特定
  3. 03監視目的とクエリの動作の照合

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/akin-ozer/cc-devops-skills --skill promql-validator

インストール後、Claude Code で/promql-validatorを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

docs/
anti_patterns.md
best_practices.md
examples/
bad_queries.promql
good_queries.promql
optimization_examples.promql
scripts/
check_best_practices.py
test_validators.py
validate_syntax.py

詳細

このスキルの仕組み

このスキルは、複数レベルの検証を実行し、対話型のクエリ計画を提供します。

  1. 構文検証:PromQL 式の構文が正しいか確認します
  2. 意味検証:クエリに論理的な整合性があるか確認します(例:ゲージではなくカウンターに対して rate() を使用しているか)
  3. アンチパターンの検出:よくある間違いや非効率なパターンを特定します
  4. 最適化の提案:パフォーマンス改善を提案します
  5. クエリの説明:PromQL を平易な英語に変換します
  6. 対話型の計画:ユーザーが意図を明確にし、クエリを改善できるよう支援します

ワークフロー

ユーザーが PromQL クエリを提示したら、次のワークフローに従います。

作業ディレクトリの要件

相対パスが正しく解決されるよう、リポジトリのルートから検証コマンドを実行してください。

cd "$(git rev-parse --show-toplevel)"

別の場所から実行する場合は、scripts/ ファイルに絶対パスを使用してください。

ステップ 1:構文を検証する

構文検証スクリプトを実行して、基本的な正しさを確認します。

python3 devops-skills-plugin/skills/promql-validator/scripts/validate_syntax.py "<query>"

出力の解析に関する注意:

  • 終了コード 0:構文は有効です
  • 終了コードが 0 以外:構文エラーです。stderr を含め、問題のトークン/位置を特定してください
  • まず、最小限の問題箇所を引用し、その後に修正済みのクエリを提示してください

スクリプトでは、次の項目を確認します。

  • 有効なメトリクス名とラベルマッチャー
  • 演算子の正しい使用方法
  • 関数構文の適切さ
  • 有効な時間の長さと範囲
  • 括弧と引用符の対応
  • 修飾子(offset、@)の正しい使用方法
ステップ 2:ベストプラクティスを確認する

ベストプラクティスチェッカーを実行して、アンチパターンと最適化の機会を検出します。

python3 devops-skills-plugin/skills/promql-validator/scripts/check_best_practices.py "<query>"

出力の解析に関する注意:

  • スクリプトの各セクションを個別の指摘(カーディナリティ、メトリクス型の誤用、正規表現の誤用など)として扱います
  • スクリプトの出力が空でも、クエリが複雑な場合は手動で健全性を確認し、manual-review として記載してください
  • 指摘ラベルにはスクリプトの文言をそのまま使用し、その後に平易な英語で修正方法を加えてください

スクリプトでは、次の項目を特定します。

  • ラベルフィルターがない高カーディナリティのクエリ
  • 完全一致に置き換えられる非効率な正規表現マッチャー
  • カウンターメトリクスに対する rate()/increase() の不足
  • ゲージメトリクスに対する rate() の使用
  • 事前計算済み分位数の平均化
  • 時間範囲が過度に長いサブクエリ
  • 長い時間範囲に対する irate() の使用
  • より具体的なラベルフィルターを追加する機会
  • レコーディングルールを使用すべき複雑なクエリ
ステップ 3:クエリを説明する

クエリを解析し、何をするものか平易な英語で説明します。

  • どのメトリクスがクエリ対象か
  • それらがどの種類のメトリクスか(カウンター、ゲージ、ヒストグラム、サマリー)
  • どの関数が適用され、その理由は何か
  • クエリが何を計算するか
  • 出力にどのラベルが含まれるか
  • 期待される結果の構造

必須の出力詳細(必ず明示してください):

**Output Labels**: [list labels that will be in the result, or "None (fully aggregated to scalar)"]
**Expected Result Structure**: [instant vector / range vector / scalar] with [N series / single value]

例:

**Output Labels**: job, instance
**Expected Result Structure**: Instant vector with one series per job/instance combination
行番号による引用方法(必須)

推奨事項で例やドキュメントを引用する場合は、ファイルパスと 1 から始まる行番号を含めてください。

examples/good_queries.promql:42
docs/best_practices.md:88

ルール:

  • 最も関連性の高い 1 行(複数行のスニペットの場合は開始行)を引用してください
  • 引用は必要な範囲にとどめ、ファイル全体を引用しないでください
  • 行番号がわからない場合は、line number unavailable と記載し、ファイルパスを示してください
Step 4: 対話形式でクエリを計画する(フェーズ 1 - 停止して待機)

クエリがユーザーの意図に合っているか確認するため、ユーザーに確認の質問をします。

  1. 目標を把握する:「何を監視または測定しようとしていますか?」

    • リクエスト率、エラー率、レイテンシ、リソース使用率など
  2. メトリクスの種類を確認する:「これはカウンター(常に増加する)、ゲージ(増減する)、ヒストグラム、サマリーのどれですか?」

    • 使用する関数に影響します
  3. 時間範囲を明確にする:「どの時間範囲が必要ですか?」

    • 瞬時値、時間経過に伴うレート、履歴分析
  4. 集計方法を確認する:「ラベルをまたいでデータを集計する必要がありますか?必要な場合、どのラベルですか?」

    • by (job)、by (instance)、without (pod) など
  5. 出力の用途を確認する:「アラート、ダッシュボード、アドホック分析のどれに使用しますか?」

    • 最適化の優先事項に影響します

重要:2 段階の対話

ステップ 1~4 の結果(構文、ベストプラクティス、クエリの説明、意図を確認する質問)を提示した後:

⏸️ ここで停止し、ユーザーの応答を待ってください

ユーザーが確認の質問に答えるまで、ステップ 5~7 に進まないでください。 これにより、後続の推奨事項をユーザーの実際の意図に合わせられます。

Step 5: 意図と実装を比較する(フェーズ 2 - ユーザーの応答後)

ステップ 4 の確認の質問にユーザーが回答した後にのみ、このステップに進んでください。

ユーザーの意図を把握した後:

  • 現在のクエリが実際に何を行うか説明する
  • 意図と実装の不一致があれば強調する
  • クエリが目標に合っていない場合は修正を提案する
  • 該当する場合は代替案を提示する

該当する場合は、既知の制限事項について言及してください。

  • メトリクスの種類の判定がヒューリスティックに基づく場合は、その旨を伝えます(例:「スクリプトは _bytes 接尾辞に基づいて、これがゲージだと推定しました。正しいか確認してください。」)
  • カーディナリティに関する警告が誤検知の可能性がある場合は、その点を認めます(例:「レコーディングルールを使用している場合や、カーディナリティが低いと分かっている場合、この警告は該当しない可能性があります。」)
Step 6: 最適化を提案する

検証結果に基づいて:

  • より効率的なクエリパターンを提案する
  • 複雑なクエリや繰り返し使用するクエリには、レコーディングルールを推奨する
  • カーディナリティを抑えるため、より適切なラベルマッチャーを提案する
  • 適切な時間範囲について助言する

参考例:修正を提案するときは、次の形式で関連する例を引用してください。

As shown in `examples/bad_queries.promql` (lines 91-97):
❌ BAD: `avg(http_request_duration_seconds{quantile="0.95"})`
✅ GOOD: Use histogram_quantile() with histogram buckets

引用元:

  • examples/good_queries.promql - 適切な形式のパターン
  • examples/optimization_examples.promql - 修正前後の比較
  • examples/bad_queries.promql - 避けるべき例
  • docs/best_practices.md - 詳細な説明
  • docs/anti_patterns.md - アンチパターンの詳細な解説

引用形式:file_path (lines X-Y) と関連するコードスニペットの引用

Step 7: ユーザーが計画・調整できるようにする

ユーザーに主導権を委ねます。

  • クエリを変更するかどうか尋ねる
  • パフォーマンスを向上させるための書き換えを支援すると申し出る
  • 該当する場合は、複数の代替案を提示する
  • さまざまなアプローチのトレードオフを説明する

主な検証ルール

構文ルール
  1. メトリクス名:[a-zA-Z_:][a-zA-Z0-9_:]* に一致する必要があります。または UTF-8 の引用構文(Prometheus 3.0+)を使用します。
    • 引用形式:{"my.metric.with.dots"}
    • name ラベルを使用:{__name__="my.metric.with.dots"}
  2. ラベルマッチャー:=(等しい)、!=(等しくない)、=~(正規表現に一致)、!~(正規表現に一致しない)
  3. 時間の長さ:[0-9]+(ms|s|m|h|d|w|y) - 例:5m、1h、7d
  4. レンジベクトル:metric_name[duration] - 例:http_requests_total[5m]
  5. オフセット修飾子:offset <duration> - 例:metric_name offset 5m
  6. @ 修飾子:@ <timestamp> または @ start() / @ end()
セマンティックルール
  1. rate() と irate():カウンターメトリクス(_total、_count、_sum、または _bucket で終わるメトリクス)にのみ使用してください。
  2. カウンター:通常、生の値ではなく rate() または increase() を使用してください。
  3. ゲージ:rate() または increase() を使用しないでください。
  4. ヒストグラム:le ラベルと、_bucket メトリクスに対する rate() を使用して histogram_quantile() を使ってください。
  5. サマリー:分位数の平均は取らず、_sum と _count から計算してください。
  6. 集計:出力ラベルを制御するには by() または without() を使用してください。
パフォーマンスルール
  1. カーディナリティ:時系列の数を減らすため、常に具体的なラベルマッチャーを使用してください。
  2. 正規表現:完全一致が可能な場合は、=~ ではなく = を使用してください。
  3. レート範囲:スクレイプ間隔の少なくとも 4 倍にしてください(通常、最小値は [2m])。
  4. irate():短い範囲(<5m)に最適です。長い期間には rate() を使用してください。
  5. サブクエリ:数百万件のサンプルを処理するような過度に長い時間範囲は避けてください。
  6. レコーディングルール:頻繁にアクセスする複雑なクエリには使用してください。

検出するアンチパターン

高カーディナリティの問題

❌ 悪い例:http_requests_total{}

  • フィルタリングせずに、すべての時系列に一致します。

✅ 良い例:http_requests_total{job="api", instance="prod-1"}

  • 具体的なラベルフィルターでカーディナリティを下げます。
正規表現の過剰使用

❌ 悪い例:http_requests_total{status=~"2.."}

  • 正規表現は遅く、精度も低くなります。

✅ 良い例:http_requests_total{status="200"}

  • 完全一致の方が高速です。
カウンターでの rate() の不足

❌ 悪い例:http_requests_total

  • カウンターの生の値は役に立ちません(常に増加します)。

✅ 良い例:rate(http_requests_total[5m])

  • レートは秒あたりのリクエスト数を示します。
ゲージでの rate()

❌ 悪い例:rate(memory_usage_bytes[5m])

  • ゲージは累積値ではなく、現在の状態を計測します。

✅ 良い例:memory_usage_bytes

  • ゲージの値をそのまま、または avg_over_time() とともに使用してください。
分位数の平均

❌ 悪い例:avg(http_request_duration_seconds{quantile="0.95"})

  • 事前に計算された分位数の平均を取ることは、数学的に無効です。

✅ 良い例:histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))

  • ヒストグラムのバケットから分位数を計算します。
過度に長いサブクエリ範囲

❌ 悪い例:rate(metric[5m])[90d:1m]

  • 数百万件のサンプルを処理するため、非常に遅くなります。

✅ 良い例:レコーディングルールを使用するか、範囲を必要な期間に制限してください。

長い範囲での irate()

❌ 悪い例:irate(metric[1h])

  • irate() は最後の 2 サンプルのみを見るため、範囲が無駄になります。

✅ 良い例:rate(metric[1h]) または irate(metric[5m])

  • 長い範囲には rate() を使用するか、irate() の範囲を短くしてください。
メトリクスタイプの混在

❌ 悪い例:avg(http_request_duration_seconds{quantile="0.95"}) / rate(node_memory_usage_bytes[1h]) + sum(http_requests_total)

  • サマリーの分位数、ゲージメトリクス、カウンターを算術演算で組み合わせています。
  • 意味のない結果になります。

✅ 良い例:各メトリクスタイプを目的別のクエリに分けてください。

  • レイテンシ:histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))
  • メモリ:node_memory_usage_bytes{instance="prod-1"}
  • リクエストレート:rate(http_requests_total{job="api"}[5m])

出力形式

次の構造で検証結果を提示してください。

## PromQL Validation Results

### Syntax Check
- Status: ✅ VALID / ⚠️ WARNING / ❌ ERROR
- Issues: [list any syntax errors with line/position]

### Semantic Check
- Status: ✅ VALID / ⚠️ WARNING / ❌ ERROR
- Issues: [list any logical problems]

### Performance Analysis
- Status: ✅ OPTIMIZED / ⚠️ CAN BE IMPROVED / ❌ INEFFICIENT
- Issues: [list optimization opportunities]
- Suggestions: [specific improvements]

### Query Explanation
Your query: `<query>`

This query does:
- [Plain English explanation]
- Metrics: [list metrics and their types]
- Functions: [explain each function]
- Output: [describe result structure]

### Intent Verification
Let me verify this matches your needs:

1. What are you trying to measure? [your goal here]
2. Is this a counter/gauge/histogram/summary? [metric type]
3. What time range interests you? [time window]
4. Do you need aggregation? If so, by which labels? [aggregation needs]
5. Is this for alerting, dashboarding, or analysis? [use case]

### Recommendations
[Based on the analysis, suggest improvements or alternatives]

対話

検証後、対話を続けてください。

Claude:「クエリを検証しました。構文は正しいですが、ラベルフィルターなしで http_requests_total をクエリしていることに気付きました。これにより、数千の時系列に一致する可能性があります。どのサービスまたはエンドポイントを監視しようとしていますか?」

User:[目的を提示]

Claude:「承知しました。それに基づいて、最適化したバージョンはこちらです:rate(http_requests_total{job="api-service", path="/users"}[5m])。これは、直近 5 分間の /users エンドポイントへのリクエストの秒あたりのレートを計算します。ご希望に合っていますか?」

User:[確認する、または変更を依頼する]

Claude:[改善したクエリまたは代替案を提示]

例

examples/ ディレクトリにある次のファイルを参照してください。

  • good_queries.promql:ベストプラクティスに従った、適切に記述されたクエリ
  • bad_queries.promql:よくある間違いやアンチパターン(修正例付き)
  • optimization_examples.promql:最適化前後の例

ドキュメント

docs/ ディレクトリにある次のファイルを参照してください。

  • best_practices.md:PromQL のベストプラクティスを網羅したガイド
  • anti_patterns.md:説明付きの詳細なアンチパターンリファレンス

重要な注意事項

  1. 対話的に対応する:ユーザーの意図を理解するため、必ず確認の質問をしてください
  2. 教育的に対応する:何が間違っているかだけでなく、なぜ間違っているのかを説明してください
  3. 役立つ対応をする:批判するだけでなく、クエリの書き換えを提案してください
  4. 状況を考慮する:ユーザーのユースケース(アラートかダッシュボードか)を考慮してください
  5. 徹底的に確認する:4 つすべてのレベル(構文、意味、パフォーマンス、意図)を確認してください
  6. 実用的に対応する:理論上の完璧さではなく、現実的な最適化を提案してください

統合

このスキルは次の用途で使用できます。

  • クエリレビューに単独で使用する
  • 監視設定時にアラートルールを検証する
  • 遅い Prometheus クエリのトラブルシューティングを行う
  • 記録ルールのコードレビューの一環として使用する
  • チームメンバーに PromQL を教える

検証ツール

このスキルでは、主に 2 つの Python スクリプトを使用します。

  1. validate_syntax.py:正規表現パターンを使用した純粋な構文チェック
  2. check_best_practices.py:意味とパフォーマンスの分析

どちらのスクリプトも、プログラムによる解析用の JSON と、表示用の人間が読みやすいメッセージを出力します。

成功基準

検証セッションが成功したといえるのは、次の条件を満たす場合です。

  1. すべての構文エラーを特定する
  2. 意味上の問題を検出する
  3. 該当する場合、少なくとも 1 つの最適化を提案する
  4. クエリが何をするのかを明確に説明する
  5. クエリがユーザーの意図に合っていることを確認する
  6. 実行可能な次のステップを提示する

既知の制限事項

検証スクリプトには、次のような制限事項があります。

メトリクスの型の検出
  • ヒューリスティックベース:メトリクスの型(カウンター、ゲージ、ヒストグラム、サマリー)は、命名規則(例:_total、_bytes)から推測されます
  • カスタムメトリクス:標準的でない名前のメトリクスは、正しく分類されない場合があります
  • 推奨事項:スクリプトでメトリクスの型を判断できない場合は、ユーザーに確認してください
高カーディナリティの検出
  • 保守的なアプローチ:スクリプトはラベルセレクターのないメトリクスに警告を出しますが、すべての系列をクエリすることが正当なユースケースもあります
  • 記録ルール:記録ルールのメトリクス(例:job:http_requests:rate5m)を使用するクエリは、ラベルフィルターがなくても有効です
  • 推奨事項:状況に応じて判断してください。ユーザーがカーディナリティを許容範囲内だと把握している場合は、警告を無視しても問題ありません
意味の検証
  • 実行時のコンテキストなし:メトリクスが実際に存在するか、ラベル値が有効かをスクリプトで検証することはできません
  • スキーマ非依存:特定の Prometheus のデプロイやメトリクススキーマに関する知識はありません
  • 推奨事項:本番環境で検証する場合は、実際の Prometheus インスタンスに対してクエリをテストしてください
スクリプトによる検出範囲

スクリプトはよくあるアンチパターンを検出しますが、次の問題は検出できません。

  • ビジネスロジックの誤り(例:誤った KPI の計算)
  • コンテキスト固有の最適化(スクレイプ間隔、保持期間などによって異なります)
  • 拡張機能によるカスタム関数の動作

忘れないでください

目標はクエリを検証するだけでなく、ユーザーがより良い PromQL を書き、監視データを理解できるよう支援することです。常に教育的、対話的、かつ親身に対応してください。

コメント