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

base / win / event_trace_controller.h [blame]

// 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 controller class.
// The controller takes care of creating and manipulating event trace
// sessions.
//
// Event tracing for Windows is a system-provided service that provides
// logging control and high-performance transport for generic, binary trace
// events. Event trace providers register with the system by their name,
// which is a GUID, and can from that point forward receive callbacks that
// start or end tracing and that change their trace level and enable mask.
//
// A trace controller can create an event tracing session, which either
// sends events to a binary file, or to a realtime consumer, or both.
//
// A trace consumer consumes events from zero or one realtime session,
// as well as potentially from multiple binary trace files.
#ifndef BASE_WIN_EVENT_TRACE_CONTROLLER_H_
#define BASE_WIN_EVENT_TRACE_CONTROLLER_H_

#include <windows.h>

#include <evntrace.h>
#include <stddef.h>
#include <wmistr.h>

#include <string>

#include "base/base_export.h"

namespace base {
namespace win {

// Utility class to make it easier to work with EVENT_TRACE_PROPERTIES.
// The EVENT_TRACE_PROPERTIES structure contains information about an
// event tracing session.
class BASE_EXPORT EtwTraceProperties {
 public:
  EtwTraceProperties();

  EtwTraceProperties(const EtwTraceProperties&) = delete;
  EtwTraceProperties& operator=(const EtwTraceProperties&) = delete;

  EVENT_TRACE_PROPERTIES* get() { return &properties_; }

  const EVENT_TRACE_PROPERTIES* get() const {
    return reinterpret_cast<const EVENT_TRACE_PROPERTIES*>(&properties_);
  }

  const wchar_t* GetLoggerName() const {
    return reinterpret_cast<const wchar_t*>(buffer_ + get()->LoggerNameOffset);
  }

  // Copies logger_name to the properties structure.
  HRESULT SetLoggerName(const wchar_t* logger_name);
  const wchar_t* GetLoggerFileName() const {
    return reinterpret_cast<const wchar_t*>(buffer_ + get()->LogFileNameOffset);
  }

  // Copies logger_file_name to the properties structure.
  HRESULT SetLoggerFileName(const wchar_t* logger_file_name);

  // Max string len for name and session name is 1024 per documentation.
  static const size_t kMaxStringLen = 1024;
  // Properties buffer allocates space for header and for
  // max length for name and session name.
  static const size_t kBufSize =
      sizeof(EVENT_TRACE_PROPERTIES) + 2 * sizeof(wchar_t) * (kMaxStringLen);

 private:
  // The EVENT_TRACE_PROPERTIES structure needs to be overlaid on a
  // larger buffer to allow storing the logger name and logger file
  // name contiguously with the structure.
  union {
    // Our properties header.
    EVENT_TRACE_PROPERTIES properties_;
    // The actual size of the buffer is forced by this member.
    char buffer_[kBufSize];
  };
};

// This class implements an ETW controller, which knows how to start and
// stop event tracing sessions, as well as controlling ETW provider
// log levels and enable bit masks under the session.
class BASE_EXPORT EtwTraceController {
 public:
  EtwTraceController();

  EtwTraceController(const EtwTraceController&) = delete;
  EtwTraceController& operator=(const EtwTraceController&) = delete;

  ~EtwTraceController();

  // Start a session with given name and properties.
  HRESULT Start(const wchar_t* session_name, EtwTraceProperties* prop);

  // Starts a session tracing to a file with some default properties.
  HRESULT StartFileSession(const wchar_t* session_name,
                           const wchar_t* logfile_path,
                           bool realtime = false);

  // Starts a realtime session with some default properties.  |buffer_size| is
  // in KB.  A default value for |buffer_size| is used if 0 is passed in.
  HRESULT StartRealtimeSession(const wchar_t* session_name, size_t buffer_size);

  // Enables "provider" at "level" for this session.
  // This will cause all providers registered with the GUID
  // "provider" to start tracing at the new level, systemwide.
  HRESULT EnableProvider(const GUID& provider,
                         UCHAR level,
                         ULONG flags = 0xFFFFFFFF);
  // Disables "provider".
  HRESULT DisableProvider(const GUID& provider);

  // Stops our session and retrieve the new properties of the session,
  // properties may be NULL.
  HRESULT Stop(EtwTraceProperties* properties);

  // Flushes our session and retrieve the current properties,
  // properties may be NULL.
  HRESULT Flush(EtwTraceProperties* properties);

  // Static utility functions for controlling
  // sessions we don't necessarily own.
  static HRESULT Start(const wchar_t* session_name,
                       EtwTraceProperties* properties,
                       TRACEHANDLE* session_handle);

  static HRESULT Query(const wchar_t* session_name,
                       EtwTraceProperties* properties);

  static HRESULT Update(const wchar_t* session_name,
                        EtwTraceProperties* properties);

  static HRESULT Stop(const wchar_t* session_name,
                      EtwTraceProperties* properties);
  static HRESULT Flush(const wchar_t* session_name,
                       EtwTraceProperties* properties);

  // Accessors.
  TRACEHANDLE session() const { return session_; }
  const wchar_t* session_name() const { return session_name_.c_str(); }

 private:
  std::wstring session_name_;
  TRACEHANDLE session_ = NULL;
};

}  // namespace win
}  // namespace base

#endif  // BASE_WIN_EVENT_TRACE_CONTROLLER_H_