Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(21)

Side by Side Diff: base/trace_event/trace_event_etw_export_win.cc

Issue 1279353002: [ETW Export] Add polling for ETW keyword. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix nit. Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/trace_event/trace_event_etw_export_win.h ('k') | base/trace_event/trace_log.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/trace_event/trace_event_etw_export_win.h" 5 #include "base/trace_event/trace_event_etw_export_win.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/memory/singleton.h" 9 #include "base/memory/singleton.h"
10 #include "base/strings/string_tokenizer.h" 10 #include "base/strings/string_tokenizer.h"
11 #include "base/strings/utf_string_conversions.h" 11 #include "base/strings/utf_string_conversions.h"
12 #include "base/threading/platform_thread.h"
12 #include "base/trace_event/trace_event.h" 13 #include "base/trace_event/trace_event.h"
13 #include "base/trace_event/trace_event_impl.h" 14 #include "base/trace_event/trace_event_impl.h"
14 15
15 // The GetProcAddress technique is borrowed from 16 // The GetProcAddress technique is borrowed from
16 // https://github.com/google/UIforETW/tree/master/ETWProviders 17 // https://github.com/google/UIforETW/tree/master/ETWProviders
17 // 18 //
18 // EVNTAPI is used in evntprov.h which is included by chrome_events_win.h. 19 // EVNTAPI is used in evntprov.h which is included by chrome_events_win.h.
19 // We define EVNTAPI without the DECLSPEC_IMPORT specifier so that we can 20 // We define EVNTAPI without the DECLSPEC_IMPORT specifier so that we can
20 // implement these functions locally instead of using the import library, and 21 // implement these functions locally instead of using the import library, and
21 // can therefore still run on Windows XP. 22 // can therefore still run on Windows XP.
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 "toplevel", // 0x200 84 "toplevel", // 0x200
84 "v8", // 0x400 85 "v8", // 0x400
85 "disabled-by-default-cc.debug", // 0x800 86 "disabled-by-default-cc.debug", // 0x800
86 "disabled-by-default-cc.debug.picture", // 0x1000 87 "disabled-by-default-cc.debug.picture", // 0x1000
87 "disabled-by-default-toplevel.flow"}; // 0x2000 88 "disabled-by-default-toplevel.flow"}; // 0x2000
88 const char* other_events_group_name = "__OTHER_EVENTS"; // 0x2000000000000000 89 const char* other_events_group_name = "__OTHER_EVENTS"; // 0x2000000000000000
89 const char* disabled_other_events_group_name = 90 const char* disabled_other_events_group_name =
90 "__DISABLED_OTHER_EVENTS"; // 0x4000000000000000 91 "__DISABLED_OTHER_EVENTS"; // 0x4000000000000000
91 uint64 other_events_keyword_bit = 1ULL << 61; 92 uint64 other_events_keyword_bit = 1ULL << 61;
92 uint64 disabled_other_events_keyword_bit = 1ULL << 62; 93 uint64 disabled_other_events_keyword_bit = 1ULL << 62;
94
95 // This object will be created by each process. It's a background (low-priority)
96 // thread that will monitor the ETW keyword for any changes.
97 class ETWKeywordUpdateThread : public base::PlatformThread::Delegate {
98 public:
99 ETWKeywordUpdateThread() {}
100 ~ETWKeywordUpdateThread() override {}
101
102 // Implementation of PlatformThread::Delegate:
103 void ThreadMain() override {
104 base::PlatformThread::SetName("ETW Keyword Update Thread");
105 base::TimeDelta sleep_time =
106 base::TimeDelta::FromMilliseconds(kUpdateTimerDelayMs);
107 while (1) {
108 base::PlatformThread::Sleep(sleep_time);
109 base::trace_event::TraceEventETWExport::UpdateETWKeyword();
110 }
111 }
112
113 private:
114 // Time between checks for ETW keyword changes (in milliseconds).
115 unsigned int kUpdateTimerDelayMs = 1000;
116 };
117
93 } // namespace 118 } // namespace
94 119
95 // Redirector function for EventRegister. Called by macros in 120 // Redirector function for EventRegister. Called by macros in
96 // chrome_events_win.h 121 // chrome_events_win.h
97 ULONG EVNTAPI EventRegister(LPCGUID ProviderId, 122 ULONG EVNTAPI EventRegister(LPCGUID ProviderId,
98 PENABLECALLBACK EnableCallback, 123 PENABLECALLBACK EnableCallback,
99 PVOID CallbackContext, 124 PVOID CallbackContext,
100 PREGHANDLE RegHandle) { 125 PREGHANDLE RegHandle) {
101 if (EventRegisterProc) 126 if (EventRegisterProc)
102 return EventRegisterProc(ProviderId, EnableCallback, CallbackContext, 127 return EventRegisterProc(ProviderId, EnableCallback, CallbackContext,
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 EventRegisterProc = reinterpret_cast<tEventRegister>( 161 EventRegisterProc = reinterpret_cast<tEventRegister>(
137 ::GetProcAddress(AdvapiDLL, "EventRegister")); 162 ::GetProcAddress(AdvapiDLL, "EventRegister"));
138 EventWriteProc = reinterpret_cast<tEventWrite>( 163 EventWriteProc = reinterpret_cast<tEventWrite>(
139 ::GetProcAddress(AdvapiDLL, "EventWrite")); 164 ::GetProcAddress(AdvapiDLL, "EventWrite"));
140 EventUnregisterProc = reinterpret_cast<tEventUnregister>( 165 EventUnregisterProc = reinterpret_cast<tEventUnregister>(
141 ::GetProcAddress(AdvapiDLL, "EventUnregister")); 166 ::GetProcAddress(AdvapiDLL, "EventUnregister"));
142 167
143 // Register the ETW provider. If registration fails then the event logging 168 // Register the ETW provider. If registration fails then the event logging
144 // calls will fail (on XP this call will do nothing). 169 // calls will fail (on XP this call will do nothing).
145 EventRegisterChrome(); 170 EventRegisterChrome();
146
147 UpdateEnabledCategories();
148 } 171 }
149 } 172 }
150 173
151 TraceEventETWExport::~TraceEventETWExport() { 174 TraceEventETWExport::~TraceEventETWExport() {
152 EventUnregisterChrome(); 175 EventUnregisterChrome();
153 } 176 }
154 177
155 // static 178 // static
156 TraceEventETWExport* TraceEventETWExport::GetInstance() { 179 TraceEventETWExport* TraceEventETWExport::GetInstance() {
157 return Singleton<TraceEventETWExport, 180 return Singleton<TraceEventETWExport,
158 StaticMemorySingletonTraits<TraceEventETWExport>>::get(); 181 StaticMemorySingletonTraits<TraceEventETWExport>>::get();
159 } 182 }
160 183
161 // static 184 // static
162 void TraceEventETWExport::EnableETWExport() { 185 void TraceEventETWExport::EnableETWExport() {
163 if (GetInstance()) 186 auto* instance = GetInstance();
164 GetInstance()->etw_export_enabled_ = true; 187 if (instance && !instance->etw_export_enabled_) {
188 instance->etw_export_enabled_ = true;
189 // Sync the enabled categories with ETW by calling UpdateEnabledCategories()
190 // that checks the keyword. Then create a thread that will call that same
191 // function periodically, to make sure we stay in sync.
192 instance->UpdateEnabledCategories();
193 if (instance->keyword_update_thread_handle_.is_null()) {
194 instance->keyword_update_thread_.reset(new ETWKeywordUpdateThread);
195 PlatformThread::CreateWithPriority(
196 0, instance->keyword_update_thread_.get(),
197 &instance->keyword_update_thread_handle_, ThreadPriority::BACKGROUND);
198 }
199 }
165 } 200 }
166 201
167 // static 202 // static
168 void TraceEventETWExport::DisableETWExport() { 203 void TraceEventETWExport::DisableETWExport() {
169 if (GetInstance()) 204 auto* instance = GetInstance();
170 GetInstance()->etw_export_enabled_ = false; 205 if (instance && instance->etw_export_enabled_)
206 instance->etw_export_enabled_ = false;
171 } 207 }
172 208
173 // static 209 // static
174 bool TraceEventETWExport::IsETWExportEnabled() { 210 bool TraceEventETWExport::IsETWExportEnabled() {
175 return (GetInstance() && GetInstance()->etw_export_enabled_); 211 auto* instance = GetInstance();
212 return (instance && instance->etw_export_enabled_);
176 } 213 }
177 214
178 // static 215 // static
179 void TraceEventETWExport::AddEvent( 216 void TraceEventETWExport::AddEvent(
180 char phase, 217 char phase,
181 const unsigned char* category_group_enabled, 218 const unsigned char* category_group_enabled,
182 const char* name, 219 const char* name,
183 unsigned long long id, 220 unsigned long long id,
184 int num_args, 221 int num_args,
185 const char** arg_names, 222 const char** arg_names,
186 const unsigned char* arg_types, 223 const unsigned char* arg_types,
187 const unsigned long long* arg_values, 224 const unsigned long long* arg_values,
188 const scoped_refptr<ConvertableToTraceFormat>* convertable_values) { 225 const scoped_refptr<ConvertableToTraceFormat>* convertable_values) {
189 // We bail early in case exporting is disabled or no consumer is listening. 226 // We bail early in case exporting is disabled or no consumer is listening.
190 if (!GetInstance() || !GetInstance()->etw_export_enabled_ || 227 auto* instance = GetInstance();
191 !EventEnabledChromeEvent()) 228 if (!instance || !instance->etw_export_enabled_ || !EventEnabledChromeEvent())
192 return; 229 return;
193 230
194 const char* phase_string = nullptr; 231 const char* phase_string = nullptr;
195 // Space to store the phase identifier and null-terminator, when needed. 232 // Space to store the phase identifier and null-terminator, when needed.
196 char phase_buffer[2]; 233 char phase_buffer[2];
197 switch (phase) { 234 switch (phase) {
198 case TRACE_EVENT_PHASE_BEGIN: 235 case TRACE_EVENT_PHASE_BEGIN:
199 phase_string = "Begin"; 236 phase_string = "Begin";
200 break; 237 break;
201 case TRACE_EVENT_PHASE_END: 238 case TRACE_EVENT_PHASE_END:
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 324
288 // static 325 // static
289 void TraceEventETWExport::AddCustomEvent(const char* name, 326 void TraceEventETWExport::AddCustomEvent(const char* name,
290 char const* phase, 327 char const* phase,
291 const char* arg_name_1, 328 const char* arg_name_1,
292 const char* arg_value_1, 329 const char* arg_value_1,
293 const char* arg_name_2, 330 const char* arg_name_2,
294 const char* arg_value_2, 331 const char* arg_value_2,
295 const char* arg_name_3, 332 const char* arg_name_3,
296 const char* arg_value_3) { 333 const char* arg_value_3) {
297 if (!GetInstance() || !GetInstance()->etw_export_enabled_ || 334 auto* instance = GetInstance();
298 !EventEnabledChromeEvent()) 335 if (!instance || !instance->etw_export_enabled_ || !EventEnabledChromeEvent())
299 return; 336 return;
300 337
301 EventWriteChromeEvent(name, phase, arg_name_1, arg_value_1, arg_name_2, 338 EventWriteChromeEvent(name, phase, arg_name_1, arg_value_1, arg_name_2,
302 arg_value_2, arg_name_3, arg_value_3); 339 arg_value_2, arg_name_3, arg_value_3);
303 } 340 }
304 341
305 // static 342 // static
306 bool TraceEventETWExport::IsCategoryGroupEnabled( 343 bool TraceEventETWExport::IsCategoryGroupEnabled(
307 const char* category_group_name) { 344 const char* category_group_name) {
308 DCHECK(category_group_name); 345 DCHECK(category_group_name);
309 auto instance = GetInstance(); 346 auto* instance = GetInstance();
310 if (instance == nullptr) 347 if (instance == nullptr)
311 return false; 348 return false;
312 349
313 if (!instance->IsETWExportEnabled()) 350 if (!instance->IsETWExportEnabled())
314 return false; 351 return false;
315 352
316 CStringTokenizer category_group_tokens( 353 CStringTokenizer category_group_tokens(
317 category_group_name, category_group_name + strlen(category_group_name), 354 category_group_name, category_group_name + strlen(category_group_name),
318 ","); 355 ",");
319 while (category_group_tokens.GetNext()) { 356 while (category_group_tokens.GetNext()) {
(...skipping 27 matching lines...) Expand all
347 categories_status_[other_events_group_name] = true; 384 categories_status_[other_events_group_name] = true;
348 } else { 385 } else {
349 categories_status_[other_events_group_name] = false; 386 categories_status_[other_events_group_name] = false;
350 } 387 }
351 if (etw_match_any_keyword_ & disabled_other_events_keyword_bit) { 388 if (etw_match_any_keyword_ & disabled_other_events_keyword_bit) {
352 categories_status_[disabled_other_events_group_name] = true; 389 categories_status_[disabled_other_events_group_name] = true;
353 } else { 390 } else {
354 categories_status_[disabled_other_events_group_name] = false; 391 categories_status_[disabled_other_events_group_name] = false;
355 } 392 }
356 393
394 // Update the categories in TraceLog.
395 TraceLog::GetInstance()->UpdateETWCategoryGroupEnabledFlags();
396
357 return true; 397 return true;
358 } 398 }
359 399
360 bool TraceEventETWExport::IsCategoryEnabled(const char* category_name) const { 400 bool TraceEventETWExport::IsCategoryEnabled(const char* category_name) const {
361 // Try to find the category and return its status if found 401 // Try to find the category and return its status if found
362 auto it = categories_status_.find(category_name); 402 auto it = categories_status_.find(category_name);
363 if (it != categories_status_.end()) 403 if (it != categories_status_.end())
364 return it->second; 404 return it->second;
365 405
366 // Otherwise return the corresponding default status by first checking if the 406 // Otherwise return the corresponding default status by first checking if the
367 // category is disabled by default. 407 // category is disabled by default.
368 if (StringPiece(category_name).starts_with("disabled-by-default")) { 408 if (StringPiece(category_name).starts_with("disabled-by-default")) {
369 DCHECK(categories_status_.find(disabled_other_events_group_name) != 409 DCHECK(categories_status_.find(disabled_other_events_group_name) !=
370 categories_status_.end()); 410 categories_status_.end());
371 return categories_status_.find(disabled_other_events_group_name)->second; 411 return categories_status_.find(disabled_other_events_group_name)->second;
372 } else { 412 } else {
373 DCHECK(categories_status_.find(other_events_group_name) != 413 DCHECK(categories_status_.find(other_events_group_name) !=
374 categories_status_.end()); 414 categories_status_.end());
375 return categories_status_.find(other_events_group_name)->second; 415 return categories_status_.find(other_events_group_name)->second;
376 } 416 }
377 } 417 }
378 418
419 // static
420 void TraceEventETWExport::UpdateETWKeyword() {
421 if (!IsETWExportEnabled())
422 return;
423 auto* instance = GetInstance();
424 DCHECK(instance);
425 instance->UpdateEnabledCategories();
426 }
379 } // namespace trace_event 427 } // namespace trace_event
380 } // namespace base 428 } // namespace base
OLDNEW
« no previous file with comments | « base/trace_event/trace_event_etw_export_win.h ('k') | base/trace_event/trace_log.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698