TraceLoggingWrite macro (traceloggingprovider.h)

Emits a TraceLogging event.


void TraceLoggingWrite(
  [in]            hProvider,
  [in]            eventName,
  [in, optional]  __VA_ARGS__


[in] hProvider

The handle of the TraceLogging provider to use for writing the event.

[in] eventName

A short and unique name to use for identifying the event. This must be a string literal and not a variable. It cannot have any embedded '\0' characters.

[in, optional] __VA_ARGS__

Up to 99 additional parameters to configure or add fields to the event. Each parameter must be one of the TraceLogging Wrapper Macros, such as TraceLoggingLevel, TraceLoggingKeyword, or TraceLoggingValue.


ProviderId, Level and Keyword are the primary means for filtering events. Other kinds of filtering are possible but have much higher overhead. Always assign a non-zero level and keyword to every event.

Return value



Each invocation of the TraceLoggingWrite macro expands to the code necessary to write an event to ETW through the specified provider handle.

  • TraceLoggingWrite checks whether the specified provider is registered. If the provider is not registered, TraceLoggingWrite does nothing.
  • TraceLoggingWrite checks whether any consumer is listening for the event, as if by calling TraceLoggingProviderEnabled. If no consumer is listening for the event, TraceLoggingWrite does nothing.
  • Otherwise, TraceLoggingWrite evaluates the runtime expressions specified in the arguments, saves the results, packs the necessary data into an event, and calls EventWriteTransfer to send the event to ETW.

The generated event will be constructed as follows:

  • The event's provider ID, provider name, and provider group will come from the hProvider parameter.
  • The event's name will come from the eventName parameter.
  • In user-mode, the event's activity ID will come from the thread's implicit activity ID. In kernel-mode, the event's activity ID will be GUID_NULL.
  • The event will not have a related activity ID.
  • The event's level will come from the TraceLoggingLevel argument. If no TraceLoggingLevel argument is present, the event's level will be 5 (WINEVENT_LEVEL_VERBOSE). If more than one TraceLoggingLevel argument is present, the last argument will be used. To enable effective event filtering, always assign a meaningful non-zero level to every event.
  • The event's keyword will come from the TraceLoggingKeyword argument. If no TraceLoggingKeyword argument is present, the event's keyword will be 0 (NONE). If more than one TraceLoggingKeyword argument is present, the values will be OR'ed together. To enable effective event filtering, always assign a meaningful non-zero keyword to every event.
  • Other event attributes may be set by arguments such as TraceLoggingOpcode, TraceLoggingDescription, TraceLoggingEventTag, or TraceLoggingChannel.
  • Event fields can be grouped using TraceLoggingStruct.
  • Event fields are added by field arguments like TraceLoggingValue, TraceLoggingInt32, TraceLoggingHResult, TraceLoggingString, etc. See TraceLogging Wrapper Macros for details.

For example:

    TraceLoggingLevel(WINEVENT_LEVEL_WARNING), // Levels defined in <winmeta.h>
    TraceLoggingString(operationName), // Adds an "operationName" field.
    TraceLoggingHResult(hr, "NetStatus")); // Adds a "NetStatus" field.

An invocation of TraceLoggingWrite(hProvider, "EventName", args...) can be thought of as expanding to code like the following:

if (TraceLoggingProviderEnabled(hProvider, eventLevel, eventKeyword))
    static const metadata = { GetMetadataFromArgs(args...) };
    EVENT_DATA_DESCRIPTOR data[N] = { GetDataFromArgs(args...) };
    EventWriteTransfer(etwHandle, metadata.desc, NULL, NULL, N, data);


Each TraceLoggingWrite macro automatically checks TraceLoggingProviderEnabled so the event will only be written if a consumer is listening for events from the provider. As a result, it is usually unnecessary to directly call TraceLoggingProviderEnabled. Any runtime expressions in args... will be evaluated if and only if the event is enabled. Runtime expressions will not be evaluated more than once.

If generating complex events, you might get a compiler error indicating that the line is too long or that the compiler is out of heap space. This occurs when the TraceLoggingWrite macro expands to a line longer than can be supported by the compiler. If this happens you will need to simplify your event.

The TraceLoggingWrite macro uses an array of EVENT_DATA_DESCRIPTOR to transfer data to ETW. The maximum number of descriptors accepted by ETW is 128. Since each parameter may require the use of 0, 1, or 2 descriptors, it is possible to hit the data descriptor limit (128) before hitting the argument limit (99).


Try to avoid large events. ETW is primarily designed for handling small events. TraceLoggingWrite will silently drop any event that is too large. The event's size is based on the total of the event's headers (added by the ETW runtime), metadata (i.e. provider name, event name, field names, field types), and data (field values). If the event's total size is greater than 65535 or if the consumer session is using a buffer size smaller than the event's size, the event will not be recorded.

A call to TraceLoggingWrite is the same as a call to TraceLoggingWriteActivity with NULL for the pActivityId and pRelatedActivityId parameters. Use TraceLoggingWriteActivity if you need to specify activity IDs for an event.


#include <windows.h> // or <wdm.h> for kernel-mode.
#include <winmeta.h> // For event level definitions.
#include <TraceLoggingProvider.h>

    g_hProvider,  // Name of the provider handle
    "MyProvider", // Human-readable name of the provider
    // ETW Control GUID: {b3864c38-4273-58c5-545b-8b3608343471}

int main(int argc, char* argv[]) // or DriverEntry for kernel-mode.

        TraceLoggingLevel(WINEVENT_LEVEL_WARNING), // Levels defined in <winmeta.h>
        TraceLoggingKeyword(MyEventCategories), // Provider-defined categories
        TraceLoggingString(argv[0], "arg0"), // field name is "arg0"
        TraceLoggingInt32(argc)); // field name is implicitly "argc"

    return 0;


Minimum supported client Windows Vista [desktop apps | UWP apps]
Minimum supported server Windows Server 2008 [desktop apps | UWP apps]
Target Platform Windows
Header traceloggingprovider.h
Library Advapi32.lib

See also



TraceLogging Wrapper Macros