AMDTResult tpCollectImpl::tpStopThreadProfile() { AMDTResult retVal = AMDT_STATUS_OK; ULONG status = ERROR_SUCCESS; //if (!tpIsProfileInitialized()) //{ // retVal = AMDT_ERROR_PROFILE_NOT_CONFIGURED; //} if (!tpIsProfileRunning()) { retVal = AMDT_ERROR_PROFILE_NOT_STARTED; } PEVENT_TRACE_PROPERTIES pSessionProperties = m_pSessionProperties; bool isCollectCStack = m_callstack; if (NULL == pSessionProperties) { retVal = AMDT_ERROR_INTERNAL; } //fprintf(stderr, "tpStopThreadProfile .. retVal(%lx), state(%u)\n", retVal, m_tpState); if (AMDT_STATUS_OK == retVal) { // To disable stack tracing, call this function with InformationClass set to TraceStackTracingInfo // and InformationLength set to 0 if (isCollectCStack) { status = TraceSetInformation(m_sessionHandle, TraceStackTracingInfo, NULL, 0); fprintf(stderr, "Disable stack tracing - TraceSetInformation() status(%lu)\n", status); } status = ControlTrace(m_sessionHandle, KERNEL_LOGGER_NAME, pSessionProperties, EVENT_TRACE_CONTROL_STOP); //fprintf(stderr, "ControlTrace(stop) status(%lu)\n", status); if (ERROR_SUCCESS != status) { // FIXME: what to do if it fails fprintf(stderr, "ControlTrace(stop) failed with %lu\n", status); } // TODO: set this only is top succeeds m_tpState = AMDT_THREAD_PROFILE_STATE_UNINITIALIZED; status = tpClear(); } return status; } // tpStopThreadProfile
int __cdecl wmain() { CLASSIC_EVENT_ID EventId[2]; ULONG Status = ERROR_SUCCESS; TRACEHANDLE SessionHandle = 0; PEVENT_TRACE_PROPERTIES TraceProperties; BOOLEAN TraceStarted = FALSE; ULONG SystemTraceFlags[8]; PWSTR LoggerName = L"MyTrace"; HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0); // // Allocate EVENT_TRACE_PROPERTIES structure and perform some // basic initialization. // // N.B. LoggerName will be populated during StartTrace call. // TraceProperties = AllocateTraceProperties(NULL, L"SystemTrace.etl"); if (TraceProperties == NULL) { Status = ERROR_OUTOFMEMORY; goto Exit; } // // Configure additinal trace settings. // TraceProperties->LogFileMode = EVENT_TRACE_FILE_MODE_SEQUENTIAL | EVENT_TRACE_SYSTEM_LOGGER_MODE; TraceProperties->Wnode.ClientContext = 1; // Use QueryPerformanceCounter for time stamps TraceProperties->MaximumFileSize = 100; // Limit file size to 100MB max TraceProperties->BufferSize = 512; // Use 512KB trace buffers TraceProperties->MinimumBuffers = 64; TraceProperties->MaximumBuffers = 128; // // Start trace session which can receive events from SystemTraceProvider. // Status = StartTrace(&SessionHandle, LoggerName, TraceProperties); if (Status != ERROR_SUCCESS) { wprintf(L"StartTrace() failed with %lu\n", Status); goto Exit; } TraceStarted = TRUE; // // Configure stack walking. In this example stack traces will be collected on // ImageLoad and ProcessCreate events. // // N.B. Stack tracing is configured before enabling event collection. // ZeroMemory(EventId, sizeof(EventId)); EventId[0].EventGuid = ImageLoadGuid; EventId[0].Type = EVENT_TRACE_TYPE_LOAD; EventId[1].EventGuid = ProcessGuid; EventId[1].Type = EVENT_TRACE_TYPE_START; Status = TraceSetInformation(SessionHandle, TraceStackTracingInfo, EventId, sizeof(EventId)); if (Status != ERROR_SUCCESS) { wprintf(L"TraceSetInformation(StackTracing) failed with %lu\n", Status); goto Exit; } // // Enable system events for Process, Thread and Loader groups. // ZeroMemory(SystemTraceFlags, sizeof(SystemTraceFlags)); SystemTraceFlags[0] = (EVENT_TRACE_FLAG_PROCESS | EVENT_TRACE_FLAG_THREAD | EVENT_TRACE_FLAG_IMAGE_LOAD); Status = TraceSetInformation(SessionHandle, TraceSystemTraceEnableFlagsInfo, SystemTraceFlags, sizeof(SystemTraceFlags)); if (Status != ERROR_SUCCESS) { wprintf(L"TraceSetInformation(EnableFlags) failed with %lu\n", Status); goto Exit; } // // Collect trace for 30 seconds. // Sleep(30 * 1000); Exit: // // Stop tracing. // if (TraceStarted != FALSE) { Status = ControlTrace(SessionHandle, NULL, TraceProperties, EVENT_TRACE_CONTROL_STOP); if (Status != ERROR_SUCCESS) { wprintf(L"StopTrace() failed with %lu\n", Status); } } if (TraceProperties != NULL) { FreeTraceProperties(TraceProperties); } return Status; }
AMDTResult tpCollectImpl::tpStartThreadProfile() { AMDTResult retVal = AMDT_STATUS_OK; ULONG status; if (!tpIsProfileInitialized()) { retVal = AMDT_ERROR_PROFILE_NOT_CONFIGURED; } if (tpIsProfileRunning()) { retVal = AMDT_ERROR_PROFILE_ALREADY_STARTED; } PTRACEHANDLE pSessionHandle = &m_sessionHandle; PEVENT_TRACE_PROPERTIES pSessionProperties = m_pSessionProperties; bool isCollectCStack = m_callstack; if (NULL == pSessionProperties) { retVal = AMDT_ERROR_INTERNAL; } if (AMDT_STATUS_OK == retVal) { // Create the trace session. status = StartTrace(pSessionHandle, KERNEL_LOGGER_NAME, pSessionProperties); if (ERROR_SUCCESS == status) { // StartTrace succeeded. // Events in "NT Kernel Logger", // - EVENT_TRACE_FLAG_THREAD // - Supported Event Type // 1 - EVENT_TRACE_TYPE_START Start thread event. The Thread_V2_TypeGroup1 MOF class defines the // event data for this event // 2 - EVENT_TRACE_TYPE_END End thread event. The Thread_V2_TypeGroup1 MOF class defines the // event data for this event // 36 - Context switch event. The CSwitch MOF class defines the event data for this event // 50 - Ready thread event. The ReadyThread MOF class defines the event data for this event // // - EVENT_TRACE_FLAG_IMAGE_LOAD // - Supported Event Type // 10 - EVENT_TRACE_TYPE_LOAD Image load event. Generated when a DLL or executable file is loaded. // The provider generates only one event for the first time a given DLL is loaded. // The Image_Load MOF class defines the event data for this event // 2 - EVENT_TRACE_TYPE_END End thread event. Image unload event. Generated when a DLL or executable // file is unloaded. The provider generates only one event for the last time a given DLL is unloaded. // The Image_Load MOF class defines the event data for this event // // - EVENT_TRACE_FLAG_CSWITCH // - Enables the following *Thread* event type - CSWITCH // FIXME: Do i need to enable EVENT_TRACE_FLAG_THREAD or just enabling EVENT_TRACE_FLAG_CSWITCH is enough? // // StackWalk_Event class will have the stack data // https://msdn.microsoft.com/en-us/library/windows/desktop/dd392323(v=vs.85).aspx // CLASSIC_EVENT_ID traceCSForClasses[] = { { PerfInfoGuid, 46, { 0 } }, // { ThreadGuid, 36, { 0 } }, // { ThreadGuid, 50, { 0 } } }; if (isCollectCStack) { CLASSIC_EVENT_ID traceCallStackForClasses[] = { //{ g_threadGuid, 1, { 0 } }, // Start Thread Event //{ g_threadGuid, 2, { 0 } }, // End Thread Event { g_threadGuid, 36, { 0 } }, // Context Switch Event //{ g_threadGuid, 50, { 0 } } // Ready Thread Event }; status = TraceSetInformation(*pSessionHandle, TraceStackTracingInfo, traceCallStackForClasses, sizeof(traceCallStackForClasses)); if (ERROR_SUCCESS != status) { retVal = AMDT_ERROR_INTERNAL; fprintf(stderr, "TraceSetInformation() status(%lu)\n", status); } } } else if (ERROR_ALREADY_EXISTS == status) { retVal = AMDT_ERROR_PROFILE_SESSION_EXISTS; fprintf(stderr, "The NT Kernel Logger session is already in use.\n"); // TODO: Use ControlTrace() to update status = ControlTraceW(0, KERNEL_LOGGER_NAME, pSessionProperties, EVENT_TRACE_CONTROL_UPDATE); fprintf(stderr, "ControlTraceW status(%lu).\n", status); if (ERROR_SUCCESS == status) { retVal = AMDT_STATUS_OK; } else { // FIXME: just for testing purpose status = ControlTrace(m_sessionHandle, KERNEL_LOGGER_NAME, pSessionProperties, EVENT_TRACE_CONTROL_STOP); } } else { retVal = AMDT_ERROR_INTERNAL; fprintf(stderr, "StartTrace() failed with %lu\n", status); } } if (AMDT_STATUS_OK == retVal) { m_tpState = AMDT_THREAD_PROFILE_STATE_STARTED; } return retVal; } // tpStartThreadProfile