event_trace_consumer.h 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. // Copyright (c) 2012 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. // Declaration of a Windows event trace consumer base class.
  6. #ifndef BASE_WIN_EVENT_TRACE_CONSUMER_H_
  7. #define BASE_WIN_EVENT_TRACE_CONSUMER_H_
  8. #include <windows.h>
  9. #include <evntrace.h>
  10. #include <stddef.h>
  11. #include <wmistr.h>
  12. #include <vector>
  13. #include "base/macros.h"
  14. #include "base/threading/scoped_blocking_call.h"
  15. namespace base {
  16. namespace win {
  17. // This class is a base class that makes it easier to consume events
  18. // from realtime or file sessions. Concrete consumers need to subclass
  19. // a specialization of this class and override the ProcessEvent and/or
  20. // the ProcessBuffer methods to implement the event consumption logic.
  21. // Usage might look like:
  22. // class MyConsumer: public EtwTraceConsumerBase<MyConsumer, 1> {
  23. // protected:
  24. // static VOID WINAPI ProcessEvent(PEVENT_TRACE event);
  25. // };
  26. //
  27. // MyConsumer consumer;
  28. // consumer.OpenFileSession(file_path);
  29. // consumer.Consume();
  30. template <class ImplClass>
  31. class EtwTraceConsumerBase {
  32. public:
  33. // Constructs a closed consumer.
  34. EtwTraceConsumerBase() = default;
  35. ~EtwTraceConsumerBase() { Close(); }
  36. // Opens the named realtime session, which must be existent.
  37. // Note: You can use OpenRealtimeSession or OpenFileSession
  38. // to open as many as MAXIMUM_WAIT_OBJECTS (63) sessions at
  39. // any one time, though only one of them may be a realtime
  40. // session.
  41. HRESULT OpenRealtimeSession(const wchar_t* session_name);
  42. // Opens the event trace log in "file_name", which must be a full or
  43. // relative path to an existing event trace log file.
  44. // Note: You can use OpenRealtimeSession or OpenFileSession
  45. // to open as many as kNumSessions at any one time.
  46. HRESULT OpenFileSession(const wchar_t* file_name);
  47. // Consume all open sessions from beginning to end.
  48. HRESULT Consume();
  49. // Close all open sessions.
  50. HRESULT Close();
  51. protected:
  52. // Override in subclasses to handle events.
  53. static void ProcessEvent(EVENT_TRACE* event) {}
  54. // Override in subclasses to handle buffers.
  55. static bool ProcessBuffer(EVENT_TRACE_LOGFILE* buffer) {
  56. return true; // keep going
  57. }
  58. protected:
  59. // Currently open sessions.
  60. std::vector<TRACEHANDLE> trace_handles_;
  61. private:
  62. // These delegate to ImplClass callbacks with saner signatures.
  63. static void WINAPI ProcessEventCallback(EVENT_TRACE* event) {
  64. ImplClass::ProcessEvent(event);
  65. }
  66. static ULONG WINAPI ProcessBufferCallback(PEVENT_TRACE_LOGFILE buffer) {
  67. return ImplClass::ProcessBuffer(buffer);
  68. }
  69. DISALLOW_COPY_AND_ASSIGN(EtwTraceConsumerBase);
  70. };
  71. template <class ImplClass>
  72. inline HRESULT EtwTraceConsumerBase<ImplClass>::OpenRealtimeSession(
  73. const wchar_t* session_name) {
  74. EVENT_TRACE_LOGFILE logfile = {};
  75. logfile.LoggerName = const_cast<wchar_t*>(session_name);
  76. logfile.LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
  77. logfile.BufferCallback = &ProcessBufferCallback;
  78. logfile.EventCallback = &ProcessEventCallback;
  79. logfile.Context = this;
  80. TRACEHANDLE trace_handle = ::OpenTrace(&logfile);
  81. if (reinterpret_cast<TRACEHANDLE>(INVALID_HANDLE_VALUE) == trace_handle)
  82. return HRESULT_FROM_WIN32(::GetLastError());
  83. trace_handles_.push_back(trace_handle);
  84. return S_OK;
  85. }
  86. template <class ImplClass>
  87. inline HRESULT EtwTraceConsumerBase<ImplClass>::OpenFileSession(
  88. const wchar_t* file_name) {
  89. EVENT_TRACE_LOGFILE logfile = {};
  90. logfile.LogFileName = const_cast<wchar_t*>(file_name);
  91. logfile.BufferCallback = &ProcessBufferCallback;
  92. logfile.EventCallback = &ProcessEventCallback;
  93. logfile.Context = this;
  94. TRACEHANDLE trace_handle = ::OpenTrace(&logfile);
  95. if (reinterpret_cast<TRACEHANDLE>(INVALID_HANDLE_VALUE) == trace_handle)
  96. return HRESULT_FROM_WIN32(::GetLastError());
  97. trace_handles_.push_back(trace_handle);
  98. return S_OK;
  99. }
  100. template <class ImplClass>
  101. inline HRESULT EtwTraceConsumerBase<ImplClass>::Consume() {
  102. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  103. base::BlockingType::MAY_BLOCK);
  104. ULONG err = ::ProcessTrace(&trace_handles_[0],
  105. static_cast<ULONG>(trace_handles_.size()), nullptr,
  106. nullptr);
  107. return HRESULT_FROM_WIN32(err);
  108. }
  109. template <class ImplClass>
  110. inline HRESULT EtwTraceConsumerBase<ImplClass>::Close() {
  111. HRESULT hr = S_OK;
  112. for (size_t i = 0; i < trace_handles_.size(); ++i) {
  113. if (NULL != trace_handles_[i]) {
  114. ULONG ret = ::CloseTrace(trace_handles_[i]);
  115. trace_handles_[i] = NULL;
  116. if (FAILED(HRESULT_FROM_WIN32(ret)))
  117. hr = HRESULT_FROM_WIN32(ret);
  118. }
  119. }
  120. trace_handles_.clear();
  121. return hr;
  122. }
  123. } // namespace win
  124. } // namespace base
  125. #endif // BASE_WIN_EVENT_TRACE_CONSUMER_H_