| Index: base/trace_event/trace_log.cc
|
| diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc
|
| index 1a9af140551254bf6111c54ed4fb2a55d2e50121..866111a4d29620abac1835c6ddbb2ec43ce11070 100644
|
| --- a/base/trace_event/trace_log.cc
|
| +++ b/base/trace_event/trace_log.cc
|
| @@ -106,6 +106,15 @@ unsigned char g_category_group_enabled[MAX_CATEGORY_GROUPS] = {0};
|
|
|
| const char kEventNameWhitelist[] = "event_name_whitelist";
|
|
|
| +#define MAX_TRACE_EVENT_FILTERS 32
|
| +
|
| +// List of TraceEventFilter objects from the most recent tracing session.
|
| +base::LazyInstance<std::vector<std::unique_ptr<TraceLog::TraceEventFilter>>>::
|
| + Leaky g_category_group_filters = LAZY_INSTANCE_INITIALIZER;
|
| +
|
| +// Stores a bitmap of filters enabled for each category group.
|
| +uint32_t g_category_group_filters_enabled[MAX_CATEGORY_GROUPS] = {0};
|
| +
|
| class EventNameFilter : public TraceLog::TraceEventFilter {
|
| public:
|
| EventNameFilter(const base::DictionaryValue* filter_args) {
|
| @@ -129,10 +138,6 @@ class EventNameFilter : public TraceLog::TraceEventFilter {
|
| std::unordered_set<std::string> whitelist_;
|
| };
|
|
|
| -base::LazyInstance<
|
| - std::list<std::unique_ptr<TraceLog::TraceEventFilter>>>::Leaky
|
| - g_category_group_filter[MAX_CATEGORY_GROUPS] = {LAZY_INSTANCE_INITIALIZER};
|
| -
|
| // This filter is used to record trace events as pseudo stack for the heap
|
| // profiler. It does not filter-out any events from the trace, ie. the behavior
|
| // of trace events being added to TraceLog remains same: the events are added
|
| @@ -273,6 +278,20 @@ uintptr_t GetCategoryIndex(const unsigned char* category_group_enabled) {
|
| return category_index;
|
| }
|
|
|
| +template <typename Function>
|
| +void ForEachCategoryGroupFilter(const unsigned char* category_group_enabled,
|
| + Function filter_fn) {
|
| + uint32_t filter_bitmap = g_category_group_filters_enabled[GetCategoryIndex(
|
| + category_group_enabled)];
|
| + int index = 0;
|
| + while (filter_bitmap) {
|
| + if (filter_bitmap & 1 && g_category_group_filters.Get()[index])
|
| + filter_fn(g_category_group_filters.Get()[index].get());
|
| + filter_bitmap = filter_bitmap >> 1;
|
| + index++;
|
| + }
|
| +}
|
| +
|
| } // namespace
|
|
|
| // A helper class that allows the lock to be acquired in the middle of the scope
|
| @@ -542,12 +561,6 @@ const char* TraceLog::GetCategoryGroupName(
|
| return g_category_groups[GetCategoryIndex(category_group_enabled)];
|
| }
|
|
|
| -std::list<std::unique_ptr<TraceLog::TraceEventFilter>>* GetCategoryGroupFilter(
|
| - const unsigned char* category_group_enabled) {
|
| - return g_category_group_filter[GetCategoryIndex(category_group_enabled)]
|
| - .Pointer();
|
| -}
|
| -
|
| void TraceLog::UpdateCategoryGroupEnabledFlag(size_t category_index) {
|
| unsigned char enabled_flag = 0;
|
| const char* category_group = g_category_groups[category_index];
|
| @@ -574,43 +587,61 @@ void TraceLog::UpdateCategoryGroupEnabledFlag(size_t category_index) {
|
| if (mode_ == RECORDING_MODE && !strcmp(category_group, "__metadata"))
|
| enabled_flag |= ENABLED_FOR_RECORDING;
|
|
|
| - // Having a filter is an exceptional case, so we avoid
|
| - // the LazyInstance creation in the common case.
|
| - if (!(g_category_group_filter[category_index] == nullptr))
|
| - g_category_group_filter[category_index].Get().clear();
|
| -
|
| + uint32_t enabled_filters_bitmap = 0;
|
| + int index = 0;
|
| for (const auto& event_filter : trace_config_.event_filters()) {
|
| if (event_filter.IsCategoryGroupEnabled(category_group)) {
|
| - std::unique_ptr<TraceEventFilter> new_filter;
|
| -
|
| - if (event_filter.predicate_name() ==
|
| - TraceEventFilter::kEventWhitelistPredicate) {
|
| - new_filter = MakeUnique<EventNameFilter>(event_filter.filter_args());
|
| - } else if (event_filter.predicate_name() ==
|
| - TraceEventFilter::kHeapProfilerPredicate) {
|
| - new_filter = MakeUnique<HeapProfilerFilter>();
|
| - } else if (event_filter.predicate_name() == "testing_predicate") {
|
| - CHECK(g_trace_event_filter_constructor_for_testing);
|
| - new_filter = g_trace_event_filter_constructor_for_testing();
|
| - }
|
| -
|
| - if (new_filter) {
|
| - g_category_group_filter[category_index].Get().push_back(
|
| - std::move(new_filter));
|
| - enabled_flag |= ENABLED_FOR_FILTERING;
|
| - }
|
| + enabled_flag |= ENABLED_FOR_FILTERING;
|
| + DCHECK(g_category_group_filters.Get()[index]);
|
| + enabled_filters_bitmap |= 1 << index;
|
| + }
|
| + if (index++ >= MAX_TRACE_EVENT_FILTERS) {
|
| + NOTREACHED();
|
| + break;
|
| }
|
| }
|
| + g_category_group_filters_enabled[category_index] = enabled_filters_bitmap;
|
|
|
| g_category_group_enabled[category_index] = enabled_flag;
|
| }
|
|
|
| void TraceLog::UpdateCategoryGroupEnabledFlags() {
|
| + CreateFiltersForTraceConfig();
|
| size_t category_index = base::subtle::NoBarrier_Load(&g_category_index);
|
| for (size_t i = 0; i < category_index; i++)
|
| UpdateCategoryGroupEnabledFlag(i);
|
| }
|
|
|
| +void TraceLog::CreateFiltersForTraceConfig() {
|
| + // Filters were already added and tracing could be enabled. Filters list
|
| + // cannot be changed when trace events are using them.
|
| + if (g_category_group_filters.Get().size())
|
| + return;
|
| +
|
| + for (auto& event_filter : trace_config_.event_filters()) {
|
| + if (g_category_group_filters.Get().size() >= MAX_TRACE_EVENT_FILTERS) {
|
| + NOTREACHED()
|
| + << "Too many trace event filters installed in the current session";
|
| + break;
|
| + }
|
| +
|
| + std::unique_ptr<TraceEventFilter> new_filter;
|
| + if (event_filter.predicate_name() ==
|
| + TraceEventFilter::kEventWhitelistPredicate) {
|
| + new_filter = MakeUnique<EventNameFilter>(event_filter.filter_args());
|
| + } else if (event_filter.predicate_name() ==
|
| + TraceEventFilter::kHeapProfilerPredicate) {
|
| + new_filter = MakeUnique<HeapProfilerFilter>();
|
| + } else if (event_filter.predicate_name() == "testing_predicate") {
|
| + CHECK(g_trace_event_filter_constructor_for_testing);
|
| + new_filter = g_trace_event_filter_constructor_for_testing();
|
| + } else {
|
| + NOTREACHED();
|
| + }
|
| + g_category_group_filters.Get().push_back(std::move(new_filter));
|
| + }
|
| +}
|
| +
|
| void TraceLog::UpdateSyntheticDelaysFromTraceConfig() {
|
| ResetTraceEventSyntheticDelays();
|
| const TraceConfig::StringList& delays =
|
| @@ -724,6 +755,10 @@ void TraceLog::SetEnabled(const TraceConfig& trace_config, Mode mode) {
|
| DLOG(ERROR) << "Attempting to re-enable tracing with a different mode.";
|
| }
|
|
|
| + DCHECK(!trace_config.event_filters().size())
|
| + << "Adding new filters while tracing was already enabled is not "
|
| + "supported.";
|
| +
|
| trace_config_.Merge(trace_config);
|
| UpdateCategoryGroupEnabledFlags();
|
| return;
|
| @@ -744,6 +779,11 @@ void TraceLog::SetEnabled(const TraceConfig& trace_config, Mode mode) {
|
|
|
| num_traces_recorded_++;
|
|
|
| + // Clear all filters from previous tracing session. These filters are not
|
| + // cleared at the end of tracing because some threads which hit trace event
|
| + // when disabling, could try to use the filters.
|
| + g_category_group_filters.Get().clear();
|
| +
|
| trace_config_ = TraceConfig(trace_config);
|
| UpdateCategoryGroupEnabledFlags();
|
| UpdateSyntheticDelaysFromTraceConfig();
|
| @@ -1397,15 +1437,13 @@ TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp(
|
| bind_id, num_args, arg_names, arg_types,
|
| arg_values, convertable_values, flags);
|
|
|
| - auto filter_list = GetCategoryGroupFilter(category_group_enabled);
|
| - DCHECK(!filter_list->empty());
|
| -
|
| disabled_by_filters = true;
|
| - for (const auto& trace_event_filter : *filter_list) {
|
| - if (trace_event_filter->FilterTraceEvent(*new_trace_event))
|
| - disabled_by_filters = false;
|
| - }
|
| -
|
| + ForEachCategoryGroupFilter(
|
| + category_group_enabled, [&new_trace_event, &disabled_by_filters](
|
| + TraceEventFilter* trace_event_filter) {
|
| + if (trace_event_filter->FilterTraceEvent(*new_trace_event))
|
| + disabled_by_filters = false;
|
| + });
|
| if (!disabled_by_filters)
|
| filtered_trace_event = std::move(new_trace_event);
|
| }
|
| @@ -1556,13 +1594,12 @@ std::string TraceLog::EventToConsoleMessage(unsigned char phase,
|
| void TraceLog::EndFilteredEvent(const unsigned char* category_group_enabled,
|
| const char* name,
|
| TraceEventHandle handle) {
|
| - auto filter_list = GetCategoryGroupFilter(category_group_enabled);
|
| - DCHECK(!filter_list->empty());
|
| -
|
| - for (const auto& trace_event_filter : *filter_list) {
|
| - trace_event_filter->EndEvent(name,
|
| - GetCategoryGroupName(category_group_enabled));
|
| - }
|
| + const char* category_name = GetCategoryGroupName(category_group_enabled);
|
| + ForEachCategoryGroupFilter(
|
| + category_group_enabled,
|
| + [name, category_name](TraceEventFilter* trace_event_filter) {
|
| + trace_event_filter->EndEvent(name, category_name);
|
| + });
|
| }
|
|
|
| void TraceLog::UpdateTraceEventDuration(
|
| @@ -1634,6 +1671,9 @@ void TraceLog::UpdateTraceEventDuration(
|
| nullptr, nullptr, nullptr, TRACE_EVENT_FLAG_NONE);
|
| }
|
| }
|
| +
|
| + if (category_group_enabled_local & ENABLED_FOR_FILTERING)
|
| + EndFilteredEvent(category_group_enabled, name, handle);
|
| }
|
|
|
| void TraceLog::SetWatchEvent(const std::string& category_name,
|
|
|