event_trace_provider.h revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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
17namespace base {
18namespace win {
19
20typedef GUID EtwEventClass;
21typedef UCHAR EtwEventType;
22typedef UCHAR EtwEventLevel;
23typedef USHORT EtwEventVersion;
24typedef ULONG EtwEventFlags;
25
26// Base class is a POD for correctness.
27template <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.
33template <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.
89class 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_
181