Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2009 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 controller class.
      6 // The controller takes care of creating and manipulating event trace
      7 // sessions.
      8 //
      9 // Event tracing for Windows is a system-provided service that provides
     10 // logging control and high-performance transport for generic, binary trace
     11 // events. Event trace providers register with the system by their name,
     12 // which is a GUID, and can from that point forward receive callbacks that
     13 // start or end tracing and that change their trace level and enable mask.
     14 //
     15 // A trace controller can create an event tracing session, which either
     16 // sends events to a binary file, or to a realtime consumer, or both.
     17 //
     18 // A trace consumer consumes events from zero or one realtime session,
     19 // as well as potentially from multiple binary trace files.
     20 #ifndef BASE_EVENT_TRACE_CONTROLLER_WIN_H_
     21 #define BASE_EVENT_TRACE_CONTROLLER_WIN_H_
     22 
     23 #include <windows.h>
     24 #include <wmistr.h>
     25 #include <evntrace.h>
     26 #include <string>
     27 #include "base/basictypes.h"
     28 
     29 // Utility class to make it easier to work with EVENT_TRACE_PROPERTIES.
     30 // The EVENT_TRACE_PROPERTIES structure contains information about an
     31 // event tracing session.
     32 class EtwTraceProperties {
     33  public:
     34   EtwTraceProperties() {
     35     memset(buffer_, 0, sizeof(buffer_));
     36     EVENT_TRACE_PROPERTIES* prop = get();
     37 
     38     prop->Wnode.BufferSize = sizeof(buffer_);
     39     prop->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
     40     prop->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
     41     prop->LogFileNameOffset = sizeof(EVENT_TRACE_PROPERTIES) +
     42                               sizeof(wchar_t) * kMaxStringLen;
     43   }
     44 
     45   EVENT_TRACE_PROPERTIES* get() {
     46     return &properties_;
     47   }
     48   const EVENT_TRACE_PROPERTIES* get() const {
     49     return reinterpret_cast<const EVENT_TRACE_PROPERTIES*>(&properties_);
     50   }
     51 
     52   const wchar_t* GetLoggerName() const {
     53     return reinterpret_cast<const wchar_t *>(buffer_ + get()->LoggerNameOffset);
     54   }
     55 
     56   HRESULT SetLoggerName(const wchar_t* logger_name) {
     57     size_t len = wcslen(logger_name) + 1;
     58     if (kMaxStringLen < len)
     59       return E_INVALIDARG;
     60 
     61     memcpy(buffer_ + get()->LoggerNameOffset,
     62            logger_name,
     63            sizeof(wchar_t) * len);
     64     return S_OK;
     65   }
     66 
     67   const wchar_t* GetLoggerFileName() const {
     68     return reinterpret_cast<const wchar_t*>(buffer_ + get()->LogFileNameOffset);
     69   }
     70 
     71   HRESULT SetLoggerFileName(const wchar_t* logger_file_name) {
     72     size_t len = wcslen(logger_file_name) + 1;
     73     if (kMaxStringLen < len)
     74       return E_INVALIDARG;
     75 
     76     memcpy(buffer_ + get()->LogFileNameOffset,
     77            logger_file_name,
     78            sizeof(wchar_t) * len);
     79     return S_OK;
     80   }
     81 
     82   // Max string len for name and session name is 1024 per documentation.
     83   static const size_t kMaxStringLen = 1024;
     84   // Properties buffer allocates space for header and for
     85   // max length for name and session name.
     86   static const size_t kBufSize = sizeof(EVENT_TRACE_PROPERTIES)
     87       + 2 * sizeof(wchar_t) * (kMaxStringLen);
     88 
     89  private:
     90   // The EVENT_TRACE_PROPERTIES structure needs to be overlaid on a
     91   // larger buffer to allow storing the logger name and logger file
     92   // name contiguously with the structure.
     93   union {
     94    public:
     95     // Our properties header.
     96     EVENT_TRACE_PROPERTIES properties_;
     97     // The actual size of the buffer is forced by this member.
     98     char buffer_[kBufSize];
     99   };
    100 
    101   DISALLOW_COPY_AND_ASSIGN(EtwTraceProperties);
    102 };
    103 
    104 // This class implements an ETW controller, which knows how to start and
    105 // stop event tracing sessions, as well as controlling ETW provider
    106 // log levels and enable bit masks under the session.
    107 class EtwTraceController {
    108  public:
    109   EtwTraceController();
    110   ~EtwTraceController();
    111 
    112   // Start a session with given name and properties.
    113   HRESULT Start(const wchar_t* session_name, EtwTraceProperties* prop);
    114 
    115   // Starts a session tracing to a file with some default properties.
    116   HRESULT StartFileSession(const wchar_t* session_name,
    117                            const wchar_t* logfile_path,
    118                            bool realtime = false);
    119 
    120   // Starts a realtime session with some default properties.
    121   HRESULT StartRealtimeSession(const wchar_t* session_name,
    122                                size_t buffer_size);
    123 
    124   // Enables "provider" at "level" for this session.
    125   // This will cause all providers registered with the GUID
    126   // "provider" to start tracing at the new level, systemwide.
    127   HRESULT EnableProvider(const GUID& provider, UCHAR level,
    128                          ULONG flags = 0xFFFFFFFF);
    129   // Disables "provider".
    130   HRESULT DisableProvider(const GUID& provider);
    131 
    132   // Stops our session and retrieve the new properties of the session,
    133   // properties may be NULL.
    134   HRESULT Stop(EtwTraceProperties* properties);
    135 
    136   // Flushes our session and retrieve the current properties,
    137   // properties may be NULL.
    138   HRESULT Flush(EtwTraceProperties* properties);
    139 
    140   // Static utility functions for controlling
    141   // sessions we don't necessarily own.
    142   static HRESULT Start(const wchar_t* session_name,
    143                        EtwTraceProperties* properties,
    144                        TRACEHANDLE* session_handle);
    145 
    146   static HRESULT Query(const wchar_t* session_name,
    147                        EtwTraceProperties* properties);
    148 
    149   static HRESULT Update(const wchar_t* session_name,
    150                         EtwTraceProperties* properties);
    151 
    152   static HRESULT Stop(const wchar_t* session_name,
    153                       EtwTraceProperties* properties);
    154   static HRESULT Flush(const wchar_t* session_name,
    155                        EtwTraceProperties* properties);
    156 
    157   // Accessors.
    158   TRACEHANDLE session() const { return session_; }
    159   const wchar_t* session_name() const { return session_name_.c_str(); }
    160 
    161  private:
    162   std::wstring session_name_;
    163   TRACEHANDLE session_;
    164 
    165   DISALLOW_COPY_AND_ASSIGN(EtwTraceController);
    166 };
    167 
    168 #endif  // BASE_EVENT_TRACE_CONTROLLER_WIN_H_
    169