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