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