| 467 | } |
| 468 | |
| 469 | ULONG PMTraceSession::Start( |
| 470 | wchar_t const* etlPath, |
| 471 | wchar_t const* sessionName, |
| 472 | bool enableProviders) |
| 473 | { |
| 474 | assert(mPMConsumer != nullptr); |
| 475 | assert(mSessionHandle == 0); |
| 476 | assert(mTraceHandle == INVALID_PROCESSTRACE_HANDLE); |
| 477 | mStartTimestamp.QuadPart = 0; |
| 478 | mContinueProcessingBuffers = TRUE; |
| 479 | mIsRealtimeSession = etlPath == nullptr; |
| 480 | ResetEtwEventLatencyStats(); |
| 481 | mPMConsumer->mIsRealtimeSession = mIsRealtimeSession; |
| 482 | |
| 483 | // If we're not reading an ETL, start a realtime trace session with the |
| 484 | // required providers enabled. |
| 485 | if (mIsRealtimeSession) { |
| 486 | TraceProperties sessionProps = {}; |
| 487 | sessionProps.Wnode.BufferSize = (ULONG) sizeof(TraceProperties); |
| 488 | sessionProps.Wnode.ClientContext = mTimestampType; // Clock resolution to use when logging the timestamp for each event |
| 489 | sessionProps.Wnode.Flags = WNODE_FLAG_TRACED_GUID; |
| 490 | sessionProps.LogFileMode = EVENT_TRACE_REAL_TIME_MODE; // We have a realtime consumer, not writing to a log file |
| 491 | sessionProps.LoggerNameOffset = offsetof(TraceProperties, mSessionName); // Location of session name; will be written by StartTrace() |
| 492 | sessionProps.BufferSize = 64; // Buffer size in KB |
| 493 | sessionProps.MinimumBuffers = 256; // Minimum number of buffers allocated for the session's buffer pool |
| 494 | sessionProps.MaximumBuffers = 1024; // Maximum number of buffers (0 = no limit) |
| 495 | |
| 496 | auto status = StartTraceW(&mSessionHandle, sessionName, &sessionProps); |
| 497 | if (status != ERROR_SUCCESS) { |
| 498 | mSessionHandle = 0; |
| 499 | return status; |
| 500 | } |
| 501 | |
| 502 | // Set the session GUID |
| 503 | mSessionGuid = sessionProps.Wnode.Guid; |
| 504 | |
| 505 | if (enableProviders) { |
| 506 | status = EnableProviders(mSessionHandle, sessionProps.Wnode.Guid, mPMConsumer); |
| 507 | if (status != ERROR_SUCCESS) { |
| 508 | Stop(); |
| 509 | return status; |
| 510 | } |
| 511 | } |
| 512 | } |
| 513 | |
| 514 | // Open a trace to collect the session events |
| 515 | EVENT_TRACE_LOGFILEW traceProps = {}; |
| 516 | traceProps.ProcessTraceMode = PROCESS_TRACE_MODE_EVENT_RECORD | PROCESS_TRACE_MODE_RAW_TIMESTAMP; |
| 517 | traceProps.Context = this; |
| 518 | |
| 519 | if (mIsRealtimeSession) { |
| 520 | traceProps.LoggerName = (wchar_t*) sessionName; |
| 521 | traceProps.ProcessTraceMode |= PROCESS_TRACE_MODE_REAL_TIME; |
| 522 | } else { |
| 523 | traceProps.LogFileName = (wchar_t*) etlPath; |
| 524 | |
| 525 | // When processing log files, we need to use the buffer callback in |
| 526 | // case the user wants to stop processing before the entire log has |
no test coverage detected