PEVENT_RECORD_CALLBACK
コールバックシグネチャ
void PEVENT_RECORD_CALLBACK(
EVENT_RECORD* EventRecord
);パラメーター
| フィールド | 型 | 説明 |
|---|---|---|
| EventRecord | EVENT_RECORD* | イベント情報が格納された EVENT_RECORD 構造体へのポインターです。 |
公式ドキュメント
コンシューマーは、トレース処理セッションからイベントを受け取るためにこのコールバックを実装します。
PEVENT_RECORD_CALLBACK 型は、このコールバック関数へのポインターを定義します。EventRecordCallback は、アプリケーション定義の関数名のプレースホルダーです。
解説(Remarks)
イベントを配信するために ETW が呼び出す関数を指定するには、OpenTrace 関数に渡す EVENT_TRACE_LOGFILE 構造体の EventRecordCallback、Context、ProcessTraceMode の各メンバーを設定します。
- EventRecordCallback には、コールバック関数のアドレスを設定します。
- Context には、コールバックに渡される各 EVENT_RECORD の UserContext フィールドに含めたい値を設定します。
- ProcessTraceMode には、トレースの処理時に使用するフラグを設定します。EventRecordCallback を使用するには、ProcessTraceMode の値に PROCESS_TRACE_MODE_EVENT_RECORD を含める必要があります。
EventRecordCallback 関数が ProcessTrace から壊れたデータを受け取っている場合は、OpenTrace に渡した EVENT_TRACE_LOGFILE 構造体の ProcessTraceMode フィールドに指定したフラグを再確認してください。EVENT_TRACE_LOGFILE の EventCallback フィールドと EventRecordCallback フィールドは、共用体の重なり合ったメンバーです。ProcessTraceMode フィールドに PROCESS_TRACE_MODE_EVENT_RECORD フラグが含まれている場合、ProcessTrace は EventRecordCallback の関数シグネチャでコールバックを呼び出します。含まれていない場合、ProcessTrace は EventCallback の関数シグネチャでコールバックを呼び出します。
OpenTrace でトレース処理セッションを作成した後、ProcessTrace 関数を呼び出すとイベントの受信が始まります。
ProcessTrace がトレースのイベント処理を開始すると、ログに記録されたイベントのデータではなく、トレースに関するデータ (メタデータ) を含む 1 つ以上の合成イベントでコールバックを呼び出すことがあります。これらの合成イベントでは、EventHeader.ProviderId に EventTraceGuid が設定され、EventHeader.EventDescriptor.Opcode は合成イベントの内容に応じて設定されます。たとえば、各トレースファイルの最初のイベントは、TRACE_LOGFILE_HEADER の情報を含む Opcode 0 の合成イベントになります。
それ以外に受け取るイベントには、すべてプロバイダー固有のイベントデータが含まれます。受け取ったイベントの種類は、EVENT_RECORD の EventHeader.ProviderId メンバーと EventHeader.EventDescriptor メンバーを使用して判別します。
- イベントが既知のプロバイダーから送られたもので、データのレイアウトが分かっている場合は、独自の仕組みでイベントをデコードできます。
- EventHeader.Flags フィールドに
EVENT_HEADER_FLAG_TRACE_MESSAGEフラグが含まれている場合、そのイベントは WPP メッセージです。適切なデコード情報 (TMF ファイルまたは PDB ファイル) が利用できる場合は、TdhGetProperty または TdhGetWppProperty を使用してイベントをデコードできます。 - それ以外の場合、イベントは MOF ベース、マニフェストベース、または TraceLogging のイベントである可能性があります。適切なデコード情報が利用できる場合は、TdhGetEventInformation を使用してイベントをデコードできます。
- イベントが MOF ベースのデコードを使用する場合、TdhGetEventInformation はシステムの WMI データストアからイベントのデコード情報を探します。
- イベントがマニフェストベースのデコードを使用する場合、TdhGetEventInformation は、システムに登録されたマニフェスト、または TdhLoadManifest や TdhLoadManifestFromBinary によってプロセスごとのデコードコンテキストに読み込まれたマニフェストやバイナリからイベントのデコード情報を探します。
- イベントが TraceLogging ベースのデコードを使用する場合、TdhGetEventInformation はイベント内に含まれるデコード情報を使用します。
ほとんどの場合、イベントは発生した順序 (タイムスタンプ順) でコールバックに配信されます。ただし、特定の状況では、イベントが元の順序どおりに配信されないことがあります。
- セッションのタイムスタンプにシステム時刻を使用しているトレース (つまり
properties.Wnode.ClientContextに 2 を設定して開始したトレースセッション) で、セッションがイベントを収集している間にシステムクロックが逆方向に調整された場合、一部のイベントが順不同で配信されることがあります。これを避けるには、ClientContext に 0 を設定して既定のタイムスタンプ (QPC 時刻) を使用してください。 - 精度の低いクロックのタイムスタンプを使用してトレースが収集されている場合、異なる CPU から送られたタイムスタンプが同じイベントが順不同で配信されることがあります。これは、システム時刻がティック単位で進むため、セッションのタイムスタンプにシステム時刻を使用しているトレースで最も頻繁に発生します。この問題は、LogFileMode フラグに
EVENT_TRACE_NO_PER_PROCESSOR_BUFFERINGを指定してセッションを開始することで回避できますが、トレースのパフォーマンスに大きな悪影響を与える可能性があります。Windows 10 以降: システム時刻のクロック種別では GetSystemTimePreciseAsFileTime が使用されるため、この問題が発生する可能性は低くなっています。 - トレースが破損している場合、ファイル内で想定されるタイムスタンプの規則を維持しない低レベル API で生成された場合、またはイベントの書き込み時にタイムスタンプの上書きオプションを使用している場合、一部のイベントが順不同で配信されることがあります。
技術的な詳細: イベントはバッファーに格納されます。各バッファーはバッファーストリームに割り当てられ、通常は CPU ごとに 1 つのストリームが割り当てられます。ProcessTrace の実装は、バッファー内のすべてのイベントがタイムスタンプ順に並んでいること、および各バッファーが、同じストリーム内の他のバッファーの期間と重ならない単一の時間範囲のイベントを含んでいることを前提としています。これらの前提が満たされない場合、ProcessTrace はイベントを順不同で配信することがあります。
リアルタイムのトレース収集セッションに、関連付けられたトレース処理セッションが存在しない場合、収集されたイベントはバッファーがいっぱいになるまでシステムによってバッファリングされます。トレース処理セッションがリアルタイムのトレース収集セッションに接続すると、そのトレース処理セッションはまずセッションの合成イベントを受け取り、次にバッファリングされていたイベントを受け取り、その後、新たに生成されるリアルタイムイベントの受信を開始します。2 つ目のリアルタイム処理セッションが同じトレース収集セッションに接続した場合、そのセッションは合成イベントと新たに生成されるリアルタイムイベントを受け取ります (2 つ目のトレース処理セッションは、それより前のイベントを受け取りません)。
リアルタイムセッションのイベントを処理する場合、処理コールバックが各イベントの処理に時間をかけすぎ、かつイベントの到着が速すぎると、処理が追いつかなくなります。システムはデータの損失を防ぐためにイベントをバッファリングしますが、これによりシステムリソースの使用量 (メモリやディスクの使用量など) が増加します。この問題を避けるには、セッションのフィルター (プロバイダーごとのレベルフィルターやキーワードフィルターなど) を使用して受信イベントのレートを下げ、コールバック内で早期にフィルタリングを行って完全な処理が不要なイベントをスキップし、処理スレッドをブロックしないようにコールバックができるだけ早く戻るよう最適化してください。
イベントデータの解釈に関する詳細については、Consuming Events と Retrieving Event Data Using TDH を参照してください。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)