1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker //
5*6777b538SAndroid Build Coastguard Worker // Declaration of a Windows event trace consumer base class.
6*6777b538SAndroid Build Coastguard Worker #ifndef BASE_WIN_EVENT_TRACE_CONSUMER_H_
7*6777b538SAndroid Build Coastguard Worker #define BASE_WIN_EVENT_TRACE_CONSUMER_H_
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include <windows.h>
10*6777b538SAndroid Build Coastguard Worker
11*6777b538SAndroid Build Coastguard Worker #include <evntcons.h>
12*6777b538SAndroid Build Coastguard Worker #include <evntrace.h>
13*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
14*6777b538SAndroid Build Coastguard Worker #include <wmistr.h>
15*6777b538SAndroid Build Coastguard Worker
16*6777b538SAndroid Build Coastguard Worker #include <vector>
17*6777b538SAndroid Build Coastguard Worker
18*6777b538SAndroid Build Coastguard Worker #include "base/threading/scoped_blocking_call.h"
19*6777b538SAndroid Build Coastguard Worker
20*6777b538SAndroid Build Coastguard Worker namespace base {
21*6777b538SAndroid Build Coastguard Worker namespace win {
22*6777b538SAndroid Build Coastguard Worker
23*6777b538SAndroid Build Coastguard Worker // This class is a base class that makes it easier to consume events
24*6777b538SAndroid Build Coastguard Worker // from realtime or file sessions. Concrete consumers need to subclass a
25*6777b538SAndroid Build Coastguard Worker // specialization of this class and override the ProcessEvent, the
26*6777b538SAndroid Build Coastguard Worker // ProcessEventRecord and/or the ProcessBuffer methods to implement the
27*6777b538SAndroid Build Coastguard Worker // event consumption logic.
28*6777b538SAndroid Build Coastguard Worker // Usage might look like:
29*6777b538SAndroid Build Coastguard Worker // class MyConsumer: public EtwTraceConsumerBase<MyConsumer, 1> {
30*6777b538SAndroid Build Coastguard Worker // protected:
31*6777b538SAndroid Build Coastguard Worker // static VOID WINAPI ProcessEvent(PEVENT_TRACE event);
32*6777b538SAndroid Build Coastguard Worker // };
33*6777b538SAndroid Build Coastguard Worker //
34*6777b538SAndroid Build Coastguard Worker // MyConsumer consumer;
35*6777b538SAndroid Build Coastguard Worker // consumer.OpenFileSession(file_path);
36*6777b538SAndroid Build Coastguard Worker // consumer.Consume();
37*6777b538SAndroid Build Coastguard Worker template <class ImplClass>
38*6777b538SAndroid Build Coastguard Worker class EtwTraceConsumerBase {
39*6777b538SAndroid Build Coastguard Worker public:
40*6777b538SAndroid Build Coastguard Worker // If true, receive events in the new EVENT_RECORD format. To receive
41*6777b538SAndroid Build Coastguard Worker // events in the new format, ProcessEventRecord() must be overridden.
42*6777b538SAndroid Build Coastguard Worker // See PROCESS_TRACE_MODE_EVENT_RECORD from
43*6777b538SAndroid Build Coastguard Worker // https://learn.microsoft.com/en-us/windows/win32/api/evntrace/ns-evntrace-event_trace_logfilea
44*6777b538SAndroid Build Coastguard Worker static constexpr bool kEnableRecordMode = false;
45*6777b538SAndroid Build Coastguard Worker // If true, TimeStamps in EVENT_HEADER and EVENT_TRACE_HEADER are not
46*6777b538SAndroid Build Coastguard Worker // converted to system time. See PROCESS_TRACE_MODE_RAW_TIMESTAMP from
47*6777b538SAndroid Build Coastguard Worker // https://learn.microsoft.com/en-us/windows/win32/api/evntrace/ns-evntrace-event_trace_logfilea
48*6777b538SAndroid Build Coastguard Worker static constexpr bool kRawTimestamp = false;
49*6777b538SAndroid Build Coastguard Worker
50*6777b538SAndroid Build Coastguard Worker // Constructs a closed consumer.
51*6777b538SAndroid Build Coastguard Worker EtwTraceConsumerBase() = default;
52*6777b538SAndroid Build Coastguard Worker
53*6777b538SAndroid Build Coastguard Worker EtwTraceConsumerBase(const EtwTraceConsumerBase&) = delete;
54*6777b538SAndroid Build Coastguard Worker EtwTraceConsumerBase& operator=(const EtwTraceConsumerBase&) = delete;
55*6777b538SAndroid Build Coastguard Worker
~EtwTraceConsumerBase()56*6777b538SAndroid Build Coastguard Worker ~EtwTraceConsumerBase() { Close(); }
57*6777b538SAndroid Build Coastguard Worker
58*6777b538SAndroid Build Coastguard Worker // Opens the named realtime session, which must be existent.
59*6777b538SAndroid Build Coastguard Worker // Note: You can use OpenRealtimeSession or OpenFileSession
60*6777b538SAndroid Build Coastguard Worker // to open as many as MAXIMUM_WAIT_OBJECTS (63) sessions at
61*6777b538SAndroid Build Coastguard Worker // any one time, though only one of them may be a realtime
62*6777b538SAndroid Build Coastguard Worker // session.
63*6777b538SAndroid Build Coastguard Worker HRESULT OpenRealtimeSession(const wchar_t* session_name);
64*6777b538SAndroid Build Coastguard Worker
65*6777b538SAndroid Build Coastguard Worker // Opens the event trace log in "file_name", which must be a full or
66*6777b538SAndroid Build Coastguard Worker // relative path to an existing event trace log file.
67*6777b538SAndroid Build Coastguard Worker // Note: You can use OpenRealtimeSession or OpenFileSession
68*6777b538SAndroid Build Coastguard Worker // to open as many as kNumSessions at any one time.
69*6777b538SAndroid Build Coastguard Worker HRESULT OpenFileSession(const wchar_t* file_name);
70*6777b538SAndroid Build Coastguard Worker
71*6777b538SAndroid Build Coastguard Worker // Consume all open sessions from beginning to end.
72*6777b538SAndroid Build Coastguard Worker HRESULT Consume();
73*6777b538SAndroid Build Coastguard Worker
74*6777b538SAndroid Build Coastguard Worker // Close all open sessions.
75*6777b538SAndroid Build Coastguard Worker HRESULT Close();
76*6777b538SAndroid Build Coastguard Worker
77*6777b538SAndroid Build Coastguard Worker protected:
78*6777b538SAndroid Build Coastguard Worker // Override in subclasses to handle events.
ProcessEvent(EVENT_TRACE * event)79*6777b538SAndroid Build Coastguard Worker static void ProcessEvent(EVENT_TRACE* event) {}
80*6777b538SAndroid Build Coastguard Worker // Override in subclasses to handle events.
ProcessEventRecord(EVENT_RECORD * event_record)81*6777b538SAndroid Build Coastguard Worker static void ProcessEventRecord(EVENT_RECORD* event_record) {}
82*6777b538SAndroid Build Coastguard Worker // Override in subclasses to handle buffers.
ProcessBuffer(EVENT_TRACE_LOGFILE * buffer)83*6777b538SAndroid Build Coastguard Worker static bool ProcessBuffer(EVENT_TRACE_LOGFILE* buffer) {
84*6777b538SAndroid Build Coastguard Worker return true; // keep going
85*6777b538SAndroid Build Coastguard Worker }
86*6777b538SAndroid Build Coastguard Worker
87*6777b538SAndroid Build Coastguard Worker HRESULT OpenSessionImpl(EVENT_TRACE_LOGFILE& logfile);
88*6777b538SAndroid Build Coastguard Worker
89*6777b538SAndroid Build Coastguard Worker protected:
90*6777b538SAndroid Build Coastguard Worker // Currently open sessions.
91*6777b538SAndroid Build Coastguard Worker std::vector<TRACEHANDLE> trace_handles_;
92*6777b538SAndroid Build Coastguard Worker
93*6777b538SAndroid Build Coastguard Worker private:
94*6777b538SAndroid Build Coastguard Worker // These delegate to ImplClass callbacks with saner signatures.
ProcessEventCallback(EVENT_TRACE * event)95*6777b538SAndroid Build Coastguard Worker static void WINAPI ProcessEventCallback(EVENT_TRACE* event) {
96*6777b538SAndroid Build Coastguard Worker ImplClass::ProcessEvent(event);
97*6777b538SAndroid Build Coastguard Worker }
ProcessEventRecordCallback(EVENT_RECORD * event_record)98*6777b538SAndroid Build Coastguard Worker static void WINAPI ProcessEventRecordCallback(EVENT_RECORD* event_record) {
99*6777b538SAndroid Build Coastguard Worker ImplClass::ProcessEventRecord(event_record);
100*6777b538SAndroid Build Coastguard Worker }
ProcessBufferCallback(PEVENT_TRACE_LOGFILE buffer)101*6777b538SAndroid Build Coastguard Worker static ULONG WINAPI ProcessBufferCallback(PEVENT_TRACE_LOGFILE buffer) {
102*6777b538SAndroid Build Coastguard Worker return ImplClass::ProcessBuffer(buffer);
103*6777b538SAndroid Build Coastguard Worker }
104*6777b538SAndroid Build Coastguard Worker };
105*6777b538SAndroid Build Coastguard Worker
106*6777b538SAndroid Build Coastguard Worker template <class ImplClass>
OpenRealtimeSession(const wchar_t * session_name)107*6777b538SAndroid Build Coastguard Worker inline HRESULT EtwTraceConsumerBase<ImplClass>::OpenRealtimeSession(
108*6777b538SAndroid Build Coastguard Worker const wchar_t* session_name) {
109*6777b538SAndroid Build Coastguard Worker EVENT_TRACE_LOGFILE logfile = {
110*6777b538SAndroid Build Coastguard Worker .LoggerName = const_cast<wchar_t*>(session_name),
111*6777b538SAndroid Build Coastguard Worker .ProcessTraceMode = PROCESS_TRACE_MODE_REAL_TIME,
112*6777b538SAndroid Build Coastguard Worker };
113*6777b538SAndroid Build Coastguard Worker return OpenSessionImpl(logfile);
114*6777b538SAndroid Build Coastguard Worker }
115*6777b538SAndroid Build Coastguard Worker
116*6777b538SAndroid Build Coastguard Worker template <class ImplClass>
OpenFileSession(const wchar_t * file_name)117*6777b538SAndroid Build Coastguard Worker inline HRESULT EtwTraceConsumerBase<ImplClass>::OpenFileSession(
118*6777b538SAndroid Build Coastguard Worker const wchar_t* file_name) {
119*6777b538SAndroid Build Coastguard Worker EVENT_TRACE_LOGFILE logfile = {.LogFileName =
120*6777b538SAndroid Build Coastguard Worker const_cast<wchar_t*>(file_name)};
121*6777b538SAndroid Build Coastguard Worker return OpenSessionImpl(logfile);
122*6777b538SAndroid Build Coastguard Worker }
123*6777b538SAndroid Build Coastguard Worker
124*6777b538SAndroid Build Coastguard Worker template <class ImplClass>
OpenSessionImpl(EVENT_TRACE_LOGFILE & logfile)125*6777b538SAndroid Build Coastguard Worker HRESULT EtwTraceConsumerBase<ImplClass>::OpenSessionImpl(
126*6777b538SAndroid Build Coastguard Worker EVENT_TRACE_LOGFILE& logfile) {
127*6777b538SAndroid Build Coastguard Worker if (ImplClass::kEnableRecordMode) {
128*6777b538SAndroid Build Coastguard Worker logfile.ProcessTraceMode |= PROCESS_TRACE_MODE_EVENT_RECORD;
129*6777b538SAndroid Build Coastguard Worker logfile.EventRecordCallback = &ProcessEventRecordCallback;
130*6777b538SAndroid Build Coastguard Worker } else {
131*6777b538SAndroid Build Coastguard Worker logfile.EventCallback = &ProcessEventCallback;
132*6777b538SAndroid Build Coastguard Worker }
133*6777b538SAndroid Build Coastguard Worker if (ImplClass::kRawTimestamp) {
134*6777b538SAndroid Build Coastguard Worker logfile.ProcessTraceMode |= PROCESS_TRACE_MODE_RAW_TIMESTAMP;
135*6777b538SAndroid Build Coastguard Worker }
136*6777b538SAndroid Build Coastguard Worker logfile.BufferCallback = &ProcessBufferCallback;
137*6777b538SAndroid Build Coastguard Worker logfile.Context = this;
138*6777b538SAndroid Build Coastguard Worker TRACEHANDLE trace_handle = ::OpenTrace(&logfile);
139*6777b538SAndroid Build Coastguard Worker if (reinterpret_cast<TRACEHANDLE>(INVALID_HANDLE_VALUE) == trace_handle)
140*6777b538SAndroid Build Coastguard Worker return HRESULT_FROM_WIN32(::GetLastError());
141*6777b538SAndroid Build Coastguard Worker
142*6777b538SAndroid Build Coastguard Worker trace_handles_.push_back(trace_handle);
143*6777b538SAndroid Build Coastguard Worker return S_OK;
144*6777b538SAndroid Build Coastguard Worker }
145*6777b538SAndroid Build Coastguard Worker
146*6777b538SAndroid Build Coastguard Worker template <class ImplClass>
Consume()147*6777b538SAndroid Build Coastguard Worker inline HRESULT EtwTraceConsumerBase<ImplClass>::Consume() {
148*6777b538SAndroid Build Coastguard Worker base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
149*6777b538SAndroid Build Coastguard Worker base::BlockingType::MAY_BLOCK);
150*6777b538SAndroid Build Coastguard Worker ULONG err = ::ProcessTrace(&trace_handles_[0],
151*6777b538SAndroid Build Coastguard Worker static_cast<ULONG>(trace_handles_.size()), nullptr,
152*6777b538SAndroid Build Coastguard Worker nullptr);
153*6777b538SAndroid Build Coastguard Worker return HRESULT_FROM_WIN32(err);
154*6777b538SAndroid Build Coastguard Worker }
155*6777b538SAndroid Build Coastguard Worker
156*6777b538SAndroid Build Coastguard Worker template <class ImplClass>
Close()157*6777b538SAndroid Build Coastguard Worker inline HRESULT EtwTraceConsumerBase<ImplClass>::Close() {
158*6777b538SAndroid Build Coastguard Worker HRESULT hr = S_OK;
159*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < trace_handles_.size(); ++i) {
160*6777b538SAndroid Build Coastguard Worker if (NULL != trace_handles_[i]) {
161*6777b538SAndroid Build Coastguard Worker ULONG ret = ::CloseTrace(trace_handles_[i]);
162*6777b538SAndroid Build Coastguard Worker trace_handles_[i] = NULL;
163*6777b538SAndroid Build Coastguard Worker
164*6777b538SAndroid Build Coastguard Worker if (FAILED(HRESULT_FROM_WIN32(ret)))
165*6777b538SAndroid Build Coastguard Worker hr = HRESULT_FROM_WIN32(ret);
166*6777b538SAndroid Build Coastguard Worker }
167*6777b538SAndroid Build Coastguard Worker }
168*6777b538SAndroid Build Coastguard Worker trace_handles_.clear();
169*6777b538SAndroid Build Coastguard Worker
170*6777b538SAndroid Build Coastguard Worker return hr;
171*6777b538SAndroid Build Coastguard Worker }
172*6777b538SAndroid Build Coastguard Worker
173*6777b538SAndroid Build Coastguard Worker } // namespace win
174*6777b538SAndroid Build Coastguard Worker } // namespace base
175*6777b538SAndroid Build Coastguard Worker
176*6777b538SAndroid Build Coastguard Worker #endif // BASE_WIN_EVENT_TRACE_CONSUMER_H_
177