xref: /aosp_15_r20/external/cronet/base/win/event_trace_provider.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2011 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 provider class, to allow using
6*6777b538SAndroid Build Coastguard Worker // Windows Event Tracing for logging transport and control.
7*6777b538SAndroid Build Coastguard Worker #ifndef BASE_WIN_EVENT_TRACE_PROVIDER_H_
8*6777b538SAndroid Build Coastguard Worker #define BASE_WIN_EVENT_TRACE_PROVIDER_H_
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include <windows.h>
11*6777b538SAndroid Build Coastguard Worker 
12*6777b538SAndroid Build Coastguard Worker #include <cguid.h>
13*6777b538SAndroid Build Coastguard Worker #include <evntrace.h>
14*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
15*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
16*6777b538SAndroid Build Coastguard Worker #include <wmistr.h>
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker #include <limits>
19*6777b538SAndroid Build Coastguard Worker 
20*6777b538SAndroid Build Coastguard Worker #include "base/base_export.h"
21*6777b538SAndroid Build Coastguard Worker 
22*6777b538SAndroid Build Coastguard Worker namespace base {
23*6777b538SAndroid Build Coastguard Worker namespace win {
24*6777b538SAndroid Build Coastguard Worker 
25*6777b538SAndroid Build Coastguard Worker using EtwEventClass = GUID;
26*6777b538SAndroid Build Coastguard Worker using EtwEventType = UCHAR;
27*6777b538SAndroid Build Coastguard Worker using EtwEventLevel = UCHAR;
28*6777b538SAndroid Build Coastguard Worker using EtwEventVersion = USHORT;
29*6777b538SAndroid Build Coastguard Worker using EtwEventFlags = ULONG;
30*6777b538SAndroid Build Coastguard Worker 
31*6777b538SAndroid Build Coastguard Worker // Base class is a POD for correctness.
32*6777b538SAndroid Build Coastguard Worker template <size_t N>
33*6777b538SAndroid Build Coastguard Worker struct EtwMofEventBase {
34*6777b538SAndroid Build Coastguard Worker   EVENT_TRACE_HEADER header;
35*6777b538SAndroid Build Coastguard Worker   MOF_FIELD fields[N];
36*6777b538SAndroid Build Coastguard Worker };
37*6777b538SAndroid Build Coastguard Worker 
38*6777b538SAndroid Build Coastguard Worker // Utility class to auto-initialize event trace header structures.
39*6777b538SAndroid Build Coastguard Worker template <size_t N>
40*6777b538SAndroid Build Coastguard Worker class EtwMofEvent : public EtwMofEventBase<N> {
41*6777b538SAndroid Build Coastguard Worker  public:
42*6777b538SAndroid Build Coastguard Worker   using Super = EtwMofEventBase<N>;
43*6777b538SAndroid Build Coastguard Worker 
44*6777b538SAndroid Build Coastguard Worker   // Clang and the C++ standard don't allow unqualified lookup into dependent
45*6777b538SAndroid Build Coastguard Worker   // bases, hence these using decls to explicitly pull the names out.
46*6777b538SAndroid Build Coastguard Worker   using EtwMofEventBase<N>::header;
47*6777b538SAndroid Build Coastguard Worker   using EtwMofEventBase<N>::fields;
48*6777b538SAndroid Build Coastguard Worker 
EtwMofEvent()49*6777b538SAndroid Build Coastguard Worker   EtwMofEvent() { memset(static_cast<Super*>(this), 0, sizeof(Super)); }
50*6777b538SAndroid Build Coastguard Worker 
EtwMofEvent(const EtwEventClass & event_class,EtwEventType type,EtwEventLevel level)51*6777b538SAndroid Build Coastguard Worker   EtwMofEvent(const EtwEventClass& event_class,
52*6777b538SAndroid Build Coastguard Worker               EtwEventType type,
53*6777b538SAndroid Build Coastguard Worker               EtwEventLevel level) {
54*6777b538SAndroid Build Coastguard Worker     memset(static_cast<Super*>(this), 0, sizeof(Super));
55*6777b538SAndroid Build Coastguard Worker     header.Size = sizeof(Super);
56*6777b538SAndroid Build Coastguard Worker     header.Guid = event_class;
57*6777b538SAndroid Build Coastguard Worker     header.Class.Type = type;
58*6777b538SAndroid Build Coastguard Worker     header.Class.Level = level;
59*6777b538SAndroid Build Coastguard Worker     header.Flags = WNODE_FLAG_TRACED_GUID | WNODE_FLAG_USE_MOF_PTR;
60*6777b538SAndroid Build Coastguard Worker   }
61*6777b538SAndroid Build Coastguard Worker 
EtwMofEvent(const EtwEventClass & event_class,EtwEventType type,EtwEventVersion version,EtwEventLevel level)62*6777b538SAndroid Build Coastguard Worker   EtwMofEvent(const EtwEventClass& event_class,
63*6777b538SAndroid Build Coastguard Worker               EtwEventType type,
64*6777b538SAndroid Build Coastguard Worker               EtwEventVersion version,
65*6777b538SAndroid Build Coastguard Worker               EtwEventLevel level) {
66*6777b538SAndroid Build Coastguard Worker     memset(static_cast<Super*>(this), 0, sizeof(Super));
67*6777b538SAndroid Build Coastguard Worker     header.Size = sizeof(Super);
68*6777b538SAndroid Build Coastguard Worker     header.Guid = event_class;
69*6777b538SAndroid Build Coastguard Worker     header.Class.Type = type;
70*6777b538SAndroid Build Coastguard Worker     header.Class.Version = version;
71*6777b538SAndroid Build Coastguard Worker     header.Class.Level = level;
72*6777b538SAndroid Build Coastguard Worker     header.Flags = WNODE_FLAG_TRACED_GUID | WNODE_FLAG_USE_MOF_PTR;
73*6777b538SAndroid Build Coastguard Worker   }
74*6777b538SAndroid Build Coastguard Worker 
75*6777b538SAndroid Build Coastguard Worker   EtwMofEvent(const EtwMofEvent&) = delete;
76*6777b538SAndroid Build Coastguard Worker   EtwMofEvent& operator=(const EtwMofEvent&) = delete;
77*6777b538SAndroid Build Coastguard Worker 
SetField(size_t field,size_t size,const void * data)78*6777b538SAndroid Build Coastguard Worker   void SetField(size_t field, size_t size, const void* data) {
79*6777b538SAndroid Build Coastguard Worker     // DCHECK(field < N);
80*6777b538SAndroid Build Coastguard Worker     if ((field < N) && (size <= std::numeric_limits<uint32_t>::max())) {
81*6777b538SAndroid Build Coastguard Worker       fields[field].DataPtr = reinterpret_cast<ULONG64>(data);
82*6777b538SAndroid Build Coastguard Worker       fields[field].Length = static_cast<ULONG>(size);
83*6777b538SAndroid Build Coastguard Worker     }
84*6777b538SAndroid Build Coastguard Worker   }
85*6777b538SAndroid Build Coastguard Worker 
get()86*6777b538SAndroid Build Coastguard Worker   EVENT_TRACE_HEADER* get() { return &header; }
87*6777b538SAndroid Build Coastguard Worker };
88*6777b538SAndroid Build Coastguard Worker 
89*6777b538SAndroid Build Coastguard Worker // Trace provider with Event Tracing for Windows. The trace provider
90*6777b538SAndroid Build Coastguard Worker // registers with ETW by its name which is a GUID. ETW calls back to
91*6777b538SAndroid Build Coastguard Worker // the object whenever the trace level or enable flags for this provider
92*6777b538SAndroid Build Coastguard Worker // name changes.
93*6777b538SAndroid Build Coastguard Worker // Users of this class can test whether logging is currently enabled at
94*6777b538SAndroid Build Coastguard Worker // a particular trace level, and whether particular enable flags are set,
95*6777b538SAndroid Build Coastguard Worker // before other resources are consumed to generate and issue the log
96*6777b538SAndroid Build Coastguard Worker // messages themselves.
97*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT EtwTraceProvider {
98*6777b538SAndroid Build Coastguard Worker  public:
99*6777b538SAndroid Build Coastguard Worker   // Creates an event trace provider identified by provider_name, which
100*6777b538SAndroid Build Coastguard Worker   // will be the name registered with Event Tracing for Windows (ETW).
101*6777b538SAndroid Build Coastguard Worker   explicit EtwTraceProvider(const GUID& provider_name);
102*6777b538SAndroid Build Coastguard Worker 
103*6777b538SAndroid Build Coastguard Worker   // Creates an unnamed event trace provider, the provider must be given
104*6777b538SAndroid Build Coastguard Worker   // a name before registration.
105*6777b538SAndroid Build Coastguard Worker   EtwTraceProvider();
106*6777b538SAndroid Build Coastguard Worker 
107*6777b538SAndroid Build Coastguard Worker   EtwTraceProvider(const EtwTraceProvider&) = delete;
108*6777b538SAndroid Build Coastguard Worker   EtwTraceProvider& operator=(const EtwTraceProvider&) = delete;
109*6777b538SAndroid Build Coastguard Worker 
110*6777b538SAndroid Build Coastguard Worker   virtual ~EtwTraceProvider();
111*6777b538SAndroid Build Coastguard Worker 
112*6777b538SAndroid Build Coastguard Worker   // Registers the trace provider with Event Tracing for Windows.
113*6777b538SAndroid Build Coastguard Worker   // Note: from this point forward ETW may call the provider's control
114*6777b538SAndroid Build Coastguard Worker   //    callback. If the provider's name is enabled in some trace session
115*6777b538SAndroid Build Coastguard Worker   //    already, the callback may occur recursively from this call, so
116*6777b538SAndroid Build Coastguard Worker   //    call this only when you're ready to handle callbacks.
117*6777b538SAndroid Build Coastguard Worker   ULONG Register();
118*6777b538SAndroid Build Coastguard Worker   // Unregisters the trace provider with ETW.
119*6777b538SAndroid Build Coastguard Worker   ULONG Unregister();
120*6777b538SAndroid Build Coastguard Worker 
121*6777b538SAndroid Build Coastguard Worker   // Accessors.
set_provider_name(const GUID & provider_name)122*6777b538SAndroid Build Coastguard Worker   void set_provider_name(const GUID& provider_name) {
123*6777b538SAndroid Build Coastguard Worker     provider_name_ = provider_name;
124*6777b538SAndroid Build Coastguard Worker   }
provider_name()125*6777b538SAndroid Build Coastguard Worker   const GUID& provider_name() const { return provider_name_; }
registration_handle()126*6777b538SAndroid Build Coastguard Worker   TRACEHANDLE registration_handle() const { return registration_handle_; }
session_handle()127*6777b538SAndroid Build Coastguard Worker   TRACEHANDLE session_handle() const { return session_handle_; }
enable_flags()128*6777b538SAndroid Build Coastguard Worker   EtwEventFlags enable_flags() const { return enable_flags_; }
enable_level()129*6777b538SAndroid Build Coastguard Worker   EtwEventLevel enable_level() const { return enable_level_; }
130*6777b538SAndroid Build Coastguard Worker 
131*6777b538SAndroid Build Coastguard Worker   // Returns true iff logging should be performed for "level" and "flags".
132*6777b538SAndroid Build Coastguard Worker   // Note: flags is treated as a bitmask, and should normally have a single
133*6777b538SAndroid Build Coastguard Worker   //      bit set, to test whether to log for a particular sub "facility".
ShouldLog(EtwEventLevel level,EtwEventFlags flags)134*6777b538SAndroid Build Coastguard Worker   bool ShouldLog(EtwEventLevel level, EtwEventFlags flags) {
135*6777b538SAndroid Build Coastguard Worker     return NULL != session_handle_ && level >= enable_level_ &&
136*6777b538SAndroid Build Coastguard Worker            (0 != (flags & enable_flags_));
137*6777b538SAndroid Build Coastguard Worker   }
138*6777b538SAndroid Build Coastguard Worker 
139*6777b538SAndroid Build Coastguard Worker   // Simple wrappers to log Unicode and ANSI strings.
140*6777b538SAndroid Build Coastguard Worker   // Do nothing if !ShouldLog(level, 0xFFFFFFFF).
141*6777b538SAndroid Build Coastguard Worker   ULONG Log(const EtwEventClass& event_class,
142*6777b538SAndroid Build Coastguard Worker             EtwEventType type,
143*6777b538SAndroid Build Coastguard Worker             EtwEventLevel level,
144*6777b538SAndroid Build Coastguard Worker             const char* message);
145*6777b538SAndroid Build Coastguard Worker   ULONG Log(const EtwEventClass& event_class,
146*6777b538SAndroid Build Coastguard Worker             EtwEventType type,
147*6777b538SAndroid Build Coastguard Worker             EtwEventLevel level,
148*6777b538SAndroid Build Coastguard Worker             const wchar_t* message);
149*6777b538SAndroid Build Coastguard Worker 
150*6777b538SAndroid Build Coastguard Worker   // Log the provided event.
151*6777b538SAndroid Build Coastguard Worker   ULONG Log(EVENT_TRACE_HEADER* event);
152*6777b538SAndroid Build Coastguard Worker 
153*6777b538SAndroid Build Coastguard Worker  protected:
154*6777b538SAndroid Build Coastguard Worker   // Called after events have been enabled, override in subclasses
155*6777b538SAndroid Build Coastguard Worker   // to set up state or log at the start of a session.
156*6777b538SAndroid Build Coastguard Worker   // Note: This function may be called ETW's thread and may be racy,
157*6777b538SAndroid Build Coastguard Worker   //    bring your own locking if needed.
OnEventsEnabled()158*6777b538SAndroid Build Coastguard Worker   virtual void OnEventsEnabled() {}
159*6777b538SAndroid Build Coastguard Worker 
160*6777b538SAndroid Build Coastguard Worker   // Called just before events are disabled, override in subclasses
161*6777b538SAndroid Build Coastguard Worker   // to tear down state or log at the end of a session.
162*6777b538SAndroid Build Coastguard Worker   // Note: This function may be called ETW's thread and may be racy,
163*6777b538SAndroid Build Coastguard Worker   //    bring your own locking if needed.
OnEventsDisabled()164*6777b538SAndroid Build Coastguard Worker   virtual void OnEventsDisabled() {}
165*6777b538SAndroid Build Coastguard Worker 
166*6777b538SAndroid Build Coastguard Worker   // Called just after events have been disabled, override in subclasses
167*6777b538SAndroid Build Coastguard Worker   // to tear down state at the end of a session. At this point it's
168*6777b538SAndroid Build Coastguard Worker   // to late to log anything to the session.
169*6777b538SAndroid Build Coastguard Worker   // Note: This function may be called ETW's thread and may be racy,
170*6777b538SAndroid Build Coastguard Worker   //    bring your own locking if needed.
PostEventsDisabled()171*6777b538SAndroid Build Coastguard Worker   virtual void PostEventsDisabled() {}
172*6777b538SAndroid Build Coastguard Worker 
173*6777b538SAndroid Build Coastguard Worker  private:
174*6777b538SAndroid Build Coastguard Worker   ULONG EnableEvents(PVOID buffer);
175*6777b538SAndroid Build Coastguard Worker   ULONG DisableEvents();
176*6777b538SAndroid Build Coastguard Worker   ULONG Callback(WMIDPREQUESTCODE request, PVOID buffer);
177*6777b538SAndroid Build Coastguard Worker   static ULONG WINAPI ControlCallback(WMIDPREQUESTCODE request,
178*6777b538SAndroid Build Coastguard Worker                                       PVOID context,
179*6777b538SAndroid Build Coastguard Worker                                       ULONG* reserved,
180*6777b538SAndroid Build Coastguard Worker                                       PVOID buffer);
181*6777b538SAndroid Build Coastguard Worker 
182*6777b538SAndroid Build Coastguard Worker   GUID provider_name_ = GUID_NULL;
183*6777b538SAndroid Build Coastguard Worker   TRACEHANDLE registration_handle_ = NULL;
184*6777b538SAndroid Build Coastguard Worker   TRACEHANDLE session_handle_ = NULL;
185*6777b538SAndroid Build Coastguard Worker   EtwEventFlags enable_flags_ = 0;
186*6777b538SAndroid Build Coastguard Worker   EtwEventLevel enable_level_ = 0;
187*6777b538SAndroid Build Coastguard Worker 
188*6777b538SAndroid Build Coastguard Worker   // We don't use this, but on XP we're obliged to pass one in to
189*6777b538SAndroid Build Coastguard Worker   // RegisterTraceGuids. Non-const, because that's how the API needs it.
190*6777b538SAndroid Build Coastguard Worker   static TRACE_GUID_REGISTRATION obligatory_guid_registration_;
191*6777b538SAndroid Build Coastguard Worker };
192*6777b538SAndroid Build Coastguard Worker 
193*6777b538SAndroid Build Coastguard Worker }  // namespace win
194*6777b538SAndroid Build Coastguard Worker }  // namespace base
195*6777b538SAndroid Build Coastguard Worker 
196*6777b538SAndroid Build Coastguard Worker #endif  // BASE_WIN_EVENT_TRACE_PROVIDER_H_
197