Win32 API 日本語リファレンス
ホーム › System.Diagnostics.Etw › PENABLECALLBACK

PENABLECALLBACK

コールバック

シグネチャ

void PENABLECALLBACK(
    GUID* SourceId,
    ENABLECALLBACK_ENABLED_STATE IsEnabled,
    BYTE Level,
    ULONGLONG MatchAnyKeyword,
    ULONGLONG MatchAllKeyword,
    EVENT_FILTER_DESCRIPTOR* FilterData,
    void* CallbackContext
);

パラメーター

フィールド型説明
SourceIdGUID*

プロバイダーを有効または無効にする呼び出し元が指定した GUID です。

この値は、EnableTraceEx の SourceId パラメーター、または EnableTraceEx2 に渡される ENABLE_TRACE_PARAMETERS の SourceId フィールドに由来します。

メモ

SourceId は、セッションが EnableTraceEx または EnableTraceEx2 API の呼び出しで指定した値です。セッションの GUID と同じであるとは限りません。

通知にソース識別子が存在しないいくつかの状況では、SourceId は GUID_NULL に設定されます。たとえば、プロバイダーの開始前にトレースセッションがプロバイダーを有効にしていた場合、プロバイダーが停止しようとしている場合、あるいはトレースコントローラーが SourceId を指定せずに EnableTrace API を呼び出した場合に発生します。

IsEnabledENABLECALLBACK_ENABLED_STATE

この通知に対応する ControlCode を示します。次のいずれかの値になります。

値 意味
EVENT_CONTROL_CODE_DISABLE_PROVIDER (0) プロバイダーを有効にしているセッションがありません。
EVENT_CONTROL_CODE_ENABLE_PROVIDER (1) 1 つ以上のセッションがプロバイダーを有効にしています。
EVENT_CONTROL_CODE_CAPTURE_STATE (2) セッションが、プロバイダーに状態情報のログ記録を要求しています。プロバイダーは通常、プロバイダーの状態を含むイベントを書き込むことで応答します。
メモ

IsEnabled の値は、この通知を発生させた EnableTrace API に渡された ControlCode と同じであるとは限りません。たとえば、2 つのセッションがこのプロバイダーを有効にしていて、一方のセッションが EnableTraceEx2(..., EVENT_CONTROL_CODE_DISABLE_PROVIDER, ...) を呼び出してこのプロバイダーを無効にした場合、もう一方のセッションによってプロバイダーは依然として有効なままであるため、プロバイダーは IsEnabled が EVENT_CONTROL_CODE_ENABLE_PROVIDER に設定された通知を受け取ります。

DISABLE_PROVIDER 通知を受け取った後、プロバイダーはすべてのイベントを無効にすることでパフォーマンスを最適化できます。ENABLE_PROVIDER 通知を受け取った後、プロバイダーはイベントの書き込みを有効にする必要があります。また、Level、MatchAnyKeyword、MatchAllKeyword の各フィルターの値を記録しておき、フィルターを通過するイベントだけを書き込むことでパフォーマンスを最適化することもできます (remarks を参照)。CAPTURE_STATE 通知を受け取った後、プロバイダーは適切と思われる任意の処理を行えます。通常は、コンポーネントの構成や状態を表すイベントを書き込みます。

プロバイダーは、認識できない、またはサポートしていない IsEnabled の値を持つ通知は無視してください。

LevelBYTE

プロバイダーが書き込むべきイベントの詳細度 (verbosity) を指定する値です。制御コード EVENT_CONTROL_CODE_ENABLE_PROVIDER で呼び出された場合、プロバイダーは Level の値を記録し、以降はイベントの詳細度レベルが記録した Level より大きいイベントをスキップする必要があります。つまり、イベントは次の条件を満たす場合にのみ書き込みます。

eventDescriptor.Level <= recorded.Level

通知内の Level は、このイベントプロバイダーの GUID を指定して EnableTrace、EnableTraceEx、EnableTraceEx2 を呼び出したトレースコントローラーが指定したレベルの最大値です。言い換えると、複数のセッションが異なる詳細度レベルでこのイベントプロバイダーのイベントを記録している場合、EnableCallback 通知の Level パラメーターには、それらのレベルのうち最も高い (最も詳細な) 値が設定されます。

MatchAnyKeywordULONGLONG

プロバイダーが書き込むべきイベントのカテゴリを指定するビットマスク値です。制御コード EVENT_CONTROL_CODE_ENABLE_PROVIDER で呼び出された場合、プロバイダーは MatchAnyKeyword の値を記録し、以降はイベントのキーワードが 0 以外で、かつ記録した MatchAnyKeyword のビットをいずれも含まないイベントをスキップする必要があります。つまり、イベントは次の条件を満たす場合にのみ書き込みます。

eventDescriptor.Keyword == 0 || (eventDescriptor.Keyword & recorded.MatchAnyKeyword) != 0

通知内の MatchAnyKeyword は、このイベントプロバイダーの GUID を指定して EnableTrace、EnableTraceEx、EnableTraceEx2 を呼び出したトレースコントローラーが指定した match-any-keyword (有効化フラグ) の和 (OR) です。言い換えると、複数のセッションが異なる match-any-keyword フィルターでこのイベントプロバイダーのイベントを記録している場合、EnableCallback 通知の MatchAnyKeyword パラメーターには、各セッションの match-any-keyword フィルターのビットごとの OR が設定されます。

MatchAllKeywordULONGLONG

プロバイダーが書き込むべきイベントのカテゴリを指定するビットマスク値です。制御コード EVENT_CONTROL_CODE_ENABLE_PROVIDER で通知された場合、プロバイダーは MatchAllKeyword の値を記録し、以降はイベントのキーワードが 0 以外で、かつ記録した MatchAllKeyword のビットをすべては含まないイベントをスキップする必要があります。つまり、イベントは次の条件を満たす場合にのみ書き込みます。

eventDescriptor.Keyword == 0 || (eventDescriptor.Keyword & recorded.MatchAllKeyword) == recorded.MatchAllKeyword

通知内の MatchAllKeyword は、このイベントプロバイダーの GUID を指定して EnableTraceEx および EnableTraceEx2 を呼び出したトレースコントローラーが指定した match-all-keyword の論理積 (AND) です。言い換えると、複数のセッションが異なる match-all-keyword フィルターでこのイベントプロバイダーのイベントを記録している場合、EnableCallback 通知の MatchAllKeyword パラメーターには、各セッションの match-all-keyword フィルターのビットごとの AND が設定されます。

FilterDataEVENT_FILTER_DESCRIPTOR*

イベントプロバイダー向けのフィルターデータを保持する EVENT_FILTER_DESCRIPTOR へのポインターです。

各セッションが指定できるフィルターは 1 つだけです。コールバック通知のフィルター記述子には、プロバイダーを有効にする際にフィルターデータを指定した各セッションのフィルターが 1 つずつ含まれます。

フィルターデータが有効なのはコールバックの内部のみです。コールバックから戻った後もデータが必要な場合、プロバイダーはデータのローカルコピーを作成してください。

CallbackContextvoid*コールバック用のコンテキストです。これは、イベントプロバイダーが EventRegister を呼び出したときに使用した CallbackContext パラメーターの値です。

公式ドキュメント

ETW イベントプロバイダーは、構成変更の通知を受け取るために EnableCallback 関数を任意で定義します。PENABLECALLBACK 型は、このコールバック関数へのポインターを定義します。EnableCallback は、アプリケーション定義の関数名のプレースホルダーです。

解説(Remarks)

構成変更の通知を必要とする ETW イベントプロバイダーは、EventRegister で登録する際に、自身の EnableCallback 実装へのポインターを渡す必要があります。ETW は、そのプロバイダーが関係するトレースセッションの構成が変更されたときに、プロバイダーの EnableCallback 関数を呼び出します。たとえば、トレースセッションのコントローラーが EnableTraceEx2 でトレースを構成したり、ControlTrace でトレースを停止したりすると、ETW は更新後の構成を渡してプロバイダーの EnableCallback 関数を呼び出します。

メモ

ほとんどのイベントプロバイダーは EnableCallback を直接実装しません。代わりに、独自の EnableCallback 実装を提供し、EventRegister、EventWrite、EventUnregister の呼び出しをラップする ETW フレームワークを使って実装されます。たとえば、イベントマニフェストを記述して メッセージコンパイラー でイベント用の C/C++ コードを生成したり、マニフェストを不要にする TraceLogging を使用したりします。ETW フレームワークは通常、通知の Level、MatchAnyKeyword、MatchAllKeyword の各値を記録する EnableCallback 関数を実装し、記録した値を使って自動的にイベントをフィルターします。また ETW フレームワークは通常、独自の通知処理が必要な場合にユーザー提供のコールバックを呼び出す仕組みもサポートします。たとえば TraceLoggingProvider.h では、TraceLoggingRegisterEx によって通知コールバックを指定できます。

重要

プロバイダーの EnableCallback 関数は、できる限り単純にしてください。必要な情報を記録して速やかに戻る必要があります。実行に時間のかかるコールバック関数は、EnableTraceEx2 や ControlTrace などの ETW セッション制御 API の遅延を引き起こす可能性があります。コールバック関数は、プロセスのローダーロックを必要とする処理を行ってはなりません。つまり、直接的にも間接的にも LoadLibrary や FreeLibrary を呼び出してはなりません。コールバック関数はロックでブロックしてはなりません。ロックでブロックした場合や、StartTrace、ControlTrace、EnableTrace などの ETW セッション制御 API を呼び出した場合、コールバック関数はデッドロックを引き起こすおそれがあります。

通知コールバックによって、プロバイダーはレベル、キーワード、その他のフィルターを自前で追跡できるため、より効率的に動作できます。フィルターを追跡することで、有効になっていないイベントを効率良くスキップできます (すなわち、どのトレースセッションからも必要とされていないイベントについては、イベントデータを準備したり EventWrite を呼び出したりする必要がなくなります)。

なお、プロバイダーが正しく動作するためにフィルターの追跡が必須というわけではありません。ETW はプロバイダーが利用できる EventEnabled と EventProviderEnabled を提供しており、ETW の EventWrite API は無効なイベントを黙って無視します。ただし、プロバイダー側で実装したフィルター追跡のほうが、EventEnabled や EventProviderEnabled の呼び出しより効率的な場合があります。

通知コールバックによって、プロバイダーはトレースセッションからの「状態キャプチャ (capture-state)」要求を処理することもできます。状態キャプチャ要求は通常、トレースセッションがプロバイダーからのイベントの記録を開始するときに送られます。プロバイダーが状態キャプチャをサポートしている場合、状態情報 (要求前のコンポーネントの動作に関する構成情報や統計の要約など) をログに記録することで要求に応答できます。

ETW がコールバックに渡す Level の値は、実行中のいずれかのトレースセッションがこのイベントプロバイダーに対して指定したレベルのうち、最も高い (最も詳細な) 値です。たとえば、セッション A が警告 (レベル 3) のイベントでこのプロバイダーを有効にした後、セッション B が重大 (レベル 1) のイベントでこのプロバイダーを有効にした場合、コールバックの Level の値は 1 ではなく 3 になります。

同様に、MatchAnyKeyword と MatchAllKeyword の値も、そのイベントプロバイダーを有効にしているすべてのセッションの構成から算出される合成値です。MatchAnyKeyword は各セッションの EnableFlags/MatchAnyKeyword 設定の OR、MatchAllKeyword は各セッションの MatchAllKeyword 設定の AND になります。

プロバイダーの EnableCallback 関数がプロバイダーの Enabled、Level、MatchAnyKeyword、MatchAllKeyword の状態を保存していれば、プロバイダーは次のような関数でイベントを書き込むべきかどうかを判断できます。

BOOL MyProviderEventEnabled(
    _In_ const MY_PROVIDER_STATE* pProvider,
    _In_ const EVENT_DESCRIPTOR* pEvent)
{
    return
        pProvider->Enabled &&
        pEvent->Level <= pProvider->Level &&
        (pEvent->Keyword == 0 || (
            (pEvent->Keyword & pProvider->MatchAnyKeyword) != 0 &&
            (pEvent->Keyword & pProvider->MatchAllKeyword) == pProvider->MatchAllKeyword
        ));
}
出典・ライセンス: 上記「公式ドキュメント」の内容は Microsoft の Win32 API ドキュメント(MicrosoftDocs/sdk-api)を日本語に翻訳・改変したものです。© Microsoft Corporation. CC BY 4.0 で提供。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)