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