Index: base/trace_event/trace_log.cc |
diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc |
index 1a375d146a9eb20582e7948677029c93c6a1842f..25990eddceb49bc740bd8ac41af2f613924df5d1 100644 |
--- a/base/trace_event/trace_log.cc |
+++ b/base/trace_event/trace_log.cc |
@@ -16,6 +16,7 @@ |
#include "base/lazy_instance.h" |
#include "base/location.h" |
#include "base/macros.h" |
+#include "base/memory/ptr_util.h" |
#include "base/memory/ref_counted_memory.h" |
#include "base/memory/singleton.h" |
#include "base/process/process_metrics.h" |
@@ -102,6 +103,42 @@ const char* g_category_groups[MAX_CATEGORY_GROUPS] = { |
// The enabled flag is char instead of bool so that the API can be used from C. |
unsigned char g_category_group_enabled[MAX_CATEGORY_GROUPS] = {0}; |
+ |
+class TraceEventFilter { |
+ public: |
+ 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.
|
+ virtual bool FilterTraceEvent(const TraceEvent& trace_event) const = 0; |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(TraceEventFilter); |
+}; |
+ |
+class EventNameFilter : public TraceEventFilter { |
+ public: |
+ EventNameFilter(const base::DictionaryValue* filter_args) { |
+ const base::ListValue* whitelist = nullptr; |
+ if (filter_args->GetList("event_name_whitelist", &whitelist)) { |
+ for (size_t i = 0; i < whitelist->GetSize(); ++i) { |
+ std::string event_name; |
+ if (!whitelist->GetString(i, &event_name)) |
+ continue; |
+ |
+ whitelist_[event_name] = true; |
+ } |
+ } |
+ } |
+ |
+ bool FilterTraceEvent(const TraceEvent& trace_event) const override { |
+ 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.
|
+ } |
+ |
+ private: |
+ 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.
|
+}; |
+ |
+base::LazyInstance<std::list<std::unique_ptr<TraceEventFilter>>>::Leaky |
+ g_category_group_filter[MAX_CATEGORY_GROUPS] = {LAZY_INSTANCE_INITIALIZER}; |
+ |
// Indexes here have to match the g_category_groups array indexes above. |
const int g_category_already_shutdown = 1; |
const int g_category_categories_exhausted = 2; |
@@ -434,8 +471,8 @@ const unsigned char* TraceLog::GetCategoryGroupEnabled( |
return tracelog->GetCategoryGroupEnabledInternal(category_group); |
} |
-const char* TraceLog::GetCategoryGroupName( |
- const unsigned char* category_group_enabled) { |
+namespace { |
+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
|
// Calculate the index of the category group by finding |
// category_group_enabled in g_category_group_enabled array. |
uintptr_t category_begin = |
@@ -447,7 +484,20 @@ const char* TraceLog::GetCategoryGroupName( |
<< "out of bounds category pointer"; |
uintptr_t category_index = |
(category_ptr - category_begin) / sizeof(g_category_group_enabled[0]); |
- return g_category_groups[category_index]; |
+ |
+ return category_index; |
+} |
+} |
+ |
+const char* TraceLog::GetCategoryGroupName( |
+ const unsigned char* category_group_enabled) { |
+ return g_category_groups[GetCategoryIndex(category_group_enabled)]; |
+} |
+ |
+std::list<std::unique_ptr<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) { |
@@ -470,6 +520,28 @@ void TraceLog::UpdateCategoryGroupEnabledFlag(size_t category_index) { |
} |
#endif |
+ 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
|
+ g_category_group_filter[category_index].Get().clear(); |
+ |
+ for (const auto& category_event_filter : |
+ trace_config_.category_event_filters()) { |
+ if (category_event_filter.IsCategoryGroupEnabled(category_group)) { |
+ std::unique_ptr<TraceEventFilter> new_filter; |
+ |
+ if (category_event_filter.predicate_name() == |
+ "event_whitelist_predicate") { |
+ new_filter = |
+ WrapUnique(new EventNameFilter(category_event_filter.args())); |
+ } |
+ |
+ if (new_filter) { |
+ g_category_group_filter[category_index].Get().push_back( |
+ std::move(new_filter)); |
+ enabled_flag |= ENABLED_FOR_FILTERING; |
+ } |
+ } |
+ } |
+ |
g_category_group_enabled[category_index] = enabled_flag; |
} |
@@ -1247,7 +1319,39 @@ TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp( |
#endif // OS_WIN |
std::string console_message; |
- if (*category_group_enabled & ENABLED_FOR_RECORDING) { |
+ if (*category_group_enabled & ENABLED_FOR_FILTERING) { |
+ 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
|
+ new_trace_event->Initialize(thread_id, offset_event_timestamp, thread_now, |
+ phase, category_group_enabled, name, scope, id, |
+ bind_id, num_args, arg_names, arg_types, |
+ arg_values, convertable_values, flags); |
+ |
+ 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.
|
+ GetCategoryGroupFilter(category_group_enabled); |
+ 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.
|
+ DCHECK(!filter_list->empty()); |
+ |
+ bool should_add_event = false; |
+ for (const auto& trace_event_filter : *filter_list) { |
+ 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.
|
+ if (trace_event_filter.get()->FilterTraceEvent(*new_trace_event)) |
+ should_add_event = true; |
+ } |
+ |
+ if (should_add_event) { |
+ OptionalAutoLock lock(&lock_); |
+ |
+ TraceEvent* trace_event = NULL; |
+ if (thread_local_event_buffer) { |
+ trace_event = thread_local_event_buffer->AddTraceEvent(&handle); |
+ } else { |
+ 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
|
+ trace_event = AddEventToThreadSharedChunkWhileLocked(&handle, true); |
+ } |
+ |
+ trace_event->MoveFrom(std::move(new_trace_event)); |
+ } |
+ } else if (*category_group_enabled & ENABLED_FOR_RECORDING) { |
OptionalAutoLock lock(&lock_); |
TraceEvent* trace_event = NULL; |