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