TraceLogging Examples
The source code in this topic demonstrates how to use TraceLogging.
#include <windows.h>
#include <TraceLoggingProvider.h>
#include <winmeta.h>
/*
Invoke this macro to allocate storage for a provider and declare a
corresponding handle symbol. The provider name must be a string literal (not a
variable) and must not contain any '\0' characters.
Note that the handle is created in the "unregistered" state and will ignore
any TraceLoggingWrite calls until it is registered.
*/
TRACELOGGING_DEFINE_PROVIDER(
g_hProvider,
"TraceLoggingProviderSample",
// {a12b3f0b-1161-5d99-1553-a9194ee77d81}
(0xa12b3f0b, 0x1161, 0x5d99, 0x15, 0x53, 0xa9, 0x19, 0x4e, 0xe7, 0x7d, 0x81));
ULONG StartUp()
{
/*
Call this function to register your provider with ETW.
This is analogous to the ETW EventRegister() function.
The provider handle must be in the "unregistered" state.
Returns ERROR_SUCCESS if the provider was successfully registered.
Note that it is ok to ignore failure - if TraceLoggingRegister
fails, TraceLoggingWrite and TraceLoggingUnregister will be no-ops.
*/
ULONG RegisterResult = TraceLoggingRegister(g_hProvider);
return RegisterResult;
}
ULONG ShutDown()
{
/*
Call this function to unregister your provider. Once unregistered,
TraceLoggingWrite will be a no-op until the provider is registered again.
Analogous to the ETW EventUnregister() function.
*/
TraceLoggingUnregister(g_hProvider);
return ERROR_SUCCESS;
}
void BasicDataTypes()
{
UINT8 u8 = 200;
INT32 i32 = -2000000000;
UINT32 u32 = 4000000000;
INT64 i64 = 9000000000000000000;
float f32 = 3.14f;
BOOL b = TRUE;
BOOLEAN bcpp = TRUE;
/*
The following four "NumericValues" events are equivalent (except where noted) ...
*/
TraceLoggingWrite(
g_hProvider,
"NumericValues",
TraceLoggingUInt8(u8, "MyUINT8_field"),
TraceLoggingInt32(i32, "MyINT32_field"),
TraceLoggingUInt32(u32, "MyUINT32_field"),
TraceLoggingHexUInt32(u32, "MyHexUINT32_field"),
TraceLoggingInt64(i64, "MyINT64_field"),
TraceLoggingFloat32(f32, "My_float_field"),
TraceLoggingBool(b, "MyBool32_field"),
TraceLoggingBoolean(bcpp, "MyBool8_field")
);
/*
same as ...
*/
#ifdef __cplusplus
/*
TraceLoggingValue() automatically determines the value type (C++ only)
*/
TraceLoggingWrite(
g_hProvider,
"NumericValuesCpp",
TraceLoggingValue(u8, "MyUINT8"),
TraceLoggingValue(i32, "MyINT32"),
TraceLoggingValue(u32, "MyUINT32"),
TraceLoggingValue(i64, "MyINT64"),
TraceLoggingValue(f32, "MyFloat"),
TraceLoggingValue(b, "MyBOOL32"), // Since BOOL is a typedef for int, this will be evaluated as TraceLoggingInt32, not as TraceLoggingBool
TraceLoggingValue(bcpp, "MyBool8"));
#endif
/*
Strings and chars
*/
TraceLoggingWrite(
g_hProvider,
"Strings and Chars",
TraceLoggingString("She loves me ...", "String (char)"),
TraceLoggingWideString(L"She loves me not ...", "String (wide char)"),
TraceLoggingChar('A', "Single char"),
TraceLoggingWChar(L'z', "Single wide char"));
/*
Other types
*/
/*
NOTE:
In C, a GUID, FILETIME, or SYSTEMTIME value parameter must be an l-value.
*/
INT_PTR iptr = 1234;
UINT_PTR uptr = 4321;
FILETIME ft;
SYSTEMTIME st;
SID const sid1 = { SID_REVISION, 1, 5, { 6 } };
GUID g = {0};
GetSystemTime(&st);
GetSystemTimeAsFileTime(&ft);
TraceLoggingWrite(
g_hProvider,
"Other Types",
TraceLoggingGuid(g, "GUID"),
TraceLoggingFileTime(ft, "Current Time (FILETIME)"),
TraceLoggingSystemTime(st, "Current Time (SYSTEMTIME)"),
TraceLoggingSid(&sid1, "SID"),
TraceLoggingPointer((LPCVOID)&g, "void*"),
TraceLoggingIntPtr(iptr, "INT_PTR"),
TraceLoggingUIntPtr(uptr, "UINT_PTR")
);
}
void NamingData()
{
UINT32 Cat = 0xCA7;
/*
Each of the following four events are equivalent:
*/
/*
TraceLogging uses the symbol to automatically name the field "Cat"
and assign it the value contained in the variable Cat (0xCA7).
*/
TraceLoggingWrite(
g_hProvider,
"MoreThanOneWayToSkinACat",
TraceLoggingUInt32(Cat, "Cat") // Field explicitly named "Cat"
);
TraceLoggingWrite(
g_hProvider,
"MoreThanOneWayToSkinACat",
TraceLoggingUInt32(Cat) // Field automatically named "Cat" named based on the expression Cat.
);
/*
Let's use a different symbol for the value of the event's "Cat" field.
*/
UINT32 Tiger = Cat;
/*
Now we need to explicitly name the datum or we will have events with a
different field name ("Tiger").
*/
TraceLoggingWrite(
g_hProvider,
"MoreThanOneWayToSkinACat",
TraceLoggingUInt32(Tiger, "Cat") // Field explicitly named "Cat"
);
TraceLoggingWrite(
g_hProvider,
"MoreThanOneWayToSkinACat",
TraceLoggingUInt32(Tiger) // Field automatically named "Tiger".
);
};
void LevelsAndKeywords()
{
/*
Verbosity levels and event keywords must be compile-time constants.
TraceLoggingLevel accepts values 0..255, though only 0..5 are well-defined.
0 means "always". 1 means "fatal". 2 means "error". 3 means "warning".
4 means "info". 5 means "verbose". If TraceLoggingLevel is not set for an
event, the default is 5 (verbose).
See winmeta.h for predefined verbosity levels.
TraceLoggingKeyword is a 64-bit bitfield. The top 16 bits are reserved by
Microsoft for special situations. The low 48 bits are available for
definition on a per-provider basis.
*/
PCWSTR MyName = L"Joe";
INT16 MyRank = 99;
ULONG MySerialNumber = 12345;
/*
The following is only logged when session verbosity level is
WINEVENT_LEVEL_VERBOSE (5) or higher ...
*/
TraceLoggingWrite(
g_hProvider,
"Levels",
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingWideString(MyName, "Name"),
TraceLoggingInt16(MyRank, "Rank"),
TraceLoggingUInt32(MySerialNumber, "Serial Number")
);
/*
TraceLoggingWrite will not complain if TraceLoggingLevel is invoked more than once.
However, only the last level will be used.
The following event is only logged at WINEVENT_LEVEL_VERBOSE or higher...
*/
TraceLoggingWrite(
g_hProvider,
"Levels",
TraceLoggingLevel(WINEVENT_LEVEL_CRITICAL),
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingWideString(MyName, "Name"),
TraceLoggingInt16(MyRank, "Rank"),
TraceLoggingUInt32(MySerialNumber, "Serial Number")
);
/*
Keywords, however, can be combined using multiple TraceLoggingKeyword() macros ...
*/
#define MY_PROVIDER_KEYWORD_BLUE 0x1
#define MY_PROVIDER_KEYWORD_YELLOW 0x2
#define MY_PROVIDER_KEYWORD_GREEN (MY_PROVIDER_KEYWORD_BLUE | MY_PROVIDER_KEYWORD_YELLOW)
PCWSTR Status = L"Feeling a bit green";
/*
These events are equivalent ...
*/
TraceLoggingWrite(
g_hProvider,
"Keywords",
TraceLoggingKeyword(MY_PROVIDER_KEYWORD_GREEN),
TraceLoggingWideString(Status, "Current Status")
);
TraceLoggingWrite(
g_hProvider,
"Keywords",
TraceLoggingKeyword(MY_PROVIDER_KEYWORD_BLUE | MY_PROVIDER_KEYWORD_YELLOW),
TraceLoggingWideString(Status, "Current Status")
);
TraceLoggingWrite(
g_hProvider,
"Keywords",
TraceLoggingKeyword(MY_PROVIDER_KEYWORD_BLUE),
TraceLoggingKeyword(MY_PROVIDER_KEYWORD_YELLOW),
TraceLoggingWideString(Status, "Current Status")
);
}
void Arrays()
{
INT32 IntVals[5] = {20, 21, 22, 23, 24};
UINT cIntVals = 5;
/*
Variable size arrays
*/
TraceLoggingWrite(
g_hProvider,
"Variable Size Arrays",
TraceLoggingInt32Array(IntVals, (UINT16)cIntVals, "Variable size int array")
);
/*
Fixed size arrays
Fixed size array macros use the "FixedArray" suffix.
The absence of the suffix indicates a variable sized array.
*/
TraceLoggingWrite(
g_hProvider,
"Constant Size Arrays",
TraceLoggingInt32FixedArray(IntVals, _countof(IntVals),
"Constant size int array"));
}
void Structs()
{
WIN32_FIND_DATA FindData;
HANDLE hFind = FindFirstFile(L".", &FindData);
if (hFind == INVALID_HANDLE_VALUE)
{
return;
}
/*
TraceLoggingStruct defines a group of related fields in an event.
The first parameter, which must be a compile-time constant, indicates
the number of subsequent fields that are to be considered part of the
struct.
*/
TraceLoggingWrite(
g_hProvider,
"FindFirstFile",
TraceLoggingStruct(5, "FileData"),
TraceLoggingWideString(FindData.cFileName, "Name"),
TraceLoggingUInt32(FindData.dwFileAttributes, "Attributes"),
TraceLoggingFileTime(FindData.ftCreationTime, "CreateTime"),
TraceLoggingUInt32(FindData.nFileSizeHigh, "SizeHigh"),
TraceLoggingUInt32(FindData.nFileSizeLow, "SizeLow"),
TraceLoggingPointer(hFind, "Result")
);
/*
If you commonly use the same set of fields, you might define a helper macro.
*/
#define LogWin32FindData(fd) \
TraceLoggingStruct(5, "FileData"), \
TraceLoggingWideString(((fd).cFileName), "Name"), \
TraceLoggingUInt32(((fd).dwFileAttributes), "Attributes"), \
TraceLoggingFileTime(((fd).ftCreationTime), "CreateTime"), \
TraceLoggingUInt32(((fd).nFileSizeHigh), "SizeHigh"), \
TraceLoggingUInt32(((fd).nFileSizeLow), "SizeLow")
TraceLoggingWrite(
g_hProvider,
"FindFirstFile",
LogWin32FindData(FindData),
TraceLoggingPointer(hFind, "Result")
);
FindClose(hFind);
}
int __cdecl
main()
{
// Note:
StartUp();
BasicDataTypes();
NamingData();
LevelsAndKeywords();
Arrays();
Structs();
ShutDown();
}