Chromium Code Reviews| 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 |