xref: /aosp_15_r20/external/cronet/base/win/event_trace_consumer.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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