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

Side by Side Diff: trace_event/trace_event_etw_export_win.cc

Issue 2045303002: Update to Chromium //base at Chromium commit 3e81715e6d3a4324362635aea46ce1f1a163cca1. (Closed) Base URL: https://chromium.googlesource.com/external/github.com/domokit/base@master
Patch Set: Created 4 years, 6 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 | « trace_event/trace_event_etw_export_win.h ('k') | trace_event/trace_log.cc » ('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"
(...skipping 25 matching lines...) Expand all
36 typedef ULONG(__stdcall* tEventWrite)(REGHANDLE RegHandle, 36 typedef ULONG(__stdcall* tEventWrite)(REGHANDLE RegHandle,
37 PCEVENT_DESCRIPTOR EventDescriptor, 37 PCEVENT_DESCRIPTOR EventDescriptor,
38 ULONG UserDataCount, 38 ULONG UserDataCount,
39 PEVENT_DATA_DESCRIPTOR UserData); 39 PEVENT_DATA_DESCRIPTOR UserData);
40 typedef ULONG(__stdcall* tEventUnregister)(REGHANDLE RegHandle); 40 typedef ULONG(__stdcall* tEventUnregister)(REGHANDLE RegHandle);
41 41
42 tEventRegister EventRegisterProc = nullptr; 42 tEventRegister EventRegisterProc = nullptr;
43 tEventWrite EventWriteProc = nullptr; 43 tEventWrite EventWriteProc = nullptr;
44 tEventUnregister EventUnregisterProc = nullptr; 44 tEventUnregister EventUnregisterProc = nullptr;
45 45
46 // |filtered_event_group_names| contains the event categories that can be 46 // |kFilteredEventGroupNames| contains the event categories that can be
47 // exported individually. These categories can be enabled by passing the correct 47 // exported individually. These categories can be enabled by passing the correct
48 // keyword when starting the trace. A keyword is a 64-bit flag and we attribute 48 // keyword when starting the trace. A keyword is a 64-bit flag and we attribute
49 // one bit per category. We can therefore enable a particular category by 49 // one bit per category. We can therefore enable a particular category by
50 // setting its corresponding bit in the keyword. For events that are not present 50 // setting its corresponding bit in the keyword. For events that are not present
51 // in |filtered_event_group_names|, we have two bits that control their 51 // in |kFilteredEventGroupNames|, we have two bits that control their
52 // behaviour. When bit 61 is enabled, any event that is not disabled by default 52 // behaviour. When bit 61 is enabled, any event that is not disabled by default
53 // (ie. doesn't start with disabled-by-default-) will be exported. Likewise, 53 // (ie. doesn't start with disabled-by-default-) will be exported. Likewise,
54 // when bit 62 is enabled, any event that is disabled by default will be 54 // when bit 62 is enabled, any event that is disabled by default will be
55 // exported. 55 // exported.
56 // 56 //
57 // Note that bit 63 (MSB) must always be set, otherwise tracing will be disabled 57 // Note that bit 63 (MSB) must always be set, otherwise tracing will be disabled
58 // by ETW. Therefore, the keyword will always be greater than 58 // by ETW. Therefore, the keyword will always be greater than
59 // 0x8000000000000000. 59 // 0x8000000000000000.
60 // 60 //
61 // Examples of passing keywords to the provider using xperf: 61 // Examples of passing keywords to the provider using xperf:
62 // # This exports "benchmark" and "cc" events 62 // # This exports "benchmark" and "cc" events
63 // xperf -start chrome -on Chrome:0x8000000000000009 63 // xperf -start chrome -on Chrome:0x8000000000000009
64 // 64 //
65 // # This exports "gpu", "netlog" and all other events that are not disabled by 65 // # This exports "gpu", "netlog" and all other events that are not disabled by
66 // # default 66 // # default
67 // xperf -start chrome -on Chrome:0xA0000000000000A0 67 // xperf -start chrome -on Chrome:0xA0000000000000A0
68 // 68 //
69 // More info about starting a trace and keyword can be obtained by using the 69 // More info about starting a trace and keyword can be obtained by using the
70 // help section of xperf (xperf -help start). Note that xperf documentation 70 // help section of xperf (xperf -help start). Note that xperf documentation
71 // refers to keywords as flags and there are two ways to enable them, using 71 // refers to keywords as flags and there are two ways to enable them, using
72 // group names or the hex representation. We only support the latter. Also, we 72 // group names or the hex representation. We only support the latter. Also, we
73 // ignore the level. 73 // ignore the level.
74 const char* const filtered_event_group_names[] = { 74 const char* const kFilteredEventGroupNames[] = {
75 "benchmark", // 0x1 75 "benchmark", // 0x1
76 "blink", // 0x2 76 "blink", // 0x2
77 "browser", // 0x4 77 "browser", // 0x4
78 "cc", // 0x8 78 "cc", // 0x8
79 "evdev", // 0x10 79 "evdev", // 0x10
80 "gpu", // 0x20 80 "gpu", // 0x20
81 "input", // 0x40 81 "input", // 0x40
82 "netlog", // 0x80 82 "netlog", // 0x80
83 "renderer.scheduler", // 0x100 83 "renderer.scheduler", // 0x100
84 "toplevel", // 0x200 84 "toplevel", // 0x200
85 "v8", // 0x400 85 "v8", // 0x400
86 "disabled-by-default-cc.debug", // 0x800 86 "disabled-by-default-cc.debug", // 0x800
87 "disabled-by-default-cc.debug.picture", // 0x1000 87 "disabled-by-default-cc.debug.picture", // 0x1000
88 "disabled-by-default-toplevel.flow"}; // 0x2000 88 "disabled-by-default-toplevel.flow"}; // 0x2000
89 const char* other_events_group_name = "__OTHER_EVENTS"; // 0x2000000000000000 89 const char kOtherEventsGroupName[] = "__OTHER_EVENTS"; // 0x2000000000000000
90 const char* disabled_other_events_group_name = 90 const char kDisabledOtherEventsGroupName[] =
91 "__DISABLED_OTHER_EVENTS"; // 0x4000000000000000 91 "__DISABLED_OTHER_EVENTS"; // 0x4000000000000000
92 uint64 other_events_keyword_bit = 1ULL << 61; 92 const uint64 kOtherEventsKeywordBit = 1ULL << 61;
93 uint64 disabled_other_events_keyword_bit = 1ULL << 62; 93 const uint64 kDisabledOtherEventsKeywordBit = 1ULL << 62;
94 94 const size_t kNumberOfCategories = ARRAYSIZE(kFilteredEventGroupNames) + 2U;
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 95
118 } // namespace 96 } // namespace
119 97
120 // Redirector function for EventRegister. Called by macros in 98 // Redirector function for EventRegister. Called by macros in
121 // chrome_events_win.h 99 // chrome_events_win.h
122 ULONG EVNTAPI EventRegister(LPCGUID ProviderId, 100 ULONG EVNTAPI EventRegister(LPCGUID ProviderId,
123 PENABLECALLBACK EnableCallback, 101 PENABLECALLBACK EnableCallback,
124 PVOID CallbackContext, 102 PVOID CallbackContext,
125 PREGHANDLE RegHandle) { 103 PREGHANDLE RegHandle) {
126 if (EventRegisterProc) 104 if (EventRegisterProc)
(...skipping 18 matching lines...) Expand all
145 // chrome_events_win.h 123 // chrome_events_win.h
146 ULONG EVNTAPI EventUnregister(REGHANDLE RegHandle) { 124 ULONG EVNTAPI EventUnregister(REGHANDLE RegHandle) {
147 if (EventUnregisterProc) 125 if (EventUnregisterProc)
148 return EventUnregisterProc(RegHandle); 126 return EventUnregisterProc(RegHandle);
149 return 0; 127 return 0;
150 } 128 }
151 129
152 namespace base { 130 namespace base {
153 namespace trace_event { 131 namespace trace_event {
154 132
133 // This object will be created by each process. It's a background (low-priority)
134 // thread that will monitor the ETW keyword for any changes.
135 class TraceEventETWExport::ETWKeywordUpdateThread
136 : public base::PlatformThread::Delegate {
137 public:
138 ETWKeywordUpdateThread() {}
139 ~ETWKeywordUpdateThread() override {}
140
141 // Implementation of PlatformThread::Delegate:
142 void ThreadMain() override {
143 base::PlatformThread::SetName("ETW Keyword Update Thread");
144 base::TimeDelta sleep_time =
145 base::TimeDelta::FromMilliseconds(kUpdateTimerDelayMs);
146 while (1) {
147 base::PlatformThread::Sleep(sleep_time);
148 base::trace_event::TraceEventETWExport::UpdateETWKeyword();
149 }
150 }
151
152 private:
153 // Time between checks for ETW keyword changes (in milliseconds).
154 unsigned int kUpdateTimerDelayMs = 1000;
155 };
156
155 TraceEventETWExport::TraceEventETWExport() 157 TraceEventETWExport::TraceEventETWExport()
156 : etw_export_enabled_(false), etw_match_any_keyword_(0ULL) { 158 : etw_export_enabled_(false), etw_match_any_keyword_(0ULL) {
157 // Find Advapi32.dll. This should always succeed. 159 // Find Advapi32.dll. This should always succeed.
158 HMODULE AdvapiDLL = ::LoadLibraryW(L"Advapi32.dll"); 160 HMODULE AdvapiDLL = ::LoadLibraryW(L"Advapi32.dll");
159 if (AdvapiDLL) { 161 if (AdvapiDLL) {
160 // Try to find the ETW functions. This will fail on XP. 162 // Try to find the ETW functions. This will fail on XP.
161 EventRegisterProc = reinterpret_cast<tEventRegister>( 163 EventRegisterProc = reinterpret_cast<tEventRegister>(
162 ::GetProcAddress(AdvapiDLL, "EventRegister")); 164 ::GetProcAddress(AdvapiDLL, "EventRegister"));
163 EventWriteProc = reinterpret_cast<tEventWrite>( 165 EventWriteProc = reinterpret_cast<tEventWrite>(
164 ::GetProcAddress(AdvapiDLL, "EventWrite")); 166 ::GetProcAddress(AdvapiDLL, "EventWrite"));
165 EventUnregisterProc = reinterpret_cast<tEventUnregister>( 167 EventUnregisterProc = reinterpret_cast<tEventUnregister>(
166 ::GetProcAddress(AdvapiDLL, "EventUnregister")); 168 ::GetProcAddress(AdvapiDLL, "EventUnregister"));
167 169
168 // Register the ETW provider. If registration fails then the event logging 170 // Register the ETW provider. If registration fails then the event logging
169 // calls will fail (on XP this call will do nothing). 171 // calls will fail (on XP this call will do nothing).
170 EventRegisterChrome(); 172 EventRegisterChrome();
171 } 173 }
174
175 // Make sure to initialize the map with all the group names. Subsequent
176 // modifications will be made by the background thread and only affect the
177 // values of the keys (no key addition/deletion). Therefore, the map does not
178 // require a lock for access.
179 for (int i = 0; i < ARRAYSIZE(kFilteredEventGroupNames); i++)
180 categories_status_[kFilteredEventGroupNames[i]] = false;
181 categories_status_[kOtherEventsGroupName] = false;
182 categories_status_[kDisabledOtherEventsGroupName] = false;
183 DCHECK_EQ(kNumberOfCategories, categories_status_.size());
172 } 184 }
173 185
174 TraceEventETWExport::~TraceEventETWExport() { 186 TraceEventETWExport::~TraceEventETWExport() {
175 EventUnregisterChrome(); 187 EventUnregisterChrome();
176 } 188 }
177 189
178 // static 190 // static
179 TraceEventETWExport* TraceEventETWExport::GetInstance() { 191 TraceEventETWExport* TraceEventETWExport::GetInstance() {
180 return Singleton<TraceEventETWExport, 192 return Singleton<TraceEventETWExport,
181 StaticMemorySingletonTraits<TraceEventETWExport>>::get(); 193 StaticMemorySingletonTraits<TraceEventETWExport>>::get();
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 376
365 bool TraceEventETWExport::UpdateEnabledCategories() { 377 bool TraceEventETWExport::UpdateEnabledCategories() {
366 if (etw_match_any_keyword_ == CHROME_Context.MatchAnyKeyword) 378 if (etw_match_any_keyword_ == CHROME_Context.MatchAnyKeyword)
367 return false; 379 return false;
368 380
369 // If the keyword has changed, update each category. 381 // If the keyword has changed, update each category.
370 // Chrome_Context.MatchAnyKeyword is set by UIforETW (or other ETW trace 382 // Chrome_Context.MatchAnyKeyword is set by UIforETW (or other ETW trace
371 // recording tools) using the ETW infrastructure. This value will be set in 383 // recording tools) using the ETW infrastructure. This value will be set in
372 // all Chrome processes that have registered their ETW provider. 384 // all Chrome processes that have registered their ETW provider.
373 etw_match_any_keyword_ = CHROME_Context.MatchAnyKeyword; 385 etw_match_any_keyword_ = CHROME_Context.MatchAnyKeyword;
374 for (int i = 0; i < ARRAYSIZE(filtered_event_group_names); i++) { 386 for (int i = 0; i < ARRAYSIZE(kFilteredEventGroupNames); i++) {
375 if (etw_match_any_keyword_ & (1ULL << i)) { 387 if (etw_match_any_keyword_ & (1ULL << i)) {
376 categories_status_[filtered_event_group_names[i]] = true; 388 categories_status_[kFilteredEventGroupNames[i]] = true;
377 } else { 389 } else {
378 categories_status_[filtered_event_group_names[i]] = false; 390 categories_status_[kFilteredEventGroupNames[i]] = false;
379 } 391 }
380 } 392 }
381 393
382 // Also update the two default categories. 394 // Also update the two default categories.
383 if (etw_match_any_keyword_ & other_events_keyword_bit) { 395 if (etw_match_any_keyword_ & kOtherEventsKeywordBit) {
384 categories_status_[other_events_group_name] = true; 396 categories_status_[kOtherEventsGroupName] = true;
385 } else { 397 } else {
386 categories_status_[other_events_group_name] = false; 398 categories_status_[kOtherEventsGroupName] = false;
387 } 399 }
388 if (etw_match_any_keyword_ & disabled_other_events_keyword_bit) { 400 if (etw_match_any_keyword_ & kDisabledOtherEventsKeywordBit) {
389 categories_status_[disabled_other_events_group_name] = true; 401 categories_status_[kDisabledOtherEventsGroupName] = true;
390 } else { 402 } else {
391 categories_status_[disabled_other_events_group_name] = false; 403 categories_status_[kDisabledOtherEventsGroupName] = false;
392 } 404 }
393 405
406 DCHECK_EQ(kNumberOfCategories, categories_status_.size());
407
394 // Update the categories in TraceLog. 408 // Update the categories in TraceLog.
395 TraceLog::GetInstance()->UpdateETWCategoryGroupEnabledFlags(); 409 TraceLog::GetInstance()->UpdateETWCategoryGroupEnabledFlags();
396 410
397 return true; 411 return true;
398 } 412 }
399 413
400 bool TraceEventETWExport::IsCategoryEnabled(const char* category_name) const { 414 bool TraceEventETWExport::IsCategoryEnabled(const char* category_name) const {
415 DCHECK_EQ(kNumberOfCategories, categories_status_.size());
401 // Try to find the category and return its status if found 416 // Try to find the category and return its status if found
402 auto it = categories_status_.find(category_name); 417 auto it = categories_status_.find(category_name);
403 if (it != categories_status_.end()) 418 if (it != categories_status_.end())
404 return it->second; 419 return it->second;
405 420
406 // Otherwise return the corresponding default status by first checking if the 421 // Otherwise return the corresponding default status by first checking if the
407 // category is disabled by default. 422 // category is disabled by default.
408 if (StringPiece(category_name).starts_with("disabled-by-default")) { 423 if (StringPiece(category_name).starts_with("disabled-by-default")) {
409 DCHECK(categories_status_.find(disabled_other_events_group_name) != 424 DCHECK(categories_status_.find(kDisabledOtherEventsGroupName) !=
410 categories_status_.end()); 425 categories_status_.end());
411 return categories_status_.find(disabled_other_events_group_name)->second; 426 return categories_status_.find(kDisabledOtherEventsGroupName)->second;
412 } else { 427 } else {
413 DCHECK(categories_status_.find(other_events_group_name) != 428 DCHECK(categories_status_.find(kOtherEventsGroupName) !=
414 categories_status_.end()); 429 categories_status_.end());
415 return categories_status_.find(other_events_group_name)->second; 430 return categories_status_.find(kOtherEventsGroupName)->second;
416 } 431 }
417 } 432 }
418 433
419 // static 434 // static
420 void TraceEventETWExport::UpdateETWKeyword() { 435 void TraceEventETWExport::UpdateETWKeyword() {
421 if (!IsETWExportEnabled()) 436 if (!IsETWExportEnabled())
422 return; 437 return;
423 auto* instance = GetInstance(); 438 auto* instance = GetInstance();
424 DCHECK(instance); 439 DCHECK(instance);
425 instance->UpdateEnabledCategories(); 440 instance->UpdateEnabledCategories();
426 } 441 }
427 } // namespace trace_event 442 } // namespace trace_event
428 } // namespace base 443 } // namespace base
OLDNEW
« no previous file with comments | « trace_event/trace_event_etw_export_win.h ('k') | trace_event/trace_log.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698