ETW を使用したコードのインストルメント化
Event Tracing for Windows (ETW) は、Windows に組み込まれている高速トレース機能です。 ETW では、オペレーティング システム カーネルに実装されているバッファリングとログ記録メカニズムを使用して、ユーザー モード (アプリ) とカーネル モードのコンポーネント (ドライバー) の両方で発生するイベントのインフラストラクチャを提供します。 ETW は、システムおよびアプリの診断、トラブルシューティング、パフォーマンス監視に使用できます。
従来、トレースは、ハードウェアとアプリの両方で予期しない動作を診断するために使用されていました。 しかし、最近では、ビジネス ニーズを満たすためにシステムの安定性とパフォーマンスを管理および監視するための需要が高まっています。 その結果、開発環境と運用環境でのパフォーマンス分析は、コンピューティング環境の重要な部分になりました。 障害やエラーとは異なり、パフォーマンスに関連する問題は構成やワークロードによって左右されることが多いため、検出と診断が困難です。 運用環境でトレースを行うことにより、パフォーマンス関連の問題の根本原因を検出するための貴重なデータだけではなく、容量計画や評価も得られます。
ETW メカニズムを使用すると、トレース セッションを動的に制御できます。これにより、システムの再起動やアプリの再起動を行わなくても、運用環境で詳細なトレースをキャプチャできます。
次のセクションでは、ETW を使用して正確なパフォーマンス測定と分析を行う方法を示します。
- カーネル モード ドライバー コード
- 従来のデスクトップ プロセスとサービス
- Microsoft Store アプリ (C#)
概要
ETW の便利な特性の一部を以下に示します。
- Robust
-
効率的なバッファリングとログ記録のメカニズムを提供します。 トレース バッファーはカーネルによって管理されます。 ETW を使用したトレースは、アプリのクラッシュやハングによる影響を受けません。 システム障害が発生した場合、保存されていないイベントはメモリ ダンプ ファイルでアクセスできます。
- 動的
-
トレース セッションは、システムの再起動やアプリの再起動を行わなくても、動的に開始、停止、再構成、および一時停止することができます。 ETW には、さまざまな要求を満たすために複数のモードが用意されています。
- 組み込み Windows
-
コントローラー アプリのほかに、追加のツールは必要ありません。 Windows には、いくつかの受信トレイ コントローラーとコンシューマー アプリがあります。
- 軽量
-
トレース ファイルの履歴と、保存されるログ ファイルのオーバーヘッドは非常に最適化されているため、アプリやシステムのパフォーマンスに影響を及ぼしません。 ログ記録メカニズムでは、カーネル モード バッファーを使用します。このバッファーは、別個のライター スレッドによってディスクに書き込まれるため、トレースのオーバーヘッドが制限されます。
Windows 2000 より前では、Windows の DbgPrint() および DebugPrint() API で使用できるのは基本的なテキスト ベースのトレース メカニズムのみでした。 これらにはデバッガーが必要で、通常は動的に制御できませんでした。 時間の経過に伴い Windows のトレース メカニズムは進化し、現在は 4 つの異なるトレース メカニズムを使用できます。 ETW とイベント ログ API のセットは Windows Vista の Unified Event Logging API セットに統合されたため、ユーザーや開発者は発生するイベントに対応する統合メカニズムを利用できます。
次の 3 つのタイプのイベントがあります。
Windows ソフトウェア トレース プロセッサ (WPP) およびクラシック ETW
Managed Object Format (MOF): MOF は、WMI オブジェクトを記述し、イベントを有効およびデコードするための手法です。
マニフェスト ベース: XML ベースの統合トレース定義が Windows Vista で導入されました。 XML ファイルには、プロバイダーが書き込むイベントの要素が含まれています。 詳細については、「インストルメンテーション マニフェストの作成」を参照してください。
Note
このセクションのガイダンスでは、マニフェスト ベースのイベント インストルメンテーションのみに焦点を当てました。
ETW には、次の重要な特性があります。
開発者は、目的の用途に基づいて適切な実装セットを選択できます (たとえば、WPP 実装などの Printf はデバッグを目的としたイベント用に簡単に追加できます)。
インフラストラクチャは、タイムスタンプ、関数名、ソース ファイル行番号などの一般的に使用される情報を管理します。
ユーザー モード アプリとカーネル モード コンポーネントで同じ実装が使用されます。
ETW には、クラッシュ ダンプとライブ デバッグでアクセスできます。
ETW は、リアルタイム ビュー用にカーネル デバッガーにリダイレクトできます。
ETW にはリアルタイム ビューがあります。
ログ ファイルはバイナリ ログ ファイル (ETL ファイル) に保存されます。
ETW では、複数のプロセスのログ記録がサポートされています。
ETW は高スループットです。
ログ ファイルは別のコンピューターで表示できます。
ETW では、継続的なログ記録と監視のための循環バッファリングがサポートされます。
ETW は、対象ユーザーに基づいていずれかのチャネルにグループ化できます。
ETW アーキテクチャ
ETW には、プロバイダー、セッション、コントローラー、コンシューマーという 4 つの主要なコンポーネントがあります。
プロバイダー
プロバイダーは、イベントを生成するインストルメント化されたコンポーネントです。 プロバイダーは、ユーザー モード アプリ、カーネル モード ドライバー、または Windows カーネル自体にすることができます。 イベントは、固定されたイベント データ (ヘッダー) に加えて、ユーザー データを転送できます。
イベントは、データのイベント ベースの表現です。 データは、詳細な分析に使用できます。 イベントを使用してカウンターを生成することもできます。 カウンターは、データのサンプル ベースのビューを提供します。 1 秒あたりの I/O バイト数や 1 秒あたりの割り込みなど、通常は現在の状態を示す小規模なデータ セットが含まれます。
プロバイダーは ETW に登録し、ETW ログ API を呼び出してイベントを送信する必要があります。 プロバイダーは、トレースを動的に有効または無効にできるよう、通知の有効化と無効化を行うコールバック関数を登録します。
セッション
ETW セッション インフラストラクチャは、1 つ以上のプロバイダーからコンシューマーにイベントを中継する中間ブローカーとして機能します。 セッションは、イベントをカーネル バッファーに収集し、指定されたファイルまたはリアルタイム コンシューマー プロセスにイベントを送信するカーネル オブジェクトです。 複数のプロバイダーを 1 つのセッションにマップできます。これにより、ユーザーは複数のソースからデータを収集できます。
コントローラー
コントローラーは、トレース セッションを開始、停止、または更新します。 セッションは、トレースの単位です。 プロバイダーは、特定のセッションにマップ (または有効化) されます。 コントローラーは、ETW へのイベントの送信を開始できるよう、プロバイダーを有効または無効にします。 コントローラーの機能は、Microsoft が提供するツールを使用して呼び出すことができます。また、独自のアプリを作成することもできます。
Logman.exeは、インボックス コントローラー アプリです。 Windows Performance Toolkit に含まれている Windows Performance Recorder (WPR) は、推奨されるコントローラー プロセスです。
コンシューマー
コンシューマーは、ログに記録されたトレース ファイル (ETL ファイル) を読み取る、またはアクティブなトレース セッション内のイベントをリアルタイムでキャプチャし、イベントを処理するアプリです。 イベント ビューアーとリソース モニターは、インボックス ETW コンシューマー アプリです。
Windows Performance Toolkit に含まれている Windows Performance Analyzer (WPA) は、推奨されるコンシューマー プロセスです。
ETW インストルメンテーションの実装
インストルメンテーションを計画する
コード内の ETW イベントをログに記録する場所を決定します。 このログ記録は、重要なユーザー シナリオや、測定、分析、および最終的に改善する頻繁な使用例と関連付けられている必要があります。 インストルメント可能な例を次に示します。
- 状態変更
- 重要な操作の開始/終了
- リソースの作成/削除
- パフォーマンスまたは信頼性に関連するその他のイベント
- デバッグ イベント
マニフェスト ファイルを作成してプロバイダーを実装する
マニフェスト ベースの ETW イベントは、イベント マニフェストと呼ばれる XML ファイルを使用して、サービスを含むユーザー モード アプリ、およびドライバーなどのカーネル モード コンポーネントで実装できます。 詳細については、「イベント トレーシング機能」を参照してください。
イベント マニフェストは、次のセクションに分割されています。
- プロバイダー定義: < プロバイダー >
-
作成するプロバイダーの名前と GUID、インストルメント化されたバイナリの場所 (最終的には ETW フレームワークで必要なインストルメンテーション リソースを含む) が含まれます。
- イベント ペイロード: <templates>
-
イベントにペイロードとして含まれるデータ型の定義が含まれます。 使用できる種類は次のとおりです。
-
符号付きおよび符号なし 8 ビット、16 ビット、32 ビット、および 64 ビット整数
-
ANSI および Unicode 文字列
-
Float と double
-
Boolean、Binary、GUID、Pointer、FILETIME、SYSTEMTIME、SID、HexInt32
-
- 静的イベント データ
-
イベントの解釈、並べ替え、グループ化に役立ちます。
- インストルメント化される操作 (またはタスク) の名前を定義します。
- Start イベント、時間内の区切り操作の Stop イベント、デバッグ データをログに記録するための Informational イベントなど、イベントに対して作成する操作の種類を定義します。
-
イベント定義: <events>
ペイロードと静的データを結び付け。 コードは、このセクションに記載されている内容で定義されているイベントを出力します。
イベント マニフェストの例を次に示します。
<provider
guid="{3877cf22-0702-4dfc-965e-7fdc7780cd74}"
name="MyEventProvider"
symbol="MY_EVENT_PROVIDER"
messageFileName="%temp%\MyProviderBinary.exe"
resourceFileName="%temp%\MyProviderBinary.exe“
>
<templates>
<template tid="T_MyProvider_1">
<data inType="win:Int32" name="Operation Id" />
<data inType="win:Int32" name="Memory Allocated (MB)" />
</template>
</templates>
<opcodes>
<opcode name="DebugInfo" symbol="_DebugInfo" value="10"/>
</opcodes>
<tasks>
<task name="OpMemAllocation" symbol="OpMemAllocation_Task" value="1“
eventGUID="{87ebca33-bf25-442c-9256-82ba484586e8}"/>
</tasks>
<events>
<event symbol="DebugInfo" template="T_MyProvider_1" value="200"
task="OpMemAllocation" opcode="DebugInfo" />
</events>
次を使用して、マニフェスト ファイルを作成できます。
Manifest Generator (ECManGen.exe)。Platform SDK で入手可能
Visual Studio (Eventman.xsd)。Platform SDK で入手可能
イベント マニフェストをコンパイルする
次に、Platform SDK で入手可能な Message Compiler ツール (mc.exe) を使用して、マニフェストをコンパイルします。 このツールにより、インストルメント化されたコードをインストルメント化、コンパイル、およびビルドするために必要ないくつかのファイルが生成されます。
- ManifestFileName.h
- コードで使用するイベント記述子を格納します。
- ManifestFileName.rc
- リソース コンパイラ スクリプト。
- MSG00001.bin
- 言語リソース。
- ManifestFileNameTEMP.bin
- テンプレート リソース (プロバイダーとメタデータ)。
ユーザー モード コードをコンパイルするには、次のように入力します。
mc.exe -um [ManifestFileName]
カーネル モード コードをコンパイルするには、次のように入力します。
mc.exe -km [ManifestFileName]
マネージ コードまたは JavaScript コードをコンパイルするには、次のように入力します。
mc.exe -cs [ManifestFileName]
mc.exe -css [ManifestFileName]
mc.exe -generateProjections [ManifestFileName]
コードを更新する
次に、インストルメンテーションをコードに追加します。 Visual Studio を実行し、Message Compiler によって生成されたヘッダー ファイルを追加して、プログラムにリソース ファイルをビルドします。
ヘッダー内で次の項目を探し、コードで呼び出すマクロ (またはクラス メソッド) を見つけます。
EventRegister<YourProviderName>
(アプリの起動時に) プロバイダーを登録するために使用されます。
EventUnregister<YourProviderName>
(アプリの終了時に) プロバイダーを登録解除するために使用されます。
EventWrite
イベントごとに 1 つのマクロ (またはメソッド) は、マニフェスト (<events> ノード) で定義されます。
コードが正しくインストルメント化されたら、バイナリをビルドできます。
ドライバーについては、MSDN で入手可能な EventDrv のサンプルを参照してください。 ETW カーネル モード EtwRegister 関数を使用して、ドライバーをイベント プロバイダーとして登録します。
デバイス オブジェクトを作成および初期化するコードの後に、DriverEntry ルーチンでこの関数を追加します。
EtwRegister 関数の呼び出しと、ドライバーの Unload ルーチンでの EtwUnregister の呼び出しを照合します。
イベントをログに記録して視覚化する
コンポーネントを適切にインストルメント化したら、テスト システムでイベントのログ記録を開始できます。 最初に、受信トレイ ツールの wevtutil を使用してプロバイダーを登録することで、ログを記録できるようにシステムを準備する必要があります。
resourceFileName 属性を使用して、マニフェストで指定した場所にコンポーネントをコピーします。
xcopy /y MyProviderBinary.exe %temp%
プロバイダーを登録します。
wevtutil um etwmanifest.man
wetvutil im etwmanifest.man次のプロバイダーが表示されていることを確認します。
logman query providers
プロバイダー名/GUID が一覧に表示されます。
イベント メタデータは、マニフェスト ファイルではなく、インストルメント化されたバイナリに格納されることに注意してください。 wevtutil を使用して PC にマニフェストをインストールすると、イベント メタデータを含むバイナリにプロバイダー GUID を接続するレジストリへのリンクが配置されます。 このバイナリの名前とパスは、指定されたマニフェスト ファイルから取得されます。 マニフェストファイルは、後で破棄できます。
これはデコードに使用しているコンピューター上にあるため、イベント メタデータを含むバイナリもアクセス可能で読み込み可能である必要があります。 WPR/xperf を使用すると、トレースにメタデータを挿入することで、プロセスの移植性が向上します。
このシステムにプロバイダーが正しくインストールされたら、トレース セッションを開始して、コンポーネントからのイベントを ETL ファイルに収集できます。 Windows Performance Recorder (WPR) または Xperf (コマンド ライン ツール) のいずれかを使用できます。どちらも、Windows Performance Toolkit で使用できます。
トレースを開始します。
xperf -start MySession -on MyEventProvider -f MySession.etl
このコマンド ラインでは、-start によってイベント コレクションに名前が指定され、-on によってこのセッションでプロバーダーからイベントを収集することが ETW に伝達されます (-on 引数は複数指定できます)。
ワークロードを実行します。
トレースの停止:
xperf -stop MySession
ETL ファイルを作成したら、Windows Performance Analyzer ツールでそのファイルを開き、汎用イベントのグラフと表を使用してイベントを視覚化することができます。