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