event_trace_controller.cc 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. // Copyright (c) 2009 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. //
  5. // Implementation of a Windows event trace controller class.
  6. #include "base/win/event_trace_controller.h"
  7. #include "base/check.h"
  8. #include "base/numerics/checked_math.h"
  9. constexpr size_t kDefaultRealtimeBufferSizeKb = 16;
  10. namespace base {
  11. namespace win {
  12. EtwTraceProperties::EtwTraceProperties() {
  13. memset(buffer_, 0, sizeof(buffer_));
  14. EVENT_TRACE_PROPERTIES* prop = get();
  15. prop->Wnode.BufferSize = sizeof(buffer_);
  16. prop->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
  17. prop->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
  18. prop->LogFileNameOffset =
  19. sizeof(EVENT_TRACE_PROPERTIES) + sizeof(wchar_t) * kMaxStringLen;
  20. }
  21. HRESULT EtwTraceProperties::SetLoggerName(const wchar_t* logger_name) {
  22. size_t len = wcslen(logger_name) + 1;
  23. if (kMaxStringLen < len)
  24. return E_INVALIDARG;
  25. memcpy(buffer_ + get()->LoggerNameOffset, logger_name, sizeof(wchar_t) * len);
  26. return S_OK;
  27. }
  28. HRESULT EtwTraceProperties::SetLoggerFileName(const wchar_t* logger_file_name) {
  29. size_t len = wcslen(logger_file_name) + 1;
  30. if (kMaxStringLen < len)
  31. return E_INVALIDARG;
  32. memcpy(buffer_ + get()->LogFileNameOffset, logger_file_name,
  33. sizeof(wchar_t) * len);
  34. return S_OK;
  35. }
  36. EtwTraceController::EtwTraceController() = default;
  37. EtwTraceController::~EtwTraceController() {
  38. if (session_)
  39. Stop(nullptr);
  40. }
  41. HRESULT EtwTraceController::Start(const wchar_t* session_name,
  42. EtwTraceProperties* prop) {
  43. DCHECK(NULL == session_ && session_name_.empty());
  44. EtwTraceProperties ignore;
  45. if (prop == nullptr)
  46. prop = &ignore;
  47. HRESULT hr = Start(session_name, prop, &session_);
  48. if (SUCCEEDED(hr))
  49. session_name_ = session_name;
  50. return hr;
  51. }
  52. HRESULT EtwTraceController::StartFileSession(const wchar_t* session_name,
  53. const wchar_t* logfile_path,
  54. bool realtime) {
  55. DCHECK(NULL == session_ && session_name_.empty());
  56. EtwTraceProperties prop;
  57. prop.SetLoggerFileName(logfile_path);
  58. EVENT_TRACE_PROPERTIES& p = *prop.get();
  59. p.Wnode.ClientContext = 1; // QPC timer accuracy.
  60. p.LogFileMode = EVENT_TRACE_FILE_MODE_SEQUENTIAL; // Sequential log.
  61. if (realtime)
  62. p.LogFileMode |= EVENT_TRACE_REAL_TIME_MODE;
  63. p.MaximumFileSize = 100; // 100M file size.
  64. p.FlushTimer = 30; // 30 seconds flush lag.
  65. return Start(session_name, &prop);
  66. }
  67. HRESULT EtwTraceController::StartRealtimeSession(const wchar_t* session_name,
  68. size_t buffer_size) {
  69. DCHECK(NULL == session_ && session_name_.empty());
  70. EtwTraceProperties prop;
  71. EVENT_TRACE_PROPERTIES& p = *prop.get();
  72. p.LogFileMode = EVENT_TRACE_REAL_TIME_MODE | EVENT_TRACE_USE_PAGED_MEMORY;
  73. p.FlushTimer = 1; // flush every second.
  74. p.BufferSize = checked_cast<ULONG>(
  75. buffer_size ? buffer_size : kDefaultRealtimeBufferSizeKb);
  76. p.LogFileNameOffset = 0;
  77. return Start(session_name, &prop);
  78. }
  79. HRESULT EtwTraceController::EnableProvider(REFGUID provider,
  80. UCHAR level,
  81. ULONG flags) {
  82. ULONG error = ::EnableTrace(TRUE, flags, level, &provider, session_);
  83. return HRESULT_FROM_WIN32(error);
  84. }
  85. HRESULT EtwTraceController::DisableProvider(REFGUID provider) {
  86. ULONG error = ::EnableTrace(FALSE, 0, 0, &provider, session_);
  87. return HRESULT_FROM_WIN32(error);
  88. }
  89. HRESULT EtwTraceController::Stop(EtwTraceProperties* properties) {
  90. EtwTraceProperties ignore;
  91. if (properties == nullptr)
  92. properties = &ignore;
  93. ULONG error = ::ControlTrace(session_, nullptr, properties->get(),
  94. EVENT_TRACE_CONTROL_STOP);
  95. if (ERROR_SUCCESS != error)
  96. return HRESULT_FROM_WIN32(error);
  97. session_ = NULL;
  98. session_name_.clear();
  99. return S_OK;
  100. }
  101. HRESULT EtwTraceController::Flush(EtwTraceProperties* properties) {
  102. EtwTraceProperties ignore;
  103. if (properties == nullptr)
  104. properties = &ignore;
  105. ULONG error = ::ControlTrace(session_, nullptr, properties->get(),
  106. EVENT_TRACE_CONTROL_FLUSH);
  107. if (ERROR_SUCCESS != error)
  108. return HRESULT_FROM_WIN32(error);
  109. return S_OK;
  110. }
  111. HRESULT EtwTraceController::Start(const wchar_t* session_name,
  112. EtwTraceProperties* properties,
  113. TRACEHANDLE* session_handle) {
  114. DCHECK(properties != nullptr);
  115. ULONG err = ::StartTrace(session_handle, session_name, properties->get());
  116. return HRESULT_FROM_WIN32(err);
  117. }
  118. HRESULT EtwTraceController::Query(const wchar_t* session_name,
  119. EtwTraceProperties* properties) {
  120. ULONG err = ::ControlTrace(NULL, session_name, properties->get(),
  121. EVENT_TRACE_CONTROL_QUERY);
  122. return HRESULT_FROM_WIN32(err);
  123. }
  124. HRESULT EtwTraceController::Update(const wchar_t* session_name,
  125. EtwTraceProperties* properties) {
  126. DCHECK(properties != nullptr);
  127. ULONG err = ::ControlTrace(NULL, session_name, properties->get(),
  128. EVENT_TRACE_CONTROL_UPDATE);
  129. return HRESULT_FROM_WIN32(err);
  130. }
  131. HRESULT EtwTraceController::Stop(const wchar_t* session_name,
  132. EtwTraceProperties* properties) {
  133. DCHECK(properties != nullptr);
  134. ULONG err = ::ControlTrace(NULL, session_name, properties->get(),
  135. EVENT_TRACE_CONTROL_STOP);
  136. return HRESULT_FROM_WIN32(err);
  137. }
  138. HRESULT EtwTraceController::Flush(const wchar_t* session_name,
  139. EtwTraceProperties* properties) {
  140. DCHECK(properties != nullptr);
  141. ULONG err = ::ControlTrace(NULL, session_name, properties->get(),
  142. EVENT_TRACE_CONTROL_FLUSH);
  143. return HRESULT_FROM_WIN32(err);
  144. }
  145. } // namespace win
  146. } // namespace base