Events
May 19, 6 PM - May 23, 12 AM
Calling all developers, creators, and AI innovators to join us in Seattle @Microsoft Build May 19-22.
Register todayThis browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
The following example shows you how to use events to calculate the CPU usage for a set of instructions. This example assumes the provider wraps the instruction set with a start event type and an end event type.
//Turns the DEFINE_GUID for EventTraceGuid into a const.
#define INITGUID
#include <windows.h>
#include <stdio.h>
#include <wbemidl.h>
#include <wmistr.h>
#include <evntrace.h>
#define LOGFILE_PATH L"<FULLPATHTOLOGFILE.etl>"
//Remember to use your own GUID. Event class GUID used in the provider.
// {12BF20F2-0B1C-47e8-90B3-13C81C7AFD9A}
static const GUID CpuUsageEvent =
{ 0x12bf20f2, 0xb1c, 0x47e8, { 0x90, 0xb3, 0x13, 0xc8, 0x1c, 0x7a, 0xfd, 0x9a } };
// Used to calculate CPU usage
ULONG g_TimerResolution = 0;
// Used to determine if the session is a private session or kernel session.
// You need to know this when accessing some members of the EVENT_TRACE.Header
// member (for example, KernelTime or UserTime).
BOOL g_bUserMode = FALSE;
//Start time value for the start event.
ULONG g_StartKernelTime = 0;
ULONG g_StartUserTime = 0;
ULONG64 g_StartProcessTime = 0;
void WINAPI ProcessEvent(PEVENT_TRACE pEvent);
void wmain(void)
{
ULONG status = ERROR_SUCCESS;
EVENT_TRACE_LOGFILE trace;
TRACE_LOGFILE_HEADER* pHeader = &trace.LogfileHeader;
TRACEHANDLE hTrace = 0;
// Identify the log file from which you want to consume events
// and the callbacks used to process the events and buffers.
ZeroMemory(&trace, sizeof(EVENT_TRACE_LOGFILE));
trace.LogFileName = (LPWSTR) LOGFILE_PATH;
trace.EventCallback = (PEVENT_CALLBACK) (ProcessEvent);
hTrace = OpenTrace(&trace);
if ((TRACEHANDLE)INVALID_HANDLE_VALUE == hTrace)
{
wprintf(L"OpenTrace failed with %lu\n", GetLastError());
goto cleanup;
}
g_bUserMode = pHeader->LogFileMode & EVENT_TRACE_PRIVATE_LOGGER_MODE;
if (pHeader->TimerResolution > 0)
{
g_TimerResolution = pHeader->TimerResolution / 10000;
}
status = ProcessTrace(&hTrace, 1, 0, 0);
if (status != ERROR_SUCCESS && status != ERROR_CANCELLED)
{
wprintf(L"ProcessTrace failed with %lu\n", status);
goto cleanup;
}
cleanup:
if ((TRACEHANDLE)INVALID_HANDLE_VALUE != hTrace)
{
status = CloseTrace(hTrace);
}
}
VOID WINAPI ProcessEvent(PEVENT_TRACE pEvent)
{
ULONG64 CPUProcessUnits = 0;
ULONG CPUUnits = 0;
double CPUTime = 0;
// Skips the event if it is the event trace header. Log files contain this event
// but real-time sessions do not. The event contains the same information as
// the EVENT_TRACE_LOGFILE.LogfileHeader member that you can access when you open
// the trace.
if (IsEqualGUID(pEvent->Header.Guid, EventTraceGuid) &&
pEvent->Header.Class.Type == EVENT_TRACE_TYPE_INFO)
{
; // Skip this event.
}
else
{
if (IsEqualGUID(CpuUsageEvent, pEvent->Header.Guid))
{
// This example assumes that the start and end events are paired.
// If this is the start event type, retrieve the start time values from the
// event; otherwise, retrieve the end time values from the event.
if (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_START)
{
// If the session is a private session, use the ProcessorTime
// value to calculate the CPU time; otherwise, use the
// KernelTime and UserTime values.
if (g_bUserMode) // Private session
{
g_StartProcessTime = pEvent->Header.ProcessorTime;
}
else // Kernel session
{
g_StartKernelTime = pEvent->Header.KernelTime;
g_StartUserTime = pEvent->Header.UserTime;
}
}
else if (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_END)
{
if (g_bUserMode) // Private session
{
// Calculate CPU time units used.
CPUProcessUnits = pEvent->Header.ProcessorTime - g_StartProcessTime;
wprintf(L"CPU time units used, %Lu.\n", CPUProcessUnits);
// Processor time is in CPU ticks. Convert ticks to seconds.
// 1000000000 = nanoseconds in one second.
CPUTime = (double)(CPUProcessUnits) / 1000000000;
wprintf(L"Process CPU usage in seconds, %Lf.\n", CPUTime);
}
else // Kernel session
{
// Calculate the kernel mode CPU time units used for the set of instructions.
CPUUnits = pEvent->Header.KernelTime - g_StartKernelTime;
wprintf(L"CPU time units used (kernel), %d.\n", CPUUnits);
// Calculate the kernel mode CPU time in seconds for the set of instructions.
// 100 = 100 nanoseconds, 1000000000 = nanoseconds in one second
CPUTime = (double)(g_TimerResolution * CPUUnits * 100) / 1000000000;
wprintf(L"Kernel mode CPU usage in seconds, %Lf.\n", CPUTime);
// Calculate user mode CPU time units used for the set of instructions.
CPUUnits = pEvent->Header.UserTime - g_StartUserTime;
wprintf(L"\nCPU time units used (user), %d.\n", CPUUnits);
// Calculate the user mode CPU time in seconds for the set of instructions.
// 100 = 100 nanoseconds, 1000000000 = nanoseconds in one second
CPUTime = (double)(g_TimerResolution * CPUUnits * 100) / 1000000000;
wprintf(L"User mode CPU usage in seconds, %Lf.\n", CPUTime);
}
}
}
}
}
Events
May 19, 6 PM - May 23, 12 AM
Calling all developers, creators, and AI innovators to join us in Seattle @Microsoft Build May 19-22.
Register today