ETW MCPの回答が本当にETLデータに基づいているか確認するには、シンボルを正しく解決し、対象プロセスと時間範囲を固定し、Regions of InterestとCritical Path Analysisで因果関係を追い、同じ条件をWPAで再現する必要があります。
関数名が表示されない場合は、AIの性能よりも先にシンボルパスとPDBの一致を確認してください。「ディスクが原因かもしれない」「ドライバー待ちの可能性がある」といった曖昧な回答は、対象時間が広すぎる、構造化クエリになっていない、必要なイベントがETLに記録されていない、といった原因で発生します。
ETW MCPは、ETLを直接書き換えるのではなく、TraceProcessorを通じて構造化された読み取り専用データをAIに提供します。ただし、最終的な解釈はLLMが行うため、回答が不完全または誤っている可能性は残ります。Microsoftも、出力を最終診断ではなく調査の出発点として扱い、元のトレース、時間範囲、スタック、WPAテーブルで検証するよう案内しています。(Microsoft Developer Blogs)
ETW MCP診断は「取得・限定・因果・照合」の順で検証する
ETW MCPの回答を検証するときは、いきなり「この回答は正しいか」と再質問してはいけません。次の4段階に分けると、どこで根拠が崩れているかを特定できます。
| 段階 | 確認する内容 | 失敗した場合に起きること |
|---|---|---|
| 取得 | 必要なイベント、スタック、スケジューリング情報がETLに含まれるか | AIが不足データを推測で補う |
| 限定 | プロセス、PID、スレッド、時間範囲、集計方法を固定したか | トレース全体の平均に埋もれる |
| 因果 | RegionsとCritical Pathで待機の連鎖を追ったか | CPU上位を原因と誤認する |
| 照合 | 同じETLと条件をWPAで再現したか | AIの解釈ミスを見逃す |
本件の対応状況は、次のように整理できます。
| 項目 | 状態 |
|---|---|
| 対象 | ETW MCP early preview、TraceProcessor |
| 対応状況 | 公式の解決策または回避策あり |
| 主な対処 | シンボルパスの構成、構造化クエリ、時間範囲の限定、Critical PathとRegionsの利用 |
| 最終確認 | 読み取り専用TraceProcessorデータとWPAの対応テーブルを照合 |
| 注意点 | 読み取り専用であることは、回答の正しさを保証しない |
ETW MCPが参照しているデータの仕組み
ETW MCPは、ローカルで動作するSTDIOベースのMCPサーバーです。生のETWイベントを大量にLLMへ渡すのではなく、TraceProcessorで処理した結果を、フィルター、集計、比較などが可能な構造化データとして渡します。
基盤にはWPAやXPerfでも使われるTraceProcessorエンジンが採用されています。そのため、条件をそろえれば、ETW MCPが利用するデータはWPAで確認するデータと対応します。Microsoft.Windows.EventTracing.MCPでは、CPU、メモリ、ディスク、プロセスなどの照会に加え、条件指定、グループ化、集計、スレッドと時間範囲を指定したCritical Path Analysisがサポートされています。(Microsoft Developer Blogs)
ただし、次の2つは分けて考える必要があります。
- TraceProcessorが返した数値やイベントは、ETLから取得された観測データ
- 「これが根本原因である」という文章は、LLMによる解釈
したがって、「ETLを読んだ回答だから正しい」とは限りません。検証時は、観測値、解釈、未確認事項を別々に出力させることが重要です。
最初にETLへ必要なデータが記録されているか確認する
シンボルやプロンプトを調整する前に、ETLに必要なデータソースが存在するかを確認します。
TraceProcessorは、ETLに含まれるCPUサンプリング、CPUスケジューリング、ディスクI/O、ファイルI/O、プロセス、スタック、Regions of Interestなどを個別のデータソースとして扱います。ただし、利用できるデータは、トレース取得時に有効化されていたETWプロバイダーやWPRプロファイルに依存します。後からプロンプトを工夫しても、記録されていないイベントを復元することはできません。(Microsoft Learn)
最初の質問は、原因分析ではなくデータの棚卸しにします。
<trace.etl> を処理し、このトレースで利用できるデータカテゴリを一覧にしてください。
次の項目について、利用可能、利用不可、データはあるが不足、のいずれかで判定してください。
- プロセスとスレッド
- CPU Usage(Sampled)
- CPU Scheduling、Context Switch、Ready Thread
- コールスタック
- シンボル
- Disk I/O
- File I/O
- Regions of Interest
- Trace Statistics
利用できない項目については推測せず、トレースに記録されていないと明記してください。
トレース全体の開始時刻、終了時刻、継続時間も示してください。
調査内容ごとに必要なデータは異なります。
| 確認したいこと | 主に必要なデータ |
|---|---|
| CPUを消費した関数 | CPU Usage(Sampled)、スタック、シンボル |
| スレッドが止まった原因 | CPU Scheduling、Context Switch、Ready Thread、スタック |
| ディスク待ち | Disk I/O、File I/O、スケジューリング情報 |
| 起動や処理フェーズの遅延 | Regions of Interest、Marks、関連ETWイベント |
| プロセスの開始・終了 | Processes、Threads |
| ETL自体の欠損確認 | Trace Statistics |
必要なカテゴリが存在しない場合は、ETW MCPの設定変更ではなく、WPRプロファイルやETWプロバイダーを見直してETLを再取得します。
関数名が出ない場合はシンボルパスを構成する
スタックが次のような表示になっている場合、根本原因を関数単位で判断するのは困難です。
MyApp.exe+0x18A42
example.dll+0x7F10
0x00007FFB12345678
必要なのは、次のようなmodule!function形式です。
MyApp.exe!StartupManager::Initialize
example.dll!DeviceController::Open
ntdll.dll!NtWaitForSingleObject
Microsoftの公式ドキュメントでは、WPAやTraceProcessorが完全なスタックを構築するためにPDBを使用し、_NT_SYMBOL_PATHでシンボルの検索先を設定すると説明されています。TraceProcessorはPDBからSymCacheを生成し、以後の解析でキャッシュを利用できます。(Microsoft Learn)
PowerShellでシンボルパスを設定する
次の例では、自社アプリのPDBフォルダーとMicrosoftのパブリックシンボルサーバーを指定します。
$cache = "$env:LOCALAPPDATA\ETWSymbols"
New-Item -ItemType Directory -Force -Path $cache | Out-Null
# 自社アプリのPDBがない場合は、この部分を削除する
$privatePdb = "C:\Build\MyApp\Symbols"
$symbolPath = "$privatePdb;srv*$cache*https://msdl.microsoft.com/download/symbols"
# 現在のPowerShellセッションへ反映
$env:_NT_SYMBOL_PATH = $symbolPath
# ユーザー環境変数として保存
[Environment]::SetEnvironmentVariable(
"_NT_SYMBOL_PATH",
$symbolPath,
"User"
)
$env:_NT_SYMBOL_PATH
設定後は、VS Code、GitHub Copilot CLI、ETW MCPプロセスを完全に終了してから起動し直します。WPAを含む関連ツールは、起動時に環境変数を取得するため、実行中のプロセスへ後から設定しても反映されない場合があります。(Microsoft Learn)
PDBは同名であるだけでは不十分
PDBは、解析対象のEXEやDLLと正確に対応している必要があります。
確認するポイントは次のとおりです。
- ETL取得時に動いていたバイナリと同じビルドか
- x64、x86、Arm64などのアーキテクチャが一致しているか
- リリース版とデバッグ版を取り違えていないか
- 古いPDBがシンボルキャッシュに残っていないか
- マネージドコードの場合、必要なランタイムイベントやRundownイベントが記録されているか
Microsoftのドキュメントでも、異なるビルドやアーキテクチャのPDBではコールスタックを表示できないと説明されています。シンボルを切り替えた後も古い結果になる場合は、今回の解析専用に作成したキャッシュフォルダーを削除し、再度読み込ませます。(Microsoft Learn)
シンボル解決を確認するプロンプト
<process-name> のCPUサンプルを、<開始時刻>から<終了時刻>に限定して解析してください。
- Process、Thread、Stackの順で集計する
- 解決済みフレームは module!function 形式で表示する
- 未解決フレームは、モジュール名とアドレスまたはオフセットをそのまま表示する
- 未解決の関数名を推測しない
- 解決済みフレーム数と未解決フレーム数を示す
- 上位20スタックについて、サンプル数と推定CPU時間を示す
成功条件は、「関数らしい文字列が出たこと」ではありません。次の3点を確認します。
- 自社モジュールが
module!function形式になっている - 未解決フレームが別枠で報告されている
- 同じETLをWPAで開いたときも同じ関数が表示される
原因が曖昧な場合は構造化クエリへ変える
「このETLが遅い原因を教えてください」のような質問は、調査範囲が広すぎます。トレース全体から目立つ値を拾うだけになり、問題が起きた瞬間とは無関係なプロセスを原因として挙げることがあります。
ETW MCPは、条件、グループ化、集計を含む構造化クエリを扱えます。プロンプトでも、少なくとも次の項目を固定してください。([NuGet Gallery][5])
| 指定項目 | 具体例 |
|---|---|
| ETL | C:\Traces\slow.etl |
| 時間範囲 | 12.400秒から13.900秒 |
| プロセス | MyApp.exe |
| PID | 同名プロセスが複数ある場合に指定 |
| スレッド | UIスレッド、TID 4820など |
| 指標 | CPUサンプル、待機時間、ディスクI/Oなど |
| 集計軸 | Process、Thread、Module、Function |
| 上限 | 上位20件 |
| 出力形式 | 観測値、解釈、未確認事項を分離 |
曖昧な質問と検証可能な質問の違い
| 曖昧な質問 | 検証可能な質問 |
|---|---|
| なぜ起動が遅いですか | 起動リージョン1.2秒から4.8秒を対象に、実行時間と待機時間を分離してください |
| CPU負荷の原因は何ですか | PID 3120のCPU Usage(Sampled)をThread、Module、Functionで集計してください |
| ディスクが遅いですか | 対象時間内のDisk I/Oをプロセス、ファイル、合計バイト数、I/O時間で集計してください |
| ドライバーが原因ですか | Critical Path上でドライバー待ちと判断した区間、時間、スタック、根拠イベントを示してください |
構造化クエリの実用テンプレート
<route.etl> を読み取り専用で分析してください。
対象:
- 時間範囲: <t0>から<t1>
- プロセス: <process>
- PID: <pid>
- 必要に応じてスレッドID: <tid>
実行する分析:
1. CPU Usage(Sampled)をProcess、Thread、Module、Functionで集計
2. 上位20件についてサンプル数と推定CPU時間を表示
3. 同じ時間範囲のCPU Schedulingと待機理由を集計
4. Disk I/OとFile I/Oが記録されている場合のみ集計
5. 使用したデータカテゴリ、フィルター、対象行数を明記
出力を次の3区分に分けてください。
- ETLから直接確認できた観測値
- 観測値から導いた解釈
- データ不足により確認できない事項
不足データから原因を推測しないでください。
CPU Usage(Sampled)から算出されるCPU時間は、サンプリングと各サンプルの重みに基づく推定値です。処理区間の実時間やスレッドの待機時間と同じものではありません。(Microsoft Learn)
Regions of Interestで問題の時間範囲を固定する
起動、ログオン、画面表示、デバイス初期化などの処理は、複数のフェーズから構成されます。トレース全体を解析するよりも、フェーズを名前付きの時間区間として定義した方が、比較と原因追跡が容易になります。
Regions of Interestは、XML構成で指定したETWイベントを基に、名前付きの時間区間を作る機能です。ETW MCPではRegions XMLをトレースと一緒に処理し、シナリオ全体のタイムラインを作成できます。TraceProcessor側でもUseRegionsOfInterest()に対応しており、WPAでは「Regions of Interest」テーブルに対応します。(Microsoft Developer Blogs)
Regionsを利用すると、次のような判断が可能になります。
| Region | 所要時間 | 判断 |
|---|---|---|
| Process start | 120ms | 比較的短い |
| Runtime initialization | 380ms | 要確認 |
| Device initialization | 1,420ms | 最大のボトルネック |
| UI ready | 95ms | 影響が小さい |
重要なのは、最長Regionを見つけた時点で根本原因と断定しないことです。Regionは「遅い場所」を示しますが、「なぜ遅いか」はCritical Pathで調べます。
なお、MicrosoftのETW MCP紹介記事ではRegions XMLを渡す利用例は示されていますが、XMLスキーマの具体例までは掲載されていません。イベント名や属性を推測して独自形式を作るのではなく、既存のRegions定義や利用中のTraceProcessingパッケージに対応した定義を使用してください。Regions XMLを用意できない場合は、ETL上のMarksや明確な開始・終了時刻を指定します。(Microsoft Developer Blogs)
Critical Pathで「動いていた時間」と「待っていた時間」を分ける
処理が遅いとき、対象スレッドがCPUを使い続けていたとは限りません。
遅延は大きく分けて次の3種類があります。
- 対象スレッド自身がCPU上で処理していた
- ロック、イベント、I/O、タイマーなどを待っていた
- 別スレッドや別プロセスの完了を待っていた
Critical Path Analysisは、対象スレッドから依存先をたどり、処理完了を遅らせた待機の連鎖を調べるために使います。WPAによる従来のCritical Path分析では、CPU Usage(Precise)のNew Thread StackやReady Thread Stackなどを確認し、どのスレッドが待機を解消したかを順に追跡します。(Microsoft Learn)
ETW MCPでは、対象Regionや時間範囲を指定してCritical Pathを実行できます。公式紹介例でも、最長Regionに対してCritical Path Analysisを行い、CPU処理ではなくデバイスの低電力状態からの復帰待ちが主要因だったケースが示されています。(Microsoft Developer Blogs)
Critical Path用プロンプト
<trace.etl> を <regions.xml> と共に処理してください。
1. <scenario-name> のRegionを開始時刻順に表示
2. 各Regionの開始時刻、終了時刻、継続時間を表示
3. 最も長いRegionを特定
4. そのRegionの開始時刻から終了時刻を対象にCritical Path Analysisを実行
5. Critical Pathを時間順に表示
各セグメントについて、次を示してください。
- プロセス名
- PIDとTID
- 開始時刻と終了時刻
- 継続時間
- Running、Ready、Waitingなどの状態
- 待機理由
- 依存先または待機を解除したスレッド
- 根拠となるスタック
- 使用したETLデータカテゴリ
CPU実行時間とブロック時間を別々に合計してください。
Disk I/O、File I/O、ネットワーク関連データについては、
対象データがETLに記録されている場合のみ「活動なし」と判定してください。
記録されていない場合は「確認不能」としてください。
最後に、観測事実、原因候補、未確認事項を分離してください。
「I/Oがゼロだった」と「I/Oデータが記録されていなかった」は全く異なります。Critical Pathの回答では、ゼロという値だけでなく、その判断に使ったデータソースまで出力させてください。
WPAの対応テーブルで回答を照合する
ETW MCPの回答を確定診断に使う前に、同じETLをWPAで開き、対応するテーブルで再現します。
TraceProcessorのデータソースとWPAの主な対応関係は次のとおりです。(Microsoft Learn)
| ETW MCPで確認した内容 | WPAで確認する場所 |
|---|---|
| プロセス一覧 | Processes |
| CPUサンプルとホットスタック | CPU Usage(Sampled) |
| Context Switch、Ready、待機関係 | CPU Usage(Precise) |
| ディスク処理 | Disk Usage |
| ファイル単位のI/O | File I/O |
| 汎用ETWイベント | Generic Events |
| 名前付き時間区間 | Regions of Interest |
| シンボルの読み込み状態 | Symbols Hub |
| トレースの統計情報 | System Configuration、Trace Statistics |
| プロセスとイメージ情報 | Processes、Images |
WPAでの照合手順
- ETW MCPが処理したものと同じETLをWPAで開く
- ETW MCPと同じシンボルパスを設定する
Traceメニューからシンボルを読み込む- ETW MCPで指定した開始時刻と終了時刻をWPAでも選択する
- 同じプロセス、PID、TIDでフィルターする
- 同じグループ化単位で比較する
- サンプル数、上位スタック、待機時間、I/O件数を照合する
同名のETLを取り違えないように、調査記録へSHA-256ハッシュを残すと確実です。
Get-FileHash "C:\Traces\slow.etl" -Algorithm SHA256
照合時に数値が合わない場合は、AIの誤りと即断する前に次を確認します。
- ETW MCPとWPAで時間範囲が完全に一致しているか
- 同名プロセスの別PIDを選んでいないか
- Process単位とThread単位を混同していないか
- CPUサンプル数と推定CPU時間を混同していないか
- InclusiveとExclusiveの集計方法が異なっていないか
- IdleやSystemを含める条件が一致しているか
- シンボル読み込み前後のスタックを比較していないか
- Regionの開始イベントと終了イベントが同じ定義か
特に、サンプルベースのCPU時間とRegionの経過時間は一致しません。CPU時間が200msでも、スレッドが1秒間ブロックされていれば、処理全体は1秒以上かかります。
読み取り専用制約が保証すること・しないこと
ETW MCPの読み取り専用設計は重要ですが、保証範囲を正しく理解する必要があります。
| 読み取り専用制約が保証すること | 保証しないこと |
|---|---|
| MCPからETL解析データを書き換えない | ETLに必要なイベントがすべてあること |
| 生イベントではなく構造化結果を扱う | シンボルが正しく解決されること |
| 条件を付けたクエリを実行できる | プロンプトのフィルターが適切であること |
| 元データへ戻って再確認できる | LLMの解釈が正しいこと |
| WPAとの対応関係を追跡できる | 回答が毎回同じ文章になること |
Microsoftも、LLMによる分析結果は実行ごとに変わる可能性があり、不完全または誤っている場合があると説明しています。そのため、「根拠を表示してください」という追加質問を前提に運用する必要があります。(Microsoft Developer Blogs)
実務では、次の情報を調査記録として保存します。
- ETLのファイル名、パス、SHA-256
- ETW MCPパッケージのバージョン
- 使用したシンボルパス
- シンボルキャッシュの場所
- Regions XMLのファイル名と版
- 対象時間範囲
- PID、TID
- 実行したプロンプト
- 使用されたデータカテゴリ
- ETW MCPの表形式出力
- WPAで再現したテーブルとフィルター条件
- 確定事項と未確認事項
これにより、別の担当者でも同じ条件で診断を再現できます。
症状別の確認ポイント
| 症状 | 主な原因 | 対処 |
|---|---|---|
| アドレスやオフセットしか出ない | シンボル未設定、PDB不一致 | _NT_SYMBOL_PATHを設定し、クライアントを再起動 |
| モジュール名は出るが関数名がない | PDB不一致、古いキャッシュ | ビルドとアーキテクチャを確認し、専用キャッシュを再作成 |
| プロセス名までしか分からない | 集計単位が粗い | Thread、Module、Functionまでグループ化 |
| 原因が「I/Oの可能性」など曖昧 | 時間範囲やデータソースが未指定 | 対象区間を固定し、根拠イベントを要求 |
| CPU上位プロセスが原因扱いされる | RunningとWaitingを混同 | Critical Pathでブロック時間を確認 |
| Regionが見つからない | XMLとETWイベントが一致しない | 対象イベントの存在をGeneric Eventsで確認 |
| WPAと合計値が違う | 時間、PID、単位、集計方法が異なる | 条件を1項目ずつそろえる |
| 同じ質問で回答が変わる | LLMの解釈が変動 | 出力形式とクエリ条件を固定 |
| 必要なカテゴリが利用不可 | ETL取得時のプロファイル不足 | WPR設定を変更してETLを再取得 |
そのまま使える根拠検証プロンプト
次のETLを読み取り専用で分析してください。
ETL:
<trace.etl>
Regions定義:
<regions.xml または「なし」>
対象:
- プロセス: <process>
- PID: <pid>
- スレッドID: <tid または未指定>
- 時間範囲: <t0>から<t1>
- シナリオまたはRegion: <name>
検証手順:
A. データ確認
- 利用可能なデータカテゴリを列挙
- CPU Sampled、CPU Scheduling、Stacks、Symbols、Disk I/O、
File I/O、Regions、Trace Statisticsの有無を示す
- 利用できないデータを推測で補わない
B. シンボル確認
- 解決済みフレームを module!function 形式で表示
- 未解決フレームを別表にする
- 関数名を推測しない
- 解決済みと未解決の件数を示す
C. 構造化分析
- 指定時間範囲だけを対象とする
- Process、Thread、Module、Functionで集計
- 上位20件を表示
- サンプル数、推定CPU時間、待機時間を混同しない
- 使用したフィルターと対象行数を示す
D. Critical Path
- 指定Regionまたは時間範囲のCritical Pathを実行
- Running、Ready、Waitingを分離
- 各待機区間の時間、待機理由、依存先、根拠スタックを表示
- I/Oが記録されていない場合は「活動なし」ではなく「確認不能」とする
E. 根拠表
各結論について、次の列を持つ表を作成する。
- 結論
- ETLから確認した観測値
- 使用したデータカテゴリ
- 時間範囲
- プロセス、PID、TID
- 根拠となるスタックまたはイベント
- 対応するWPAテーブル
- 確信度
- 未確認事項
最後に、次の3区分でまとめる。
1. ETLから直接確認できた事実
2. 事実から合理的に導ける原因候補
3. 現在のETLでは判断できない事項
ETW MCPの結果を確定診断に変えるための最終確認
ETW MCPの回答を信頼できる診断結果にするには、次の順番を崩さないことが重要です。
まず、ETLに必要なデータカテゴリが含まれているか確認します。次に、シンボルパスを構成し、関数名をmodule!function形式で解決します。そのうえで、プロセス、PID、スレッド、時間範囲、集計方法を固定した構造化クエリを実行します。
遅延原因の特定では、CPU使用率だけを見ず、Regions of Interestで対象フェーズを決め、Critical Path Analysisで実行時間と待機時間を分けます。最後に、同じETL、シンボル、時間範囲、フィルターをWPAへ適用し、CPU Usage、Disk Usage、File I/O、Regions of Interestなどの対応テーブルで照合します。
ETW MCPとWPAの結果が一致し、根拠となるイベント、スタック、待機時間まで説明できた時点で、初めて原因を確定します。一致しない場合は、結論を採用せず、時間範囲、PID、シンボル、集計単位、取得データの不足を再確認してください。
[5]: https://www.nuget.org/packages/Microsoft.Windows.EventTracing.MCP “
NuGet Gallery
| Microsoft.Windows.EventTracing.MCP 0.7.22
“

コメント