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> |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 25 #include "base/strings/string_split.h" | 25 #include "base/strings/string_split.h" |
| 26 #include "base/strings/string_tokenizer.h" | 26 #include "base/strings/string_tokenizer.h" |
| 27 #include "base/strings/stringprintf.h" | 27 #include "base/strings/stringprintf.h" |
| 28 #include "base/sys_info.h" | 28 #include "base/sys_info.h" |
| 29 #include "base/threading/platform_thread.h" | 29 #include "base/threading/platform_thread.h" |
| 30 #include "base/threading/thread_id_name_manager.h" | 30 #include "base/threading/thread_id_name_manager.h" |
| 31 #include "base/threading/thread_task_runner_handle.h" | 31 #include "base/threading/thread_task_runner_handle.h" |
| 32 #include "base/threading/worker_pool.h" | 32 #include "base/threading/worker_pool.h" |
| 33 #include "base/time/time.h" | 33 #include "base/time/time.h" |
| 34 #include "base/trace_event/category_registry.h" | 34 #include "base/trace_event/category_registry.h" |
| 35 #include "base/trace_event/event_filter_registry.h" | |
| 35 #include "base/trace_event/event_name_filter.h" | 36 #include "base/trace_event/event_name_filter.h" |
| 36 #include "base/trace_event/heap_profiler.h" | 37 #include "base/trace_event/heap_profiler.h" |
| 37 #include "base/trace_event/heap_profiler_allocation_context_tracker.h" | 38 #include "base/trace_event/heap_profiler_allocation_context_tracker.h" |
| 38 #include "base/trace_event/heap_profiler_event_filter.h" | 39 #include "base/trace_event/heap_profiler_event_filter.h" |
| 39 #include "base/trace_event/memory_dump_manager.h" | 40 #include "base/trace_event/memory_dump_manager.h" |
| 40 #include "base/trace_event/memory_dump_provider.h" | 41 #include "base/trace_event/memory_dump_provider.h" |
| 41 #include "base/trace_event/process_memory_dump.h" | 42 #include "base/trace_event/process_memory_dump.h" |
| 42 #include "base/trace_event/trace_buffer.h" | 43 #include "base/trace_event/trace_buffer.h" |
| 43 #include "base/trace_event/trace_event.h" | 44 #include "base/trace_event/trace_event.h" |
| 44 #include "base/trace_event/trace_event_synthetic_delay.h" | 45 #include "base/trace_event/trace_event_synthetic_delay.h" |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 79 kTraceEventVectorBufferChunks <= TraceBufferChunk::kMaxChunkIndex, | 80 kTraceEventVectorBufferChunks <= TraceBufferChunk::kMaxChunkIndex, |
| 80 "Too many vector buffer chunks"); | 81 "Too many vector buffer chunks"); |
| 81 const size_t kTraceEventRingBufferChunks = kTraceEventVectorBufferChunks / 4; | 82 const size_t kTraceEventRingBufferChunks = kTraceEventVectorBufferChunks / 4; |
| 82 | 83 |
| 83 // ECHO_TO_CONSOLE needs a small buffer to hold the unfinished COMPLETE events. | 84 // ECHO_TO_CONSOLE needs a small buffer to hold the unfinished COMPLETE events. |
| 84 const size_t kEchoToConsoleTraceEventBufferChunks = 256; | 85 const size_t kEchoToConsoleTraceEventBufferChunks = 256; |
| 85 | 86 |
| 86 const size_t kTraceEventBufferSizeInBytes = 100 * 1024; | 87 const size_t kTraceEventBufferSizeInBytes = 100 * 1024; |
| 87 const int kThreadFlushTimeoutMs = 3000; | 88 const int kThreadFlushTimeoutMs = 3000; |
| 88 | 89 |
| 89 #define MAX_TRACE_EVENT_FILTERS 32 | |
| 90 | |
| 91 // List of TraceEventFilter objects from the most recent tracing session. | |
| 92 base::LazyInstance<std::vector<std::unique_ptr<TraceEventFilter>>>::Leaky | |
| 93 g_category_group_filters = LAZY_INSTANCE_INITIALIZER; | |
| 94 | |
| 95 // The name of the current thread. This is used to decide if the current | 90 // The name of the current thread. This is used to decide if the current |
| 96 // thread name has changed. We combine all the seen thread names into the | 91 // thread name has changed. We combine all the seen thread names into the |
| 97 // output name for the thread. | 92 // output name for the thread. |
| 98 LazyInstance<ThreadLocalPointer<const char>>::Leaky g_current_thread_name = | 93 LazyInstance<ThreadLocalPointer<const char>>::Leaky g_current_thread_name = |
| 99 LAZY_INSTANCE_INITIALIZER; | 94 LAZY_INSTANCE_INITIALIZER; |
| 100 | 95 |
| 101 ThreadTicks ThreadNow() { | 96 ThreadTicks ThreadNow() { |
| 102 return ThreadTicks::IsSupported() ? ThreadTicks::Now() : ThreadTicks(); | 97 return ThreadTicks::IsSupported() ? ThreadTicks::Now() : ThreadTicks(); |
| 103 } | 98 } |
| 104 | 99 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 162 handle->event_index = static_cast<uint16_t>(event_index); | 157 handle->event_index = static_cast<uint16_t>(event_index); |
| 163 } | 158 } |
| 164 | 159 |
| 165 template <typename Function> | 160 template <typename Function> |
| 166 void ForEachCategoryFilter(const unsigned char* category_group_enabled, | 161 void ForEachCategoryFilter(const unsigned char* category_group_enabled, |
| 167 Function filter_fn) { | 162 Function filter_fn) { |
| 168 const TraceCategory* category = | 163 const TraceCategory* category = |
| 169 CategoryRegistry::GetCategoryByStatePtr(category_group_enabled); | 164 CategoryRegistry::GetCategoryByStatePtr(category_group_enabled); |
| 170 uint32_t filter_bitmap = category->enabled_filters(); | 165 uint32_t filter_bitmap = category->enabled_filters(); |
| 171 for (int index = 0; filter_bitmap != 0; filter_bitmap >>= 1, index++) { | 166 for (int index = 0; filter_bitmap != 0; filter_bitmap >>= 1, index++) { |
| 172 if (filter_bitmap & 1 && g_category_group_filters.Get()[index]) | 167 if (filter_bitmap & 1) |
| 173 filter_fn(g_category_group_filters.Get()[index].get()); | 168 filter_fn(EventFilterRegistry::Get(index)); |
| 174 } | 169 } |
| 175 } | 170 } |
| 176 | 171 |
| 177 } // namespace | 172 } // namespace |
| 178 | 173 |
| 179 // A helper class that allows the lock to be acquired in the middle of the scope | 174 // A helper class that allows the lock to be acquired in the middle of the scope |
| 180 // and unlocks at the end of scope if locked. | 175 // and unlocks at the end of scope if locked. |
| 181 class TraceLog::OptionalAutoLock { | 176 class TraceLog::OptionalAutoLock { |
| 182 public: | 177 public: |
| 183 explicit OptionalAutoLock(Lock* lock) : lock_(lock), locked_(false) {} | 178 explicit OptionalAutoLock(Lock* lock) : lock_(lock), locked_(false) {} |
| (...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 462 } | 457 } |
| 463 | 458 |
| 464 #if defined(OS_WIN) | 459 #if defined(OS_WIN) |
| 465 if (base::trace_event::TraceEventETWExport::IsCategoryGroupEnabled( | 460 if (base::trace_event::TraceEventETWExport::IsCategoryGroupEnabled( |
| 466 category->name())) { | 461 category->name())) { |
| 467 state_flags |= TraceCategory::ENABLED_FOR_ETW_EXPORT; | 462 state_flags |= TraceCategory::ENABLED_FOR_ETW_EXPORT; |
| 468 } | 463 } |
| 469 #endif | 464 #endif |
| 470 | 465 |
| 471 uint32_t enabled_filters_bitmap = 0; | 466 uint32_t enabled_filters_bitmap = 0; |
| 472 int index = 0; | 467 for (auto it = EventFilterRegistry::GetActiveFilters(); it.IsValid(); |
| 473 for (const auto& event_filter : enabled_event_filters_) { | 468 it.MoveNext()) { |
| 474 if (event_filter.IsCategoryGroupEnabled(category->name())) { | 469 if (it->IsEnabledForCategory(category->name())) { |
| 475 state_flags |= TraceCategory::ENABLED_FOR_FILTERING; | 470 state_flags |= TraceCategory::ENABLED_FOR_FILTERING; |
| 476 DCHECK(g_category_group_filters.Get()[index]); | 471 enabled_filters_bitmap |= 1ul << it.GetIndex(); |
| 477 enabled_filters_bitmap |= 1 << index; | |
| 478 } | |
| 479 if (index++ >= MAX_TRACE_EVENT_FILTERS) { | |
| 480 NOTREACHED(); | |
| 481 break; | |
| 482 } | 472 } |
| 483 } | 473 } |
| 484 category->set_enabled_filters(enabled_filters_bitmap); | 474 category->set_enabled_filters(enabled_filters_bitmap); |
| 485 category->set_state(state_flags); | 475 category->set_state(state_flags); |
| 486 } | 476 } |
| 487 | 477 |
| 488 void TraceLog::UpdateCategoryRegistry() { | 478 void TraceLog::UpdateCategoryRegistry() { |
| 489 lock_.AssertAcquired(); | 479 lock_.AssertAcquired(); |
| 490 CreateFiltersForTraceConfig(); | |
| 491 for (TraceCategory& category : CategoryRegistry::GetAllCategories()) { | 480 for (TraceCategory& category : CategoryRegistry::GetAllCategories()) { |
| 492 UpdateCategoryState(&category); | 481 UpdateCategoryState(&category); |
| 493 } | 482 } |
| 494 } | 483 } |
| 495 | 484 |
| 496 void TraceLog::CreateFiltersForTraceConfig() { | 485 void TraceLog::CreateFiltersAndUpdateFilterRegistry() { |
| 497 if (!(enabled_modes_ & FILTERING_MODE)) | 486 // At this point all existing filters should have been unregistered. |
| 498 return; | 487 DCHECK(!EventFilterRegistry::GetActiveFilters().IsValid()); |
| 499 | 488 |
| 500 // Filters were already added and tracing could be enabled. Filters list | 489 for (const auto& filter_config : trace_config_.event_filters()) { |
| 501 // cannot be changed when trace events are using them. | 490 // Create a copy of the filter config and pass it to the newly created |
| 502 if (g_category_group_filters.Get().size()) | 491 // filter instance. This allows to check whether a given category should |
| 503 return; | 492 // be filtered without having to keep additional state here in the TraceLog. |
| 504 | 493 std::unique_ptr<TraceEventFilter::Config> base_filter_config( |
| 505 for (auto& filter_config : enabled_event_filters_) { | 494 new TraceConfig::EventFilterConfig(filter_config)); |
| 506 if (g_category_group_filters.Get().size() >= MAX_TRACE_EVENT_FILTERS) { | |
| 507 NOTREACHED() | |
| 508 << "Too many trace event filters installed in the current session"; | |
| 509 break; | |
| 510 } | |
| 511 | |
| 512 std::unique_ptr<TraceEventFilter> new_filter; | 495 std::unique_ptr<TraceEventFilter> new_filter; |
| 513 const std::string& predicate_name = filter_config.predicate_name(); | 496 const std::string& predicate_name = filter_config.predicate_name(); |
| 514 if (predicate_name == EventNameFilter::kName) { | 497 if (predicate_name == EventNameFilter::kName) { |
| 515 auto whitelist = MakeUnique<std::unordered_set<std::string>>(); | 498 auto whitelist = MakeUnique<std::unordered_set<std::string>>(); |
| 516 CHECK(filter_config.GetArgAsSet("event_name_whitelist", &*whitelist)); | 499 CHECK(filter_config.GetArgAsSet("event_name_whitelist", &*whitelist)); |
| 517 new_filter = MakeUnique<EventNameFilter>(std::move(whitelist)); | 500 new_filter = MakeUnique<EventNameFilter>(std::move(base_filter_config), |
| 501 std::move(whitelist)); | |
| 518 } else if (predicate_name == HeapProfilerEventFilter::kName) { | 502 } else if (predicate_name == HeapProfilerEventFilter::kName) { |
| 519 new_filter = MakeUnique<HeapProfilerEventFilter>(); | 503 new_filter = |
| 520 } else { | 504 MakeUnique<HeapProfilerEventFilter>(std::move(base_filter_config)); |
| 521 if (filter_factory_for_testing_) | 505 } else if (filter_factory_for_testing_) { |
| 522 new_filter = filter_factory_for_testing_(predicate_name); | 506 new_filter = filter_factory_for_testing_(predicate_name, |
| 523 CHECK(new_filter) << "Unknown trace filter " << predicate_name; | 507 std::move(base_filter_config)); |
| 524 } | 508 } |
| 525 g_category_group_filters.Get().push_back(std::move(new_filter)); | 509 CHECK(new_filter) << "Unknown trace filter " << predicate_name; |
| 510 EventFilterRegistry::RegisterFilter(std::move(new_filter)); | |
| 526 } | 511 } |
| 527 } | 512 } |
| 528 | 513 |
| 529 void TraceLog::UpdateSyntheticDelaysFromTraceConfig() { | 514 void TraceLog::UpdateSyntheticDelaysFromTraceConfig() { |
| 530 ResetTraceEventSyntheticDelays(); | 515 ResetTraceEventSyntheticDelays(); |
| 531 const TraceConfig::StringList& delays = | 516 const TraceConfig::StringList& delays = |
| 532 trace_config_.GetSyntheticDelayValues(); | 517 trace_config_.GetSyntheticDelayValues(); |
| 533 TraceConfig::StringList::const_iterator ci; | 518 TraceConfig::StringList::const_iterator ci; |
| 534 for (ci = delays.begin(); ci != delays.end(); ++ci) { | 519 for (ci = delays.begin(); ci != delays.end(); ++ci) { |
| 535 StringTokenizer tokens(*ci, ";"); | 520 StringTokenizer tokens(*ci, ";"); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 578 | 563 |
| 579 InternalTraceOptions old_options = trace_options(); | 564 InternalTraceOptions old_options = trace_options(); |
| 580 | 565 |
| 581 if (dispatching_to_observer_list_) { | 566 if (dispatching_to_observer_list_) { |
| 582 // TODO(ssid): Change to NOTREACHED after fixing crbug.com/625170. | 567 // TODO(ssid): Change to NOTREACHED after fixing crbug.com/625170. |
| 583 DLOG(ERROR) | 568 DLOG(ERROR) |
| 584 << "Cannot manipulate TraceLog::Enabled state from an observer."; | 569 << "Cannot manipulate TraceLog::Enabled state from an observer."; |
| 585 return; | 570 return; |
| 586 } | 571 } |
| 587 | 572 |
| 588 // Clear all filters from previous tracing session. These filters are not | 573 // Update trace config for recording. |
| 589 // cleared at the end of tracing because some threads which hit trace event | 574 const bool already_recording = (enabled_modes_ & RECORDING_MODE) != 0; |
| 590 // when disabling, could try to use the filters. | 575 if (modes_to_enable & RECORDING_MODE) { |
| 591 if (!enabled_modes_) | 576 // Save the current filter config (and restore below) in order to prevent |
| 592 g_category_group_filters.Get().clear(); | 577 // clobbering the filter section of the TraceConfig when enabling only |
| 578 // the recording mode. This is to ensure that GetCurrentTraceConfig() | |
| 579 // always returns a consistent snapshot of the current state. | |
| 580 std::unique_ptr<TraceConfig::EventFilters> saved_filters_config; | |
|
ssid
2016/12/12 04:50:18
I do not think this is required anymore. The Trace
| |
| 581 if (!(modes_to_enable & FILTERING_MODE)) { | |
| 582 saved_filters_config.reset( | |
| 583 new TraceConfig::EventFilters(trace_config_.event_filters())); | |
| 584 } | |
| 593 | 585 |
| 594 // Update trace config for recording. | |
| 595 const bool already_recording = enabled_modes_ & RECORDING_MODE; | |
| 596 if (modes_to_enable & RECORDING_MODE) { | |
| 597 if (already_recording) { | 586 if (already_recording) { |
| 598 // TODO(ssid): Stop suporting enabling of RECODING_MODE when already | 587 // TODO(ssid): Stop suporting enabling of RECODING_MODE when already |
| 599 // enabled crbug.com/625170. | 588 // enabled crbug.com/625170. |
| 600 DCHECK_EQ(new_options, old_options) << "Attempting to re-enable " | 589 DCHECK_EQ(new_options, old_options) << "Attempting to re-enable " |
| 601 "tracing with a different set " | 590 "tracing with a different set " |
| 602 "of options."; | 591 "of options."; |
| 603 trace_config_.Merge(trace_config); | 592 trace_config_.Merge(trace_config); |
| 604 } else { | 593 } else { |
| 605 trace_config_ = trace_config; | 594 trace_config_ = trace_config; |
| 606 } | 595 } |
| 596 | |
| 597 if (saved_filters_config) | |
| 598 trace_config_.SetEventFilters(*saved_filters_config); | |
| 607 } | 599 } |
| 608 | 600 |
| 609 // Update event filters. | 601 // Update event filters. |
| 610 if (modes_to_enable & FILTERING_MODE) { | 602 if (modes_to_enable & FILTERING_MODE) { |
| 611 DCHECK(!trace_config.event_filters().empty()) | 603 const bool already_filtering = (enabled_modes_ & FILTERING_MODE) != 0; |
| 612 << "Attempting to enable filtering without any filters"; | 604 CHECK(!already_filtering) << "Attempting to re-enable filtering"; |
| 613 DCHECK(enabled_event_filters_.empty()) << "Attempting to re-enable " | 605 CHECK(!trace_config.event_filters().empty()) |
| 614 "filtering when filters are " | 606 << "Attempting to enable filtering with an empty filter set"; |
| 615 "already enabled."; | 607 trace_config_.SetEventFilters(trace_config.event_filters()); |
| 616 | 608 CreateFiltersAndUpdateFilterRegistry(); |
| 617 // Use the given event filters only if filtering was not enabled. | 609 } else { |
| 618 if (enabled_event_filters_.empty()) | 610 CHECK(trace_config.event_filters().empty()) |
|
ssid
2016/12/12 04:50:18
Crashes in case of --enable-heap-profiling:
Tracin
| |
| 619 enabled_event_filters_ = trace_config.event_filters(); | 611 << "The trace config is specifying some filters but tracing is not " |
| 612 "being enabled for FILTERING_MODE."; | |
| 620 } | 613 } |
| 621 // Keep the |trace_config_| updated with only enabled filters in case anyone | |
| 622 // tries to read it using |GetCurrentTraceConfig| (even if filters are | |
| 623 // empty). | |
| 624 trace_config_.SetEventFilters(enabled_event_filters_); | |
| 625 | 614 |
| 626 enabled_modes_ |= modes_to_enable; | 615 enabled_modes_ |= modes_to_enable; |
| 627 UpdateCategoryRegistry(); | 616 UpdateCategoryRegistry(); |
| 628 | 617 |
| 629 // Do not notify observers or create trace buffer if only enabled for | 618 // Do not notify observers or create trace buffer if only enabled for |
| 630 // filtering or if recording was already enabled. | 619 // filtering or if recording was already enabled. |
| 631 if (!(modes_to_enable & RECORDING_MODE) || already_recording) | 620 if (!(modes_to_enable & RECORDING_MODE) || already_recording) |
| 632 return; | 621 return; |
| 633 | 622 |
| 634 if (new_options != old_options) { | 623 if (new_options != old_options) { |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 713 DLOG(ERROR) | 702 DLOG(ERROR) |
| 714 << "Cannot manipulate TraceLog::Enabled state from an observer."; | 703 << "Cannot manipulate TraceLog::Enabled state from an observer."; |
| 715 return; | 704 return; |
| 716 } | 705 } |
| 717 | 706 |
| 718 bool is_recording_mode_disabled = | 707 bool is_recording_mode_disabled = |
| 719 (enabled_modes_ & RECORDING_MODE) && (modes_to_disable & RECORDING_MODE); | 708 (enabled_modes_ & RECORDING_MODE) && (modes_to_disable & RECORDING_MODE); |
| 720 enabled_modes_ &= ~modes_to_disable; | 709 enabled_modes_ &= ~modes_to_disable; |
| 721 | 710 |
| 722 if (modes_to_disable & FILTERING_MODE) | 711 if (modes_to_disable & FILTERING_MODE) |
| 723 enabled_event_filters_.clear(); | 712 EventFilterRegistry::UnregisterAllFilters(); |
| 724 | 713 |
| 725 if (modes_to_disable & RECORDING_MODE) | 714 if (modes_to_disable & RECORDING_MODE) |
| 726 trace_config_.Clear(); | 715 trace_config_.Clear(); |
| 727 | 716 |
| 728 UpdateCategoryRegistry(); | 717 UpdateCategoryRegistry(); |
| 729 | 718 |
| 730 // Add metadata events and notify observers only if recording mode was | 719 // Add metadata events and notify observers only if recording mode was |
| 731 // disabled now. | 720 // disabled now. |
| 732 if (!is_recording_mode_disabled) | 721 if (!is_recording_mode_disabled) |
| 733 return; | 722 return; |
| (...skipping 988 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1722 } | 1711 } |
| 1723 | 1712 |
| 1724 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() { | 1713 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() { |
| 1725 if (*category_group_enabled_) { | 1714 if (*category_group_enabled_) { |
| 1726 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, name_, | 1715 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, name_, |
| 1727 event_handle_); | 1716 event_handle_); |
| 1728 } | 1717 } |
| 1729 } | 1718 } |
| 1730 | 1719 |
| 1731 } // namespace trace_event_internal | 1720 } // namespace trace_event_internal |
| OLD | NEW |