TRACELOGGING_DEFINE_PROVIDER macro (traceloggingprovider.h)

Defines a handle for a TraceLogging provider.

Syntax

void TRACELOGGING_DEFINE_PROVIDER(
  [in]            handleVariable,
  [in]            providerName,
  [in]            providerId,
  [in, optional]  __VA_ARGS__
);

Parameters

[in] handleVariable

The name to use for the provider's handle, using your component's naming conventions for global variables, e.g. MyComponentLog or g_hMyProvider.

[in] providerName

A string literal with the name of the TraceLogging provider. This name should be specific to your organization and component so that it does not conflict with providers from other components. This name string will be included within each ETW event generated by the provider, so try to use a relatively short name. For example, you might use a name like "MyCompany.MyComponent" or "MyCompany.MyOrganization.MyComponent".

This must be a string literal. Do not use a variable.

[in] providerId

The ETW Control GUID for the provider, specified as a comma-separated list of 11 integers in parentheses. For example, the GUID {ce5fa4ea-ab00-5402-8b76-9f76ac858fb5} would be expressed as (0xce5fa4ea,0xab00,0x5402,0x8b,0x76,0x9f,0x76,0xac,0x85,0x8f,0xb5).

While any unique GUID can be used for the provider ID, Microsoft recommends using a GUID generated from the provider name using the ETW name-hashing algorithm. See below for information about generating the provider ID.

[in, optional] __VA_ARGS__

Optional parameters for the provider. Most providers do not need to specify any optional parameters.

If you want your provider to be associated with an ETW provider group, add the TraceLoggingOptionGroup macro to specify the provider's group GUID. Otherwise, do not specify any __VA_ARGS__ parameters.

Return value

None

Remarks

A TraceLogging provider is a connection by which events can be sent to ETW. The TRACELOGGING_DEFINE_PROVIDER macro defines a TraceLogging provider and creates a handle that can be used to access it. It also records provider information such as the provider's name and GUID.

This macro should be invoked in a .c or .cpp file to define the handle for a TraceLogging provider. For example, if my provider is named MyCompany.MyComponent and the control GUID is {ce5fa4ea-ab00-5402-8b76-9f76ac858fb5} then I would define the provider by adding the following code to one of the .c or .cpp files in my component:

TRACELOGGING_DEFINE_PROVIDER( // defines g_hProvider
    g_hProvider, // Name of the provider handle
    "MyCompany.MyComponent", // Human-readable name for the provider
    // {ce5fa4ea-ab00-5402-8b76-9f76ac858fb5}
    (0xce5fa4ea,0xab00,0x5402,0x8b,0x76,0x9f,0x76,0xac,0x85,0x8f,0xb5));

The above TRACELOGGING_DEFINE_PROVIDER macro can be thought of as defining a g_hMyProvider provider handle constant, similar to code like:

const TraceLoggingHProvider g_hMyProvider = ...;

The resulting handle has module scope and can be used anywhere within the EXE, DLL, or SYS module in which it is defined. Use the TRACELOGGING_DECLARE_PROVIDER macro as needed (e.g. in a header) to forward-declare the handle so that it can be used by other .c or .cpp files in your component.

When a component starts running, the provider will be in an unregistered state. Any attempts to use it to generate events will be silently ignored. Before it can respond to any write calls, you need to register the provider using TraceLoggingRegister. This is typically done during component startup, e.g. in main, wmain, WinMain, DllMain(DLL_PROCESS_ATTACH), or DriverEntry. At component shutdown, unregister the provider by calling TraceLoggingUnregister.

Note

The provider handle defined by TRACELOGGING_DEFINE_PROVIDER is scoped to the module. The handle can be used as needed within the EXE, DLL, or SYS file, but it should not be used outside the scope of the module, i.e. it should not be passed to other DLLs in the same process. Each EXE, DLL, or SYS file should use its own provider handle and should perform its own Register and Unregister. In debug builds, an assertion will fire if you attempt to write using a provider handle from another module.

Provider Name and ID

ETW performs event filtering and routing using the provider ID (also called the Provider GUID or Control GUID). For example, if you have a provider named MyCompany.MyComponent with provider ID {ce5fa4ea-ab00-5402-8b76-9f76ac858fb5} then you might start a trace to capture events from this provider using a tracelog command like tracelog -start MySessionName -f MySession.etl -guid #ce5fa4ea-ab00-5402-8b76-9f76ac858fb5.

All ETW providers are identified by both provider name and provider ID. Both the name and the ID need to be unique so they do not conflict with other providers. In addition, the name and the ID should be linked: once a particular name is used with a particular ID for an ETW provider, that name should not be used with any other ID and that ID should not be used with any other name.

The provider ID can be any unique GUID, such one generated using the guidgen SDK tool or https://uuidgen.org. However, instead of using a randomly-generated GUID for the provider ID, Microsoft recommends generating the provider ID from the provider name using the ETW name-hashing algorithm described below. This provides several benefits: it's easier to remember just the name; the ID and the name are automatically linked; tools such as tracelog, traceview, EventSource, and WPR have special support for providers that use IDs generated using this algorithm.

For example, if you have a provider named MyCompany.MyComponent with provider ID {ce5fa4ea-ab00-5402-8b76-9f76ac858fb5} then you might start a trace to capture events from this provider using a tracelog command like tracelog -start MySessionName -f MySession.etl -guid *MyCompany.MyComponent. This works because provider ID {ce5fa4ea-ab00-5402-8b76-9f76ac858fb5} was generated by hashing the provider name MyCompany.MyComponent, so the tracefmt tool considers -guid *MyCompany.MyComponent to be equivalent to -guid #ce5fa4ea-ab00-5402-8b76-9f76ac858fb5.

You can use PowerShell to obtain the provider ID for a particular provider name using the ETW name-hashing algorithm via the EventSource class:

[System.Diagnostics.Tracing.EventSource]::new("MyCompany.MyComponent").Guid

Results:

Guid
----
ce5fa4ea-ab00-5402-8b76-9f76ac858fb5

In C#, the ETW name-hashing algorithm can be implemented as follows:

static Guid ProviderIdFromName(string name)
{
    var signature = new byte[] {
        0x48, 0x2C, 0x2D, 0xB2, 0xC3, 0x90, 0x47, 0xC8,
        0x87, 0xF8, 0x1A, 0x15, 0xBF, 0xC1, 0x30, 0xFB };
    var nameBytes = System.Text.Encoding.BigEndianUnicode.GetBytes(name.ToUpperInvariant());
    using (var sha1 = new System.Security.Cryptography.SHA1Managed())
    {
        sha1.TransformBlock(signature, 0, signature.Length, null, 0);
        sha1.TransformFinalBlock(nameBytes, 0, nameBytes.Length);
        var hash = sha1.Hash;
        Array.Resize(ref hash, 16);
        hash[7] = (byte)((hash[7] & 0x0F) | 0x50);
        return new Guid(hash);
    }
}

Examples

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

TRACELOGGING_DEFINE_PROVIDER( // defines g_hProvider
    g_hProvider, // Name of the provider handle
    "MyCompany.MyComponent", // Human-readable name for the provider
    // {ce5fa4ea-ab00-5402-8b76-9f76ac858fb5}
    (0xce5fa4ea,0xab00,0x5402,0x8b,0x76,0x9f,0x76,0xac,0x85,0x8f,0xb5));

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

    TraceLoggingWrite(
        g_hProvider,
        "MyEvent1",
        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"

    TraceLoggingUnregister(g_hProvider);
    return 0;
}

Requirements

Requirement Value
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

See also

TRACELOGGING_DECLARE_PROVIDER

TraceLoggingWrite