サボっていて申し訳ないです。
今回はコンシューマーを作ります。
コードは例によって GitHub に。
だいたいの流れ
- EVENT_TRACE_LOGFILE 構造体を初期化
- OpenTrace 関数でセッションを開く
- ProcessTrace 関数でイベントの処理を開始
- CloseTrace 関数でセッションを閉じる
EVENT_TRACE_LOGFILE 構造体の ProcessTraceMode メンバーには PROCESS_TRACE_MODE_EVENT_RECORD を指定します。
これは Windows Vista 以降の新しい方式(Manifest-based)を使うという意味です。
このフラグを含めないと、古い方式を使うことになります。
EventRecordCallback メンバーに指定したコールバック関数にイベント情報が渡されます。
プロバイダーが発行したイベント1つにつき、1回のコールバック関数が実行されます。
ProcessTrace 関数を呼ぶと、すべてのイベントの処理が終わるまで、呼び出し元には帰ってきません。
LogFileName には、コントローラーを作る時に指定した EVENT_TRACE_PROPERTIES 構造体の後ろの方にくっつけた(LogFileNameOffset でその位置を指し示した)ファイル名を指定します。
このサンプルでは、カレント ディレクトリに Controller1.etl ファイルがあることを前提にしていますので、実行する際はパスに注意してください。
訂正
当初、サンプルでは LogFileName と LoggerName を両方指定していましたが、これらは排他的でした。
本サンプルでは LogFileName のみ指定するように訂正しました。
肝心なのはコールバック
コードは一部抜粋しています。
コールバック関数には EVENT_RECORD 構造体が渡されます。
サンプルでは、このうち EVENT_HEADER 構造体に含まれるデータのみを表示しています。
さらにその中にある EVENT_DESCRIPTOR 構造体 が、マニフェストの event 要素で指定した属性を含みます。
EVENT_HEADER 構造体の TimeStamp メンバーは、イベントの発生時刻を FILETIME 構造体と同じ形式で含んでいます。
UTC なのでローカル時刻に直した後、わかりやすいように SYSTEMTIME 構造体に変換しています。
SYSTEMTIME 構造体はミリ秒単位までしか持たない一方、FILETIME 構造体は 100 ナノ秒単位で表されていますので、マイクロ秒以下の部分は自分で計算しています。
EVENT_RECORD はイベントのすべてのデータを含みますが、このうち、EventHeader(と、ExtendedData)に含まれる部分が、マニフェストの登録なしで取得できる、イベントの共通的なメタデータ(イベント ログで言うと System 要素にあたる部分)です。
言い換えれば、EVENT_RECORD 構造体の UserData メンバーは、マニフェストがないと内部を解析することができません。
そのあたりは後程やります。
次回予告
ここまでは、トレース データを一旦ファイルに溜めて、セッション終了後にコンシューマーがファイルから読み取るという方式を解説してきました。
次回は、ファイルを介さない、リアルタイムモードについて説明します。