OLD | NEW |
---|---|
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_log.h" | 5 #include "base/trace_event/trace_log.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cmath> | 8 #include <cmath> |
9 #include <memory> | 9 #include <memory> |
10 #include <utility> | 10 #include <utility> |
11 | 11 |
12 #include "base/base_switches.h" | 12 #include "base/base_switches.h" |
13 #include "base/bind.h" | 13 #include "base/bind.h" |
14 #include "base/command_line.h" | 14 #include "base/command_line.h" |
15 #include "base/debug/leak_annotations.h" | 15 #include "base/debug/leak_annotations.h" |
16 #include "base/lazy_instance.h" | 16 #include "base/lazy_instance.h" |
17 #include "base/location.h" | 17 #include "base/location.h" |
18 #include "base/macros.h" | 18 #include "base/macros.h" |
19 #include "base/memory/ptr_util.h" | |
19 #include "base/memory/ref_counted_memory.h" | 20 #include "base/memory/ref_counted_memory.h" |
20 #include "base/memory/singleton.h" | 21 #include "base/memory/singleton.h" |
21 #include "base/process/process_metrics.h" | 22 #include "base/process/process_metrics.h" |
22 #include "base/stl_util.h" | 23 #include "base/stl_util.h" |
23 #include "base/strings/string_split.h" | 24 #include "base/strings/string_split.h" |
24 #include "base/strings/string_tokenizer.h" | 25 #include "base/strings/string_tokenizer.h" |
25 #include "base/strings/stringprintf.h" | 26 #include "base/strings/stringprintf.h" |
26 #include "base/sys_info.h" | 27 #include "base/sys_info.h" |
27 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" | 28 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" |
28 #include "base/thread_task_runner_handle.h" | 29 #include "base/thread_task_runner_handle.h" |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
95 // convert internally to determine the category name from the char enabled | 96 // convert internally to determine the category name from the char enabled |
96 // pointer. | 97 // pointer. |
97 const char* g_category_groups[MAX_CATEGORY_GROUPS] = { | 98 const char* g_category_groups[MAX_CATEGORY_GROUPS] = { |
98 "toplevel", | 99 "toplevel", |
99 "tracing already shutdown", | 100 "tracing already shutdown", |
100 "tracing categories exhausted; must increase MAX_CATEGORY_GROUPS", | 101 "tracing categories exhausted; must increase MAX_CATEGORY_GROUPS", |
101 "__metadata"}; | 102 "__metadata"}; |
102 | 103 |
103 // The enabled flag is char instead of bool so that the API can be used from C. | 104 // The enabled flag is char instead of bool so that the API can be used from C. |
104 unsigned char g_category_group_enabled[MAX_CATEGORY_GROUPS] = {0}; | 105 unsigned char g_category_group_enabled[MAX_CATEGORY_GROUPS] = {0}; |
106 | |
107 class TraceEventFilter { | |
108 public: | |
109 TraceEventFilter() {} | |
Primiano Tucci (use gerrit)
2016/05/11 16:11:57
I think you need a virtual dtor here (and override
oystein (OOO til 10th of July)
2016/05/20 20:03:44
Done.
| |
110 virtual bool FilterTraceEvent(const TraceEvent& trace_event) const = 0; | |
111 | |
112 private: | |
113 DISALLOW_COPY_AND_ASSIGN(TraceEventFilter); | |
114 }; | |
115 | |
116 class EventNameFilter : public TraceEventFilter { | |
117 public: | |
118 EventNameFilter(const base::DictionaryValue* filter_args) { | |
119 const base::ListValue* whitelist = nullptr; | |
120 if (filter_args->GetList("event_name_whitelist", &whitelist)) { | |
121 for (size_t i = 0; i < whitelist->GetSize(); ++i) { | |
122 std::string event_name; | |
123 if (!whitelist->GetString(i, &event_name)) | |
124 continue; | |
125 | |
126 whitelist_[event_name] = true; | |
127 } | |
128 } | |
129 } | |
130 | |
131 bool FilterTraceEvent(const TraceEvent& trace_event) const override { | |
132 return (whitelist_.find(trace_event.name()) != whitelist_.end()); | |
Primiano Tucci (use gerrit)
2016/05/11 16:11:57
either .count(...) != 0 or ContainsKey from base/s
oystein (OOO til 10th of July)
2016/05/20 20:03:44
Done.
| |
133 } | |
134 | |
135 private: | |
136 std::unordered_map<std::string, bool> whitelist_; | |
Primiano Tucci (use gerrit)
2016/05/11 16:11:57
Not sure what the bool is for, you seem to always
oystein (OOO til 10th of July)
2016/05/20 20:03:44
Done.
| |
137 }; | |
138 | |
139 base::LazyInstance<std::list<std::unique_ptr<TraceEventFilter>>>::Leaky | |
140 g_category_group_filter[MAX_CATEGORY_GROUPS] = {LAZY_INSTANCE_INITIALIZER}; | |
141 | |
105 // Indexes here have to match the g_category_groups array indexes above. | 142 // Indexes here have to match the g_category_groups array indexes above. |
106 const int g_category_already_shutdown = 1; | 143 const int g_category_already_shutdown = 1; |
107 const int g_category_categories_exhausted = 2; | 144 const int g_category_categories_exhausted = 2; |
108 const int g_category_metadata = 3; | 145 const int g_category_metadata = 3; |
109 const int g_num_builtin_categories = 4; | 146 const int g_num_builtin_categories = 4; |
110 // Skip default categories. | 147 // Skip default categories. |
111 base::subtle::AtomicWord g_category_index = g_num_builtin_categories; | 148 base::subtle::AtomicWord g_category_index = g_num_builtin_categories; |
112 | 149 |
113 // The name of the current thread. This is used to decide if the current | 150 // The name of the current thread. This is used to decide if the current |
114 // thread name has changed. We combine all the seen thread names into the | 151 // thread name has changed. We combine all the seen thread names into the |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
427 const unsigned char* TraceLog::GetCategoryGroupEnabled( | 464 const unsigned char* TraceLog::GetCategoryGroupEnabled( |
428 const char* category_group) { | 465 const char* category_group) { |
429 TraceLog* tracelog = GetInstance(); | 466 TraceLog* tracelog = GetInstance(); |
430 if (!tracelog) { | 467 if (!tracelog) { |
431 DCHECK(!g_category_group_enabled[g_category_already_shutdown]); | 468 DCHECK(!g_category_group_enabled[g_category_already_shutdown]); |
432 return &g_category_group_enabled[g_category_already_shutdown]; | 469 return &g_category_group_enabled[g_category_already_shutdown]; |
433 } | 470 } |
434 return tracelog->GetCategoryGroupEnabledInternal(category_group); | 471 return tracelog->GetCategoryGroupEnabledInternal(category_group); |
435 } | 472 } |
436 | 473 |
437 const char* TraceLog::GetCategoryGroupName( | 474 namespace { |
438 const unsigned char* category_group_enabled) { | 475 uintptr_t GetCategoryIndex(const unsigned char* category_group_enabled) { |
Primiano Tucci (use gerrit)
2016/05/11 16:11:57
should this be moved to the anonymous namespace ab
oystein (OOO til 10th of July)
2016/05/20 20:03:44
Ah, done; added it in the middle for expensive whi
| |
439 // Calculate the index of the category group by finding | 476 // Calculate the index of the category group by finding |
440 // category_group_enabled in g_category_group_enabled array. | 477 // category_group_enabled in g_category_group_enabled array. |
441 uintptr_t category_begin = | 478 uintptr_t category_begin = |
442 reinterpret_cast<uintptr_t>(g_category_group_enabled); | 479 reinterpret_cast<uintptr_t>(g_category_group_enabled); |
443 uintptr_t category_ptr = reinterpret_cast<uintptr_t>(category_group_enabled); | 480 uintptr_t category_ptr = reinterpret_cast<uintptr_t>(category_group_enabled); |
444 DCHECK(category_ptr >= category_begin && | 481 DCHECK(category_ptr >= category_begin && |
445 category_ptr < reinterpret_cast<uintptr_t>(g_category_group_enabled + | 482 category_ptr < reinterpret_cast<uintptr_t>(g_category_group_enabled + |
446 MAX_CATEGORY_GROUPS)) | 483 MAX_CATEGORY_GROUPS)) |
447 << "out of bounds category pointer"; | 484 << "out of bounds category pointer"; |
448 uintptr_t category_index = | 485 uintptr_t category_index = |
449 (category_ptr - category_begin) / sizeof(g_category_group_enabled[0]); | 486 (category_ptr - category_begin) / sizeof(g_category_group_enabled[0]); |
450 return g_category_groups[category_index]; | 487 |
488 return category_index; | |
489 } | |
490 } | |
491 | |
492 const char* TraceLog::GetCategoryGroupName( | |
493 const unsigned char* category_group_enabled) { | |
494 return g_category_groups[GetCategoryIndex(category_group_enabled)]; | |
495 } | |
496 | |
497 std::list<std::unique_ptr<TraceEventFilter>>* GetCategoryGroupFilter( | |
498 const unsigned char* category_group_enabled) { | |
499 return g_category_group_filter[GetCategoryIndex(category_group_enabled)] | |
500 .Pointer(); | |
451 } | 501 } |
452 | 502 |
453 void TraceLog::UpdateCategoryGroupEnabledFlag(size_t category_index) { | 503 void TraceLog::UpdateCategoryGroupEnabledFlag(size_t category_index) { |
454 unsigned char enabled_flag = 0; | 504 unsigned char enabled_flag = 0; |
455 const char* category_group = g_category_groups[category_index]; | 505 const char* category_group = g_category_groups[category_index]; |
456 if (mode_ == RECORDING_MODE && | 506 if (mode_ == RECORDING_MODE && |
457 trace_config_.IsCategoryGroupEnabled(category_group)) { | 507 trace_config_.IsCategoryGroupEnabled(category_group)) { |
458 enabled_flag |= ENABLED_FOR_RECORDING; | 508 enabled_flag |= ENABLED_FOR_RECORDING; |
459 } | 509 } |
460 | 510 |
461 if (event_callback_ && | 511 if (event_callback_ && |
462 event_callback_trace_config_.IsCategoryGroupEnabled(category_group)) { | 512 event_callback_trace_config_.IsCategoryGroupEnabled(category_group)) { |
463 enabled_flag |= ENABLED_FOR_EVENT_CALLBACK; | 513 enabled_flag |= ENABLED_FOR_EVENT_CALLBACK; |
464 } | 514 } |
465 | 515 |
466 #if defined(OS_WIN) | 516 #if defined(OS_WIN) |
467 if (base::trace_event::TraceEventETWExport::IsCategoryGroupEnabled( | 517 if (base::trace_event::TraceEventETWExport::IsCategoryGroupEnabled( |
468 category_group)) { | 518 category_group)) { |
469 enabled_flag |= ENABLED_FOR_ETW_EXPORT; | 519 enabled_flag |= ENABLED_FOR_ETW_EXPORT; |
470 } | 520 } |
471 #endif | 521 #endif |
472 | 522 |
523 if (!(g_category_group_filter[category_index] == nullptr)) | |
Primiano Tucci (use gerrit)
2016/05/11 16:11:57
Isn't a bit more readable if here you cache once t
oystein (OOO til 10th of July)
2016/05/20 20:03:44
My idea was to avoid the Get() (and hence the Lazy
| |
524 g_category_group_filter[category_index].Get().clear(); | |
525 | |
526 for (const auto& category_event_filter : | |
527 trace_config_.category_event_filters()) { | |
528 if (category_event_filter.IsCategoryGroupEnabled(category_group)) { | |
529 std::unique_ptr<TraceEventFilter> new_filter; | |
530 | |
531 if (category_event_filter.predicate_name() == | |
532 "event_whitelist_predicate") { | |
533 new_filter = | |
534 WrapUnique(new EventNameFilter(category_event_filter.args())); | |
535 } | |
536 | |
537 if (new_filter) { | |
538 g_category_group_filter[category_index].Get().push_back( | |
539 std::move(new_filter)); | |
540 enabled_flag |= ENABLED_FOR_FILTERING; | |
541 } | |
542 } | |
543 } | |
544 | |
473 g_category_group_enabled[category_index] = enabled_flag; | 545 g_category_group_enabled[category_index] = enabled_flag; |
474 } | 546 } |
475 | 547 |
476 void TraceLog::UpdateCategoryGroupEnabledFlags() { | 548 void TraceLog::UpdateCategoryGroupEnabledFlags() { |
477 size_t category_index = base::subtle::NoBarrier_Load(&g_category_index); | 549 size_t category_index = base::subtle::NoBarrier_Load(&g_category_index); |
478 for (size_t i = 0; i < category_index; i++) | 550 for (size_t i = 0; i < category_index; i++) |
479 UpdateCategoryGroupEnabledFlag(i); | 551 UpdateCategoryGroupEnabledFlag(i); |
480 } | 552 } |
481 | 553 |
482 void TraceLog::UpdateSyntheticDelaysFromTraceConfig() { | 554 void TraceLog::UpdateSyntheticDelaysFromTraceConfig() { |
(...skipping 757 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1240 #if defined(OS_WIN) | 1312 #if defined(OS_WIN) |
1241 // This is done sooner rather than later, to avoid creating the event and | 1313 // This is done sooner rather than later, to avoid creating the event and |
1242 // acquiring the lock, which is not needed for ETW as it's already threadsafe. | 1314 // acquiring the lock, which is not needed for ETW as it's already threadsafe. |
1243 if (*category_group_enabled & ENABLED_FOR_ETW_EXPORT) | 1315 if (*category_group_enabled & ENABLED_FOR_ETW_EXPORT) |
1244 TraceEventETWExport::AddEvent(phase, category_group_enabled, name, id, | 1316 TraceEventETWExport::AddEvent(phase, category_group_enabled, name, id, |
1245 num_args, arg_names, arg_types, arg_values, | 1317 num_args, arg_names, arg_types, arg_values, |
1246 convertable_values); | 1318 convertable_values); |
1247 #endif // OS_WIN | 1319 #endif // OS_WIN |
1248 | 1320 |
1249 std::string console_message; | 1321 std::string console_message; |
1250 if (*category_group_enabled & ENABLED_FOR_RECORDING) { | 1322 if (*category_group_enabled & ENABLED_FOR_FILTERING) { |
1323 std::unique_ptr<TraceEvent> new_trace_event(new TraceEvent); | |
oystein (OOO til 10th of July)
2016/05/04 23:20:44
TODO: Figure out a way to keep this on the stack i
| |
1324 new_trace_event->Initialize(thread_id, offset_event_timestamp, thread_now, | |
1325 phase, category_group_enabled, name, scope, id, | |
1326 bind_id, num_args, arg_names, arg_types, | |
1327 arg_values, convertable_values, flags); | |
1328 | |
1329 std::list<std::unique_ptr<TraceEventFilter>>* filter_list = | |
Primiano Tucci (use gerrit)
2016/05/11 16:11:58
maybe that's a good case for auto? :)
oystein (OOO til 10th of July)
2016/05/20 20:03:44
Done.
| |
1330 GetCategoryGroupFilter(category_group_enabled); | |
1331 DCHECK(filter_list); | |
Primiano Tucci (use gerrit)
2016/05/11 16:11:57
I think the policy in chrome is to not DCHECK for
oystein (OOO til 10th of July)
2016/05/20 20:03:44
Done.
| |
1332 DCHECK(!filter_list->empty()); | |
1333 | |
1334 bool should_add_event = false; | |
1335 for (const auto& trace_event_filter : *filter_list) { | |
1336 DCHECK(trace_event_filter); | |
Primiano Tucci (use gerrit)
2016/05/11 16:11:57
ditto here, remove this dcheck
oystein (OOO til 10th of July)
2016/05/20 20:03:44
Done.
| |
1337 if (trace_event_filter.get()->FilterTraceEvent(*new_trace_event)) | |
1338 should_add_event = true; | |
1339 } | |
1340 | |
1341 if (should_add_event) { | |
1342 OptionalAutoLock lock(&lock_); | |
1343 | |
1344 TraceEvent* trace_event = NULL; | |
1345 if (thread_local_event_buffer) { | |
1346 trace_event = thread_local_event_buffer->AddTraceEvent(&handle); | |
1347 } else { | |
1348 lock.EnsureAcquired(); | |
Primiano Tucci (use gerrit)
2016/05/11 16:11:57
Instead of copy-pasting this logic here, which is
oystein (OOO til 10th of July)
2016/05/20 20:03:44
Done; it's a little awkward to handle all the case
| |
1349 trace_event = AddEventToThreadSharedChunkWhileLocked(&handle, true); | |
1350 } | |
1351 | |
1352 trace_event->MoveFrom(std::move(new_trace_event)); | |
1353 } | |
1354 } else if (*category_group_enabled & ENABLED_FOR_RECORDING) { | |
1251 OptionalAutoLock lock(&lock_); | 1355 OptionalAutoLock lock(&lock_); |
1252 | 1356 |
1253 TraceEvent* trace_event = NULL; | 1357 TraceEvent* trace_event = NULL; |
1254 if (thread_local_event_buffer) { | 1358 if (thread_local_event_buffer) { |
1255 trace_event = thread_local_event_buffer->AddTraceEvent(&handle); | 1359 trace_event = thread_local_event_buffer->AddTraceEvent(&handle); |
1256 } else { | 1360 } else { |
1257 lock.EnsureAcquired(); | 1361 lock.EnsureAcquired(); |
1258 trace_event = AddEventToThreadSharedChunkWhileLocked(&handle, true); | 1362 trace_event = AddEventToThreadSharedChunkWhileLocked(&handle, true); |
1259 } | 1363 } |
1260 | 1364 |
(...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1742 } | 1846 } |
1743 | 1847 |
1744 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() { | 1848 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() { |
1745 if (*category_group_enabled_) { | 1849 if (*category_group_enabled_) { |
1746 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, name_, | 1850 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, name_, |
1747 event_handle_); | 1851 event_handle_); |
1748 } | 1852 } |
1749 } | 1853 } |
1750 | 1854 |
1751 } // namespace trace_event_internal | 1855 } // namespace trace_event_internal |
OLD | NEW |