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 |