• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // Implementation of a Windows event trace controller class.
6 #include "base/win/event_trace_controller.h"
7 #include "base/logging.h"
8 
9 namespace base {
10 namespace win {
11 
EtwTraceProperties()12 EtwTraceProperties::EtwTraceProperties() {
13   memset(buffer_, 0, sizeof(buffer_));
14   EVENT_TRACE_PROPERTIES* prop = get();
15 
16   prop->Wnode.BufferSize = sizeof(buffer_);
17   prop->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
18   prop->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
19   prop->LogFileNameOffset = sizeof(EVENT_TRACE_PROPERTIES) +
20                             sizeof(wchar_t) * kMaxStringLen;
21 }
22 
SetLoggerName(const wchar_t * logger_name)23 HRESULT EtwTraceProperties::SetLoggerName(const wchar_t* logger_name) {
24   size_t len = wcslen(logger_name) + 1;
25   if (kMaxStringLen < len)
26     return E_INVALIDARG;
27 
28   memcpy(buffer_ + get()->LoggerNameOffset,
29          logger_name,
30          sizeof(wchar_t) * len);
31   return S_OK;
32 }
33 
SetLoggerFileName(const wchar_t * logger_file_name)34 HRESULT EtwTraceProperties::SetLoggerFileName(const wchar_t* logger_file_name) {
35   size_t len = wcslen(logger_file_name) + 1;
36   if (kMaxStringLen < len)
37     return E_INVALIDARG;
38 
39   memcpy(buffer_ + get()->LogFileNameOffset,
40          logger_file_name,
41          sizeof(wchar_t) * len);
42   return S_OK;
43 }
44 
EtwTraceController()45 EtwTraceController::EtwTraceController() : session_(NULL) {
46 }
47 
~EtwTraceController()48 EtwTraceController::~EtwTraceController() {
49   Stop(NULL);
50 }
51 
Start(const wchar_t * session_name,EtwTraceProperties * prop)52 HRESULT EtwTraceController::Start(const wchar_t* session_name,
53     EtwTraceProperties* prop) {
54   DCHECK(NULL == session_ && session_name_.empty());
55   EtwTraceProperties ignore;
56   if (prop == NULL)
57     prop = &ignore;
58 
59   HRESULT hr = Start(session_name, prop, &session_);
60   if (SUCCEEDED(hr))
61     session_name_ = session_name;
62 
63   return hr;
64 }
65 
StartFileSession(const wchar_t * session_name,const wchar_t * logfile_path,bool realtime)66 HRESULT EtwTraceController::StartFileSession(const wchar_t* session_name,
67       const wchar_t* logfile_path, bool realtime) {
68   DCHECK(NULL == session_ && session_name_.empty());
69 
70   EtwTraceProperties prop;
71   prop.SetLoggerFileName(logfile_path);
72   EVENT_TRACE_PROPERTIES& p = *prop.get();
73   p.Wnode.ClientContext = 1;  // QPC timer accuracy.
74   p.LogFileMode = EVENT_TRACE_FILE_MODE_SEQUENTIAL;  // Sequential log.
75   if (realtime)
76     p.LogFileMode |= EVENT_TRACE_REAL_TIME_MODE;
77 
78   p.MaximumFileSize = 100;  // 100M file size.
79   p.FlushTimer = 30;  // 30 seconds flush lag.
80   return Start(session_name, &prop);
81 }
82 
StartRealtimeSession(const wchar_t * session_name,size_t buffer_size)83 HRESULT EtwTraceController::StartRealtimeSession(const wchar_t* session_name,
84     size_t buffer_size) {
85   DCHECK(NULL == session_ && session_name_.empty());
86   EtwTraceProperties prop;
87   EVENT_TRACE_PROPERTIES& p = *prop.get();
88   p.LogFileMode = EVENT_TRACE_REAL_TIME_MODE | EVENT_TRACE_USE_PAGED_MEMORY;
89   p.FlushTimer = 1;  // flush every second.
90   p.BufferSize = 16;  // 16 K buffers.
91   p.LogFileNameOffset = 0;
92   return Start(session_name, &prop);
93 }
94 
EnableProvider(REFGUID provider,UCHAR level,ULONG flags)95 HRESULT EtwTraceController::EnableProvider(REFGUID provider, UCHAR level,
96     ULONG flags) {
97   ULONG error = ::EnableTrace(TRUE, flags, level, &provider, session_);
98   return HRESULT_FROM_WIN32(error);
99 }
100 
DisableProvider(REFGUID provider)101 HRESULT EtwTraceController::DisableProvider(REFGUID provider) {
102   ULONG error = ::EnableTrace(FALSE, 0, 0, &provider, session_);
103   return HRESULT_FROM_WIN32(error);
104 }
105 
Stop(EtwTraceProperties * properties)106 HRESULT EtwTraceController::Stop(EtwTraceProperties* properties) {
107   EtwTraceProperties ignore;
108   if (properties == NULL)
109     properties = &ignore;
110 
111   ULONG error = ::ControlTrace(session_, NULL, properties->get(),
112     EVENT_TRACE_CONTROL_STOP);
113   if (ERROR_SUCCESS != error)
114     return HRESULT_FROM_WIN32(error);
115 
116   session_ = NULL;
117   session_name_.clear();
118   return S_OK;
119 }
120 
Flush(EtwTraceProperties * properties)121 HRESULT EtwTraceController::Flush(EtwTraceProperties* properties) {
122   EtwTraceProperties ignore;
123   if (properties == NULL)
124     properties = &ignore;
125 
126   ULONG error = ::ControlTrace(session_, NULL, properties->get(),
127                                EVENT_TRACE_CONTROL_FLUSH);
128   if (ERROR_SUCCESS != error)
129     return HRESULT_FROM_WIN32(error);
130 
131   return S_OK;
132 }
133 
Start(const wchar_t * session_name,EtwTraceProperties * properties,TRACEHANDLE * session_handle)134 HRESULT EtwTraceController::Start(const wchar_t* session_name,
135     EtwTraceProperties* properties, TRACEHANDLE* session_handle) {
136   DCHECK(properties != NULL);
137   ULONG err = ::StartTrace(session_handle, session_name, properties->get());
138   return HRESULT_FROM_WIN32(err);
139 }
140 
Query(const wchar_t * session_name,EtwTraceProperties * properties)141 HRESULT EtwTraceController::Query(const wchar_t* session_name,
142     EtwTraceProperties* properties) {
143   ULONG err = ::ControlTrace(NULL, session_name, properties->get(),
144                              EVENT_TRACE_CONTROL_QUERY);
145   return HRESULT_FROM_WIN32(err);
146 };
147 
Update(const wchar_t * session_name,EtwTraceProperties * properties)148 HRESULT EtwTraceController::Update(const wchar_t* session_name,
149     EtwTraceProperties* properties) {
150   DCHECK(properties != NULL);
151   ULONG err = ::ControlTrace(NULL, session_name, properties->get(),
152                              EVENT_TRACE_CONTROL_UPDATE);
153   return HRESULT_FROM_WIN32(err);
154 }
155 
Stop(const wchar_t * session_name,EtwTraceProperties * properties)156 HRESULT EtwTraceController::Stop(const wchar_t* session_name,
157     EtwTraceProperties* properties) {
158   DCHECK(properties != NULL);
159   ULONG err = ::ControlTrace(NULL, session_name, properties->get(),
160                              EVENT_TRACE_CONTROL_STOP);
161   return HRESULT_FROM_WIN32(err);
162 }
163 
Flush(const wchar_t * session_name,EtwTraceProperties * properties)164 HRESULT EtwTraceController::Flush(const wchar_t* session_name,
165     EtwTraceProperties* properties) {
166   DCHECK(properties != NULL);
167   ULONG err = ::ControlTrace(NULL, session_name, properties->get(),
168                              EVENT_TRACE_CONTROL_FLUSH);
169   return HRESULT_FROM_WIN32(err);
170 }
171 
172 }  // namespace win
173 }  // namespace base
174