123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- // Copyright (c) 2012 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- //
- // Declaration of a Windows event trace consumer base class.
- #ifndef BASE_WIN_EVENT_TRACE_CONSUMER_H_
- #define BASE_WIN_EVENT_TRACE_CONSUMER_H_
- #include <windows.h>
- #include <evntrace.h>
- #include <stddef.h>
- #include <wmistr.h>
- #include <vector>
- #include "base/macros.h"
- #include "base/threading/scoped_blocking_call.h"
- namespace base {
- namespace win {
- // This class is a base class that makes it easier to consume events
- // from realtime or file sessions. Concrete consumers need to subclass
- // a specialization of this class and override the ProcessEvent and/or
- // the ProcessBuffer methods to implement the event consumption logic.
- // Usage might look like:
- // class MyConsumer: public EtwTraceConsumerBase<MyConsumer, 1> {
- // protected:
- // static VOID WINAPI ProcessEvent(PEVENT_TRACE event);
- // };
- //
- // MyConsumer consumer;
- // consumer.OpenFileSession(file_path);
- // consumer.Consume();
- template <class ImplClass>
- class EtwTraceConsumerBase {
- public:
- // Constructs a closed consumer.
- EtwTraceConsumerBase() = default;
- ~EtwTraceConsumerBase() { Close(); }
- // Opens the named realtime session, which must be existent.
- // Note: You can use OpenRealtimeSession or OpenFileSession
- // to open as many as MAXIMUM_WAIT_OBJECTS (63) sessions at
- // any one time, though only one of them may be a realtime
- // session.
- HRESULT OpenRealtimeSession(const wchar_t* session_name);
- // Opens the event trace log in "file_name", which must be a full or
- // relative path to an existing event trace log file.
- // Note: You can use OpenRealtimeSession or OpenFileSession
- // to open as many as kNumSessions at any one time.
- HRESULT OpenFileSession(const wchar_t* file_name);
- // Consume all open sessions from beginning to end.
- HRESULT Consume();
- // Close all open sessions.
- HRESULT Close();
- protected:
- // Override in subclasses to handle events.
- static void ProcessEvent(EVENT_TRACE* event) {}
- // Override in subclasses to handle buffers.
- static bool ProcessBuffer(EVENT_TRACE_LOGFILE* buffer) {
- return true; // keep going
- }
- protected:
- // Currently open sessions.
- std::vector<TRACEHANDLE> trace_handles_;
- private:
- // These delegate to ImplClass callbacks with saner signatures.
- static void WINAPI ProcessEventCallback(EVENT_TRACE* event) {
- ImplClass::ProcessEvent(event);
- }
- static ULONG WINAPI ProcessBufferCallback(PEVENT_TRACE_LOGFILE buffer) {
- return ImplClass::ProcessBuffer(buffer);
- }
- DISALLOW_COPY_AND_ASSIGN(EtwTraceConsumerBase);
- };
- template <class ImplClass>
- inline HRESULT EtwTraceConsumerBase<ImplClass>::OpenRealtimeSession(
- const wchar_t* session_name) {
- EVENT_TRACE_LOGFILE logfile = {};
- logfile.LoggerName = const_cast<wchar_t*>(session_name);
- logfile.LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
- logfile.BufferCallback = &ProcessBufferCallback;
- logfile.EventCallback = &ProcessEventCallback;
- logfile.Context = this;
- TRACEHANDLE trace_handle = ::OpenTrace(&logfile);
- if (reinterpret_cast<TRACEHANDLE>(INVALID_HANDLE_VALUE) == trace_handle)
- return HRESULT_FROM_WIN32(::GetLastError());
- trace_handles_.push_back(trace_handle);
- return S_OK;
- }
- template <class ImplClass>
- inline HRESULT EtwTraceConsumerBase<ImplClass>::OpenFileSession(
- const wchar_t* file_name) {
- EVENT_TRACE_LOGFILE logfile = {};
- logfile.LogFileName = const_cast<wchar_t*>(file_name);
- logfile.BufferCallback = &ProcessBufferCallback;
- logfile.EventCallback = &ProcessEventCallback;
- logfile.Context = this;
- TRACEHANDLE trace_handle = ::OpenTrace(&logfile);
- if (reinterpret_cast<TRACEHANDLE>(INVALID_HANDLE_VALUE) == trace_handle)
- return HRESULT_FROM_WIN32(::GetLastError());
- trace_handles_.push_back(trace_handle);
- return S_OK;
- }
- template <class ImplClass>
- inline HRESULT EtwTraceConsumerBase<ImplClass>::Consume() {
- base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
- base::BlockingType::MAY_BLOCK);
- ULONG err = ::ProcessTrace(&trace_handles_[0],
- static_cast<ULONG>(trace_handles_.size()), nullptr,
- nullptr);
- return HRESULT_FROM_WIN32(err);
- }
- template <class ImplClass>
- inline HRESULT EtwTraceConsumerBase<ImplClass>::Close() {
- HRESULT hr = S_OK;
- for (size_t i = 0; i < trace_handles_.size(); ++i) {
- if (NULL != trace_handles_[i]) {
- ULONG ret = ::CloseTrace(trace_handles_[i]);
- trace_handles_[i] = NULL;
- if (FAILED(HRESULT_FROM_WIN32(ret)))
- hr = HRESULT_FROM_WIN32(ret);
- }
- }
- trace_handles_.clear();
- return hr;
- }
- } // namespace win
- } // namespace base
- #endif // BASE_WIN_EVENT_TRACE_CONSUMER_H_
|