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