I am using Event Tracing for Windows to monitor disk io and network usage of processes. I have used ETW with KERNEL_LOGGER_NAME , EVENT_TRACE_FLAG_PROCESS , EVENT_TRACE_FLAG_DISK_IO, EVENT_TRACE_FLAG_NETWORK_TCPIP:
static const GUID GUID_DISK_IO = { 0x3d6fa8d4, 0xfe05, 0x11d0, { 0x9d, 0xda, 0x00, 0xc0, 0x4f, 0xd7, 0xba, 0x7c } };
static const GUID GUID_TCPIP = { 0x9a280ac0, 0xc8e0, 0x11d1, { 0x84, 0xe2, 0x00, 0xc0, 0x4f, 0xb9, 0x98, 0xa2 } };
VOID WINAPI ProcessMonitor::EventRecordCallback(PEVENT_RECORD pEventRecord) {
bool isIo = false, isNet = false;
if (pEventRecord->EventHeader.ProviderId == GUID_DISK_IO) isIo = true;
if (pEventRecord->EventHeader.ProviderId == GUID_TCPIP) isNet = true;
if (!isIo && !isNet) return;
if (pEventRecord->EventHeader.EventDescriptor.Opcode != 10 && pEventRecord->EventHeader.EventDescriptor.Opcode != 11) return;
DWORD pid = pEventRecord->EventHeader.ProcessId;
ULONG dataSize = 0;
//std::cout << "Event appeared\n";
PROPERTY_DATA_DESCRIPTOR desc;
ZeroMemory(&desc, sizeof(desc));
desc.PropertyName = (ULONGLONG)L"Size";
desc.ArrayIndex = ULONG_MAX;
TDHSTATUS status = TdhGetProperty(pEventRecord, 0, nullptr, 1, &desc, sizeof(dataSize), (PBYTE)&dataSize);
if (status != ERROR_SUCCESS) {
ZeroMemory(&desc, sizeof(desc));
desc.PropertyName = (ULONGLONG)L"size";
desc.ArrayIndex = ULONG_MAX;
status = TdhGetProperty(pEventRecord, 0, nullptr, 1, &desc, sizeof(dataSize), (PBYTE)&dataSize);
if (status != ERROR_SUCCESS) {
ZeroMemory(&desc, sizeof(desc));
desc.PropertyName = (ULONGLONG)L"length";
desc.ArrayIndex = ULONG_MAX;
status = TdhGetProperty(pEventRecord, 0, nullptr, 1, &desc, sizeof(dataSize), (PBYTE)&dataSize);
if (status != ERROR_SUCCESS) {
ZeroMemory(&desc, sizeof(desc));
desc.PropertyName = (ULONGLONG)L"TransferSize";
desc.ArrayIndex = ULONG_MAX;
status = TdhGetProperty(pEventRecord, 0, nullptr, 1, &desc, sizeof(dataSize), (PBYTE)&dataSize);
if (status != ERROR_SUCCESS) return;
}
}
}
std::cout << "PID: " << pid << " Trace data: " << dataSize << "\n";
auto* self = (ProcessMonitor*)(pEventRecord->UserContext);
if (isIo) self->addIoCount(dataSize, pid);
if (isNet) self->addNetCount(dataSize, pid);
}
void ProcessMonitor::run() {
//...............................ETW............................
TRACEHANDLE hSession = 0;
ULONG bufferSize = sizeof(EVENT_TRACE_PROPERTIES) + 1024;
EVENT_TRACE_PROPERTIES* pSessionProperties = (EVENT_TRACE_PROPERTIES*)malloc(bufferSize);
ZeroMemory(pSessionProperties, bufferSize);
pSessionProperties->Wnode.BufferSize = bufferSize;
pSessionProperties->Wnode.ClientContext = 1;
pSessionProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
wcscpy_s((wchar_t*)(pSessionProperties + 1), 1024, KERNEL_LOGGER_NAME);
pSessionProperties->LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
pSessionProperties->EnableFlags = EVENT_TRACE_FLAG_PROCESS |
EVENT_TRACE_FLAG_IMAGE_LOAD |
EVENT_TRACE_FLAG_DISK_IO |
EVENT_TRACE_FLAG_DISK_IO_INIT |
EVENT_TRACE_FLAG_FILE_IO |
EVENT_TRACE_FLAG_NETWORK_TCPIP;
ULONG status = StartTrace(&hSession, KERNEL_LOGGER_NAME, pSessionProperties);
if (status != ERROR_SUCCESS) {
std::cout << "StartTrace failed: " << status << "\n";
return;
}
EVENT_TRACE_LOGFILE logFile = {};
logFile.LoggerName = (LPWSTR)KERNEL_LOGGER_NAME;
logFile.ProcessTraceMode = PROCESS_TRACE_MODE_REAL_TIME | PROCESS_TRACE_MODE_EVENT_RECORD;
logFile.EventRecordCallback = EventRecordCallback;
logFile.Context = this;
TRACEHANDLE hTrace = OpenTrace(&logFile);
if (hTrace == INVALID_PROCESSTRACE_HANDLE) {
std::cout << "OpenTrace failed\n";
return;
}
std::cout << "Start tracing...\n";
std::thread traceThread([&]() {
ProcessTrace(&hTrace, 1, nullptr, nullptr);
});
while (1) {
if (_kbhit()) {
char c = _getch();
if (c == 'q') break;
}
scan();
sample();
std::this_thread::sleep_for(std::chrono::seconds(monitorInterval));
}
CloseTrace(hTrace);
ControlTrace(hSession, KERNEL_LOGGER_NAME, pSessionProperties, EVENT_TRACE_CONTROL_STOP);
traceThread.join();
free(pSessionProperties);
}
...but all I got is a bunch of events with PID: 4294967295 (Trace data is the size of data of the events) when running a browser with about 10 tabs:
PID: 4294967295 Trace data: 24576
PID: 4294967295 Trace data: 24576
PID: 4294967295 Trace data: 8192
PID: 4294967295 Trace data: 106496
PID: 4294967295 Trace data: 4096
PID: 4294967295 Trace data: 24576
PID: 4294967295 Trace data: 4096
PID: 4294967295 Trace data: 4096
Help me find out where I have wrong.
4294967295is 0xFFFFFFFF so I expect it to mean some type of error likeINVALID_HANDLE_VALUEdataSizeand printed so I think the tracing process worked but have some problems with the process id.EVENT_RECORD? Please provide a minimal reproducible example that demonstrates the problem in action.logFile.EventRecordCallback = EventRecordCallback;. AfterOpenTrace(), ETW will call this function if events appeared.