vm-trace-analyzer について
vm-trace-analyzerは、VictoriaMetricsのクエリトレースJSONから性能レポートを作成するスキルです。スクリプトでトレースを要約し、新しいバージョンの変更履歴も確認したうえで、主要な処理段階と根拠に基づく改善案を示します。
主な機能
- 01トレースデータを解析して要約
- 02トレースツリーと該当ノードを調査
- 03クエリ段階ごとの所要時間を分析
- 04vmstorageごとの詳細を報告
- 05新しいVictoriaMetricsの変更履歴を確認
- 06ボトルネックに応じて改善案を選択
活用シーン
- 01遅いPromQLクエリの診断
- 02vmstorage間でクエリ段階を比較
- 03新しいバージョンの性能修正を確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ victoriametrics/ skills --skill vm-trace-analyzerインストール後、Claude Code で/vm-trace-analyzerを入力して読み込まれたか確認します。
同梱ファイルscripts/check_changelog.pyscripts/parse_trace.py
詳細
VictoriaMetrics クエリトレースアナライザー
VictoriaMetrics のクエリトレースを分析します。これは、PromQL クエリの実行におけるすべてのステップを記録した JSON ツリーです。このツリーを読み解いて何が起きたかを理解し、実行可能な推奨事項を含む明確なパフォーマンスレポートを作成することが目的です。
背景
Cluster モードでは、クエリ処理に 2 つのコンポーネントが関与します。
- vmselect — PromQL または MetricsQL クエリを受け付け、vmstorage ノードからデータを取得して計算を適用するクエリフロントエンド
- vmstorage — 時系列データを保存し、RPC 経由で vmselect に提供します
Single-node モードでは、すべての処理を 1 つのプロセスで実行します。トレース構造は似ていますが、RPC ラッパーはありません。
トレースのルートメッセージから、どちらのモードかを判別できます。
- Cluster トレースには
vmselect-<version>: /select/...が含まれます。 - Single-node トレースには
/victoria-metrics-<version>: /api/v1/...が含まれます。
クエリトレースとは何ですか?
VictoriaMetrics の HTTP クエリに trace=1 を追加すると、すべての内部処理を記述した JSON ツリーが返されます。
各ノードは次のようになります。
{
"duration_msec": 123.456,
"message": "description of what happened",
"children": [ ... ]
}
ツリーのルートは vmselect です。解析、時系列検索、ストレージからのデータ取得、ロールアップ計算、集約、レスポンス生成まで、クエリ実行パイプライン全体が記録されます。
トレースの分析方法
ステップ 0:解析スクリプトを実行する
トレースファイルを手動で読む前に、分析スクリプトを実行して構造化データを抽出します。
python3 <skill_base_dir>/scripts/parse_trace.py <trace_file>
次の情報が出力されます:ルート情報、トレースツリー(深さ 3)、所要時間を含む主要ノード、vmstorage ごとの RPC 内訳、計算された合計値(バイト数、サンプル数、時系列数)。レポートの主要なデータソースとして、この出力を使用してください。
より詳しく調査するためのサブコマンド:
python3 <script> <trace> tree --depth N— 深さ N までのトレースツリーを表示しますpython3 <script> <trace> nodes --pattern "fetch unique"— 部分文字列に一致するすべてのノードを検索します
要約出力で曖昧な点や情報の不足が明らかになった場合に限り、さらに詳しく調査してください。
要約を実行した後、新しい VictoriaMetrics バージョンで関連するパフォーマンス改善がないかも確認してください。
python3 <skill_base_dir>/scripts/check_changelog.py <version> <mode>
<version> は解析スクリプトの出力にあるセマンティックバージョン(例:v1.130.0)、<mode> は cluster または single-node です。このコマンドは GitHub から変更履歴を取得し、トレース取得時のバージョンより新しいバージョンに含まれる、パフォーマンスに関連する修正や機能を表示します。取得に失敗した場合は、このセクションを問題なくスキップしてください。
ステップ 1:ルートから確認する
ユーザーが提供したトレース JSON ファイルを読み取ります(またはステップ 0 のスクリプト出力を使用します)。 ルートノードから全体像を把握できます。以下を抽出してください。
- エンドポイント:
/api/v1/query(instant)または/api/v1/query_range(range) - クエリ:
query=の後にある PromQL 式 - 時間パラメーター:
start=、end=、step=(range クエリの場合) - 結果数:末尾にある
series= - 合計所要時間:ルートの
duration_msec - バージョン:トレースの先頭に出力されています。
ステップ 2:フェーズを特定する
トップレベルの子要素をたどり、それぞれを次のいずれかのフェーズに分類します。 すべてのトレースにすべてのフェーズが含まれるわけではありません。存在するものだけを報告してください。
大規模なトレースでは、まずトップレベルの子要素に注目します。 ボトルネックに関係する場合や、所要時間が予想外の場合にのみ、サブツリーを詳しく調べます。
クエリのトレースには通常、次のフェーズがこの順序で含まれます。 すべてのフェーズがすべてのトレースに現れるわけではありません。ここで説明するメッセージパターンと照合して特定してください。
式の評価 — 次の形式に一致するノード:eval: query=..., timeRange=..., step=..., mayCache=...: series=N, points=N, pointsPerSeries=N
これらのノードは、再帰的な PromQL/MetricsQL 式ツリーをトレースします。
これらのノードは、PromQL/MetricsQL 式ツリーの再帰的な評価をトレースします。
各 eval ノードには、部分式を表す子ノードが含まれる場合があります。主な数値は次のとおりです。
- series — この部分式によって生成された時系列の数
- points — すべての時系列に含まれるデータポイントの合計数
- pointsPerSeries — 時系列あたりのデータポイント数
関数と集約 — 次の形式に一致するノード:
transform <func>(): series=N— PromQL 関数(histogram_quantile、clamp など)aggregate <func>(): series=N— 集約演算子(sum、avg、max など)binary op "<op>": series=N— 二項演算
時系列検索(インデックス検索) — ラベルマッチャーが内部の時系列 ID に解決される箇所:
- クラスターのトレースでは、
rpc at vmstorage <addr>→rpc call search_v7()にラップされています。単一ノードでは、RPC ラッパーなしで直接表示されます - 主なメッセージ:
init series searchsearch TSIDssearch N indexDBs in parallel— インデックスデータベースの並列検索search indexDB— 個々のインデックスパーティションfound N metric ids for filter=...— メトリック ID。vmstorage 内で一意な時系列識別子found N TSIDs for N metricIDs— メトリック ID と同じsort N TSIDs
- このフェーズにおけるキャッシュ関連メッセージ:
search for metricIDs in tag filters cacheに続いてcache missまたはキャッシュヒット(cache missの子ノードがない場合)put N metricIDs in cache/stored N metricIDs into cache
データ取得 — 生データの取得:
- クラスター:
fetch matching series: ...は、各 vmstorage ノードへの RPC 呼び出しを囲みます:rpc at vmstorage <addr>— ノードごとの RPCsent N blocks to vmselect— 送信された生データの量fetch unique series=N, blocks=N, samples=N, bytes=N— すべての vmstorage ノードを合計した概要
- 単一ノード:
search for parts with data for N seriesに続いて、データスキャンのメッセージが表示されます。fetch unique seriesの bytes 値は、転送されたデータの合計量を示し、I/O 負荷の目安になります。
ロールアップ計算 — rate()、increase()、avg_over_time() などの計算:
rollup <func>(): timeRange=..., step=N, window=Nrollup <func>() with incremental aggregation <agg>() over N series— これは最適化ですthe rollup evaluation needs an estimated N bytes of RAM for N series and N points per series— メモリの推定値parallel process of fetched data: series=N, samples=N— 生サンプルに対する実際の計算series after aggregation with <func>(): N; samplesScanned=N— 集約後の結果 生データを大量にスキャンするクエリでは、このフェーズが実行時間の大部分を占めることがよくあります。
レスポンス生成 — 通常はごく短時間で完了します:
sort series by metric name and labelsgenerate /api/v1/query_range response for series=N, points=N通常は非常に高速です。レスポンスが巨大で(数百の時系列に各数千のデータポイントが含まれるなど)、クライアントの読み取り速度が遅い場合は、ボトルネックになることがあります。
ステップ 3:時間の内訳を作成する
各フェーズの duration_msec を記録します。
クラスターのトレースでは、同じフェーズが vmstorage ノードごとに繰り返されます。概要には合計値を記録しつつ、ノード間の偏りを見つけられるよう、ノードごとの数値も記録します。
ステップ 4:ボトルネックを特定する
最も時間がかかったフェーズを特定し、具体的な理由を説明してください。 たとえば、「ロールアップで生のサンプルを 2 億 1,200 万件スキャンした」は有用ですが、「クエリが遅かった」では不十分です。
ステップ 5:推奨事項を作成する
推奨事項は、トレースで実際に確認できる内容のみに基づいてください。 クエリが高速で問題がなければ、そのように伝えてください。問題を作り上げてはいけません。
以下のアルゴリズムに従って推奨事項を選択してください。
- ステップ 5a: 時間の内訳から、合計レイテンシの大部分(60%超)を占めるフェーズを 1 つ特定します。そのフェーズに対応する「推奨パターン」セクションのパターンを選びます。
- ステップ 5b: そのパターンに記載された推奨事項のみを、記載された優先順位で使用してください。他のパターンから推奨事項を取り入れてはいけません。
- ステップ 5c: 60%を超えるフェーズが 1 つもない場合は、寄与率が最も高いパターンを選び、副次的な要因にも言及します。ただし、複数のパターンの推奨事項を混ぜてはいけません。
レポート形式
## Query Overview
- **Query:** `<the PromQL/MetricsQL expression>`
- **Type:** instant / range query
- **Time range:** <start> to <end> (<duration>)
- **Step:** <step>
- **Result:** <N> series, <N> points
- **Version:** vmselect or VM single-node version
## Performance Summary
- **Total duration:** <N>ms
- **Duration score:** <Fast / Acceptable / Slow / Very Slow>
- **Matched series:** <N> (across all storage nodes)
- **Raw samples scanned:** <N>
- **Bytes transferred:** <N>
"Duration score" thresholds:
- Fast: < 500ms
- Acceptable: 500ms–5s
- Slow: 5s–10s
- Very Slow: > 10s
## Execution Time Breakdown
| Phase | Duration | % of Total | Notes |
|-------|----------|------------|-------|
| Series search (index) | Xms | X% | |
| Data fetch | Xms | X% | |
| Rollup computation | Xms | X% | |
| Aggregation / functions | Xms | X% | |
| Response generation | Xms | X% | |
(Adapt the phases to what actually appears in the trace.
For cluster traces, break down data fetch per storage node.)
## Storage Node Breakdown (cluster only)
| Node | Series | Bytes sent | Duration |
|------|--------|-------------|----------|
| vmstorage-1 | N | N | Xms |
| vmstorage-2 | N | N | Xms |
## Bottleneck Analysis
Name the single biggest contributor to total query time. Explain why it's slow with specific numbers from the trace.
## Recommendations
Provide actionable suggestions to reduce query latency (see guidance below).
## Upgrade Recommendations (if applicable)
If the changelog check found performance-relevant improvements in newer versions,
list them here with version, release date, and description.
Only include this section if there are concrete relevant entries. Omit entirely otherwise.
レポート生成ルール
- トレースで裏付けられていない問題を推測してはいけません。トレースに問題がなく、クエリが高速であれば、そのように伝えてください。
- レポートにブロックの情報を記載しないでください。ユーザーには不要で、混乱を招く可能性があります。バイト数に注目してください。
- vmstorage ノード間の Duration の偏りについては、1~2 秒を超える場合を除き、記載しないでください。
- 所要時間には「Xm」「Xs」「Xms」の形式を使用してください(例:「123ms」)。60 秒を超える場合のみ分を、1000ms を超える場合は秒を、それより短い場合は ms を使用してください。
- データ量には、読みやすい形式を使用してください(例:「268000000 bytes」ではなく「268 MB」)。サイズに応じて適切な単位(KB、MB、GB)を使用してください。
- 所要時間は、推定して差し引きで求めず、トレースの
duration_msecの値を直接使用してください。 - クラスターのトレースでは、各 vmstorage ノードに同じフェーズ(インデックス検索、データスキャン)が現れます。要約ではこれらを合算し、ユーザーが偏りを確認できるよう、ノードごとの内訳も示してください。
- トレースが大きすぎて一度に読み取れない場合は、まずトップレベルの構造を確認し、
duration_msecに基づいて最も遅い分岐を特定してから、詳細を確認してください。 - トレースには
subqueryまたは@ modifierの評価が含まれる場合があります。これらはネストされた eval フェーズとして扱ってください。 - eval メッセージ内の
mayCache=falseは情報であり、問題ではありません。
推奨パターン
重要:パターンの選択ルール
- まず、時間の内訳からボトルネックに該当するパターンを以下から1つだけ特定してください。
- 選択したパターンの推奨事項のみを、記載されている優先順位に従って使用してください。
- 異なるパターンの推奨事項を混在させないでください。支配的なフェーズがレイテンシ全体の60%を超える場合、すべての推奨事項は必ずそのパターンのみから選んでください。
- 推奨事項が複数のパターンに記載されていても、その推奨事項がパターンに依存しないという意味ではありません。選択したパターンに記載されている場合にのみ使用してください。
トレースで実際に確認できる内容に基づき、優先順位順に推奨事項を提示してください。 以下に、一般的なパターンと対応するアドバイスを示します。
シリーズのカーディナリティが高い(マッチしたシリーズが多い)
- シリーズ数を減らすため、より具体的なラベルマッチャーを追加するよう提案します
- ダッシュボードのクエリであれば、記録ルールを使って事前集計するよう提案します
- 可能であれば、保存前にストリーム集約を使ってシリーズを事前集計するよう提案します
- マッチしたメトリクスのチャーンレートが高い場合は、時間範囲を狭めるよう提案します
大量の生サンプルをスキャンしている(samplesScanned が多い)
- samplesScanned の値が取得したサンプル数を大幅に上回る場合、クエリで
[window]が短すぎるか、サブクエリが過剰に実行されています。 rate()/irate()/increase()では、意味的に許容できる場合、[window]を短くするよう提案します- シリーズごとのポイント数を減らすため、クエリのステップを大きくするよう提案します
- 時間範囲を狭めるよう提案します
インデックス検索が遅い(シリーズ検索が支配的)
- タグフィルターのキャッシュミスは初回クエリでは通常のことです。繰り返し実行するクエリは速くなるはずです
- 1日のパーティションあたりのメトリクス ID 数が多い場合、チャーンが多いか、カーディナリティの問題があることを示しています
- 可能であれば、より選択性の高いフィルターを使うよう提案します
- 可能であれば、vmstorage ノードのメモリを増やすよう提案します
データ取得が遅い/転送バイト数が多い(クラスター)
- 送信バイト数が多い場合、vmstorage で大量の I/O が発生していることを示しています
- リソースの飽和が疑われる場合は、VictoriaMetrics の公式 Grafana ダッシュボードでリソース使用状況を確認するよう提案します。
- vmstorage のディスク I/O とネットワーク帯域幅を確認するよう提案します
- 複数の vmstorage ノード間で処理時間に大きなばらつき(1~2 秒以上)がある場合、リソースの飽和またはハードウェアの問題を示している可能性があります。
- 可能であれば、I/O 容量を水平スケーリングするために vmstorage ノードを追加するよう提案します
データ取得が遅い/転送バイト数が多い(単一ノード)
- 送信バイト数が多い場合、VM 単一ノードで大量の I/O が発生していることを示しています
- リソースの飽和が疑われる場合は、VictoriaMetrics の公式 Grafana ダッシュボードでリソース使用状況を確認するよう提案します。
- VM 単一ノードのディスク I/O と CPU を確認するよう提案します
- ディスク I/O の上限を引き上げるよう提案します
- クエリまたはクエリ対象のデータを最適化できない場合は、I/O 容量を水平スケーリングするため、クラスター構成への切り替えを提案します
ロールアップ計算が支配的(多くの場合、数百万件の生サンプルをスキャンすることが原因)
- 計算速度を上げるため、vmselect の CPU 制限を引き上げるよう提案します。
- 処理対象のシリーズ数を減らすため、より具体的なラベルマッチャーを追加するよう提案します。
- 生サンプルの量を減らすため、時間範囲を狭めるよう提案します。
- シリーズごとのポイント数を減らすため、クエリの
stepを大きくするよう提案します。 - 繰り返し実行するダッシュボードのクエリには、結果を事前計算する記録ルールを提案します。
バージョンアップグレードの機会
check_changelog.py スクリプトで新しいバージョンに関連するパフォーマンス改善が見つかった場合は、「アップグレードの推奨事項」レポートセクションに追加の推奨事項として記載してください。これは「単一パターンのみ」のルールに対する唯一の例外です。選択したボトルネックのパターンに関係なく、アップグレードの推奨事項を補足として追加できます。観測されたボトルネックまたはトレースに含まれるコンポーネントに直接関連する項目のみを含めてください。