summaryrefslogtreecommitdiffstats
path: root/base/event_trace_consumer_win.h
diff options
context:
space:
mode:
Diffstat (limited to 'base/event_trace_consumer_win.h')
-rw-r--r--base/event_trace_consumer_win.h143
1 files changed, 143 insertions, 0 deletions
diff --git a/base/event_trace_consumer_win.h b/base/event_trace_consumer_win.h
new file mode 100644
index 0000000..03db96f
--- /dev/null
+++ b/base/event_trace_consumer_win.h
@@ -0,0 +1,143 @@
+// Copyright (c) 2009 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_EVENT_TRACE_CONSUMER_WIN_H_
+#define BASE_EVENT_TRACE_CONSUMER_WIN_H_
+
+#include <windows.h>
+#include <wmistr.h>
+#include <evntrace.h>
+#include <vector>
+#include "base/basictypes.h"
+
+// This class is a base class that makes it easier to consume events
+// from realtime or file sessions. Concrete consumers need to sublass
+// 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() {
+ }
+
+ ~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() {
+ ULONG err = ::ProcessTrace(&trace_handles_[0],
+ trace_handles_.size(),
+ NULL,
+ NULL);
+ 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;
+}
+
+#endif // BASE_EVENT_TRACE_CONSUMER_WIN_H_