michael@0: // Copyright (c) 2011 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: // michael@0: // Declaration of a Windows event trace provider class, to allow using michael@0: // Windows Event Tracing for logging transport and control. michael@0: #ifndef BASE_WIN_EVENT_TRACE_PROVIDER_H_ michael@0: #define BASE_WIN_EVENT_TRACE_PROVIDER_H_ michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: #include "base/base_export.h" michael@0: #include "base/basictypes.h" michael@0: michael@0: namespace base { michael@0: namespace win { michael@0: michael@0: typedef GUID EtwEventClass; michael@0: typedef UCHAR EtwEventType; michael@0: typedef UCHAR EtwEventLevel; michael@0: typedef USHORT EtwEventVersion; michael@0: typedef ULONG EtwEventFlags; michael@0: michael@0: // Base class is a POD for correctness. michael@0: template struct EtwMofEventBase { michael@0: EVENT_TRACE_HEADER header; michael@0: MOF_FIELD fields[N]; michael@0: }; michael@0: michael@0: // Utility class to auto-initialize event trace header structures. michael@0: template class EtwMofEvent: public EtwMofEventBase { michael@0: public: michael@0: typedef EtwMofEventBase Super; michael@0: michael@0: // Clang and the C++ standard don't allow unqualified lookup into dependent michael@0: // bases, hence these using decls to explicitly pull the names out. michael@0: using EtwMofEventBase::header; michael@0: using EtwMofEventBase::fields; michael@0: michael@0: EtwMofEvent() { michael@0: memset(static_cast(this), 0, sizeof(Super)); michael@0: } michael@0: michael@0: EtwMofEvent(const EtwEventClass& event_class, EtwEventType type, michael@0: EtwEventLevel level) { michael@0: memset(static_cast(this), 0, sizeof(Super)); michael@0: header.Size = sizeof(Super); michael@0: header.Guid = event_class; michael@0: header.Class.Type = type; michael@0: header.Class.Level = level; michael@0: header.Flags = WNODE_FLAG_TRACED_GUID | WNODE_FLAG_USE_MOF_PTR; michael@0: } michael@0: michael@0: EtwMofEvent(const EtwEventClass& event_class, EtwEventType type, michael@0: EtwEventVersion version, EtwEventLevel level) { michael@0: memset(static_cast(this), 0, sizeof(Super)); michael@0: header.Size = sizeof(Super); michael@0: header.Guid = event_class; michael@0: header.Class.Type = type; michael@0: header.Class.Version = version; michael@0: header.Class.Level = level; michael@0: header.Flags = WNODE_FLAG_TRACED_GUID | WNODE_FLAG_USE_MOF_PTR; michael@0: } michael@0: michael@0: void SetField(int field, size_t size, const void *data) { michael@0: // DCHECK(field < N); michael@0: if ((field < N) && (size <= kuint32max)) { michael@0: fields[field].DataPtr = reinterpret_cast(data); michael@0: fields[field].Length = static_cast(size); michael@0: } michael@0: } michael@0: michael@0: EVENT_TRACE_HEADER* get() { return& header; } michael@0: michael@0: private: michael@0: DISALLOW_COPY_AND_ASSIGN(EtwMofEvent); michael@0: }; michael@0: michael@0: // Trace provider with Event Tracing for Windows. The trace provider michael@0: // registers with ETW by its name which is a GUID. ETW calls back to michael@0: // the object whenever the trace level or enable flags for this provider michael@0: // name changes. michael@0: // Users of this class can test whether logging is currently enabled at michael@0: // a particular trace level, and whether particular enable flags are set, michael@0: // before other resources are consumed to generate and issue the log michael@0: // messages themselves. michael@0: class BASE_EXPORT EtwTraceProvider { michael@0: public: michael@0: // Creates an event trace provider identified by provider_name, which michael@0: // will be the name registered with Event Tracing for Windows (ETW). michael@0: explicit EtwTraceProvider(const GUID& provider_name); michael@0: michael@0: // Creates an unnamed event trace provider, the provider must be given michael@0: // a name before registration. michael@0: EtwTraceProvider(); michael@0: virtual ~EtwTraceProvider(); michael@0: michael@0: // Registers the trace provider with Event Tracing for Windows. michael@0: // Note: from this point forward ETW may call the provider's control michael@0: // callback. If the provider's name is enabled in some trace session michael@0: // already, the callback may occur recursively from this call, so michael@0: // call this only when you're ready to handle callbacks. michael@0: ULONG Register(); michael@0: // Unregisters the trace provider with ETW. michael@0: ULONG Unregister(); michael@0: michael@0: // Accessors. michael@0: void set_provider_name(const GUID& provider_name) { michael@0: provider_name_ = provider_name; michael@0: } michael@0: const GUID& provider_name() const { return provider_name_; } michael@0: TRACEHANDLE registration_handle() const { return registration_handle_; } michael@0: TRACEHANDLE session_handle() const { return session_handle_; } michael@0: EtwEventFlags enable_flags() const { return enable_flags_; } michael@0: EtwEventLevel enable_level() const { return enable_level_; } michael@0: michael@0: // Returns true iff logging should be performed for "level" and "flags". michael@0: // Note: flags is treated as a bitmask, and should normally have a single michael@0: // bit set, to test whether to log for a particular sub "facility". michael@0: bool ShouldLog(EtwEventLevel level, EtwEventFlags flags) { michael@0: return NULL != session_handle_ && level >= enable_level_ && michael@0: (0 != (flags & enable_flags_)); michael@0: } michael@0: michael@0: // Simple wrappers to log Unicode and ANSI strings. michael@0: // Do nothing if !ShouldLog(level, 0xFFFFFFFF). michael@0: ULONG Log(const EtwEventClass& event_class, EtwEventType type, michael@0: EtwEventLevel level, const char *message); michael@0: ULONG Log(const EtwEventClass& event_class, EtwEventType type, michael@0: EtwEventLevel level, const wchar_t *message); michael@0: michael@0: // Log the provided event. michael@0: ULONG Log(EVENT_TRACE_HEADER* event); michael@0: michael@0: protected: michael@0: // Called after events have been enabled, override in subclasses michael@0: // to set up state or log at the start of a session. michael@0: // Note: This function may be called ETW's thread and may be racy, michael@0: // bring your own locking if needed. michael@0: virtual void OnEventsEnabled() {} michael@0: michael@0: // Called just before events are disabled, override in subclasses michael@0: // to tear down state or log at the end of a session. michael@0: // Note: This function may be called ETW's thread and may be racy, michael@0: // bring your own locking if needed. michael@0: virtual void OnEventsDisabled() {} michael@0: michael@0: // Called just after events have been disabled, override in subclasses michael@0: // to tear down state at the end of a session. At this point it's michael@0: // to late to log anything to the session. michael@0: // Note: This function may be called ETW's thread and may be racy, michael@0: // bring your own locking if needed. michael@0: virtual void PostEventsDisabled() {} michael@0: michael@0: private: michael@0: ULONG EnableEvents(PVOID buffer); michael@0: ULONG DisableEvents(); michael@0: ULONG Callback(WMIDPREQUESTCODE request, PVOID buffer); michael@0: static ULONG WINAPI ControlCallback(WMIDPREQUESTCODE request, PVOID context, michael@0: ULONG *reserved, PVOID buffer); michael@0: michael@0: GUID provider_name_; michael@0: TRACEHANDLE registration_handle_; michael@0: TRACEHANDLE session_handle_; michael@0: EtwEventFlags enable_flags_; michael@0: EtwEventLevel enable_level_; michael@0: michael@0: // We don't use this, but on XP we're obliged to pass one in to michael@0: // RegisterTraceGuids. Non-const, because that's how the API needs it. michael@0: static TRACE_GUID_REGISTRATION obligatory_guid_registration_; michael@0: michael@0: DISALLOW_COPY_AND_ASSIGN(EtwTraceProvider); michael@0: }; michael@0: michael@0: } // namespace win michael@0: } // namespace base michael@0: michael@0: #endif // BASE_WIN_EVENT_TRACE_PROVIDER_H_