OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/debug/trace_event_impl.h" | 5 #include "base/debug/trace_event_impl.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/debug/leak_annotations.h" | 10 #include "base/debug/leak_annotations.h" |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 | 47 |
48 namespace base { | 48 namespace base { |
49 namespace debug { | 49 namespace debug { |
50 | 50 |
51 // Controls the number of trace events we will buffer in-memory | 51 // Controls the number of trace events we will buffer in-memory |
52 // before throwing them away. | 52 // before throwing them away. |
53 const size_t kTraceEventBufferSize = 500000; | 53 const size_t kTraceEventBufferSize = 500000; |
54 const size_t kTraceEventBatchSize = 1000; | 54 const size_t kTraceEventBatchSize = 1000; |
55 const size_t kTraceEventInitialBufferSize = 1024; | 55 const size_t kTraceEventInitialBufferSize = 1024; |
56 | 56 |
57 #define TRACE_EVENT_MAX_CATEGORIES 100 | 57 #define MAX_CATEGORY_GROUPS 100 |
58 | 58 |
59 namespace { | 59 namespace { |
60 | 60 |
61 // Parallel arrays g_categories and g_category_enabled are separate so that | 61 // Parallel arrays g_category_groups and g_category_group_enabled are separate |
62 // a pointer to a member of g_category_enabled can be easily converted to an | 62 // so that a pointer to a member of g_category_group_enabled can be easily |
63 // index into g_categories. This allows macros to deal only with char enabled | 63 // converted to an index into g_category_groups. This allows macros to deal |
64 // pointers from g_category_enabled, and we can convert internally to determine | 64 // only with char enabled pointers from g_category_group_enabled, and we can |
65 // the category name from the char enabled pointer. | 65 // convert internally to determine the category name from the char enabled |
66 const char* g_categories[TRACE_EVENT_MAX_CATEGORIES] = { | 66 // pointer. |
| 67 const char* g_category_groups[MAX_CATEGORY_GROUPS] = { |
67 "tracing already shutdown", | 68 "tracing already shutdown", |
68 "tracing categories exhausted; must increase TRACE_EVENT_MAX_CATEGORIES", | 69 "tracing categories exhausted; must increase MAX_CATEGORY_GROUPS", |
69 "__metadata", | 70 "__metadata", |
70 }; | 71 }; |
71 | 72 |
72 // The enabled flag is char instead of bool so that the API can be used from C. | 73 // The enabled flag is char instead of bool so that the API can be used from C. |
73 unsigned char g_category_enabled[TRACE_EVENT_MAX_CATEGORIES] = { 0 }; | 74 unsigned char g_category_group_enabled[MAX_CATEGORY_GROUPS] = { 0 }; |
74 const int g_category_already_shutdown = 0; | 75 const int g_category_already_shutdown = 0; |
75 const int g_category_categories_exhausted = 1; | 76 const int g_category_categories_exhausted = 1; |
76 const int g_category_metadata = 2; | 77 const int g_category_metadata = 2; |
77 int g_category_index = 3; // skip initial 3 categories | 78 int g_category_index = 3; // skip initial 3 categories |
78 | 79 |
79 // The name of the current thread. This is used to decide if the current | 80 // The name of the current thread. This is used to decide if the current |
80 // thread name has changed. We combine all the seen thread names into the | 81 // thread name has changed. We combine all the seen thread names into the |
81 // output name for the thread. | 82 // output name for the thread. |
82 LazyInstance<ThreadLocalPointer<const char> >::Leaky | 83 LazyInstance<ThreadLocalPointer<const char> >::Leaky |
83 g_current_thread_name = LAZY_INSTANCE_INITIALIZER; | 84 g_current_thread_name = LAZY_INSTANCE_INITIALIZER; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 bool IsFull() const OVERRIDE { | 132 bool IsFull() const OVERRIDE { |
132 return false; | 133 return false; |
133 } | 134 } |
134 | 135 |
135 size_t CountEnabledByName(const unsigned char* category, | 136 size_t CountEnabledByName(const unsigned char* category, |
136 const std::string& event_name) const OVERRIDE { | 137 const std::string& event_name) const OVERRIDE { |
137 size_t notify_count = 0; | 138 size_t notify_count = 0; |
138 size_t index = oldest_event_index_; | 139 size_t index = oldest_event_index_; |
139 while (index != unused_event_index_) { | 140 while (index != unused_event_index_) { |
140 const TraceEvent& event = GetEventAt(index); | 141 const TraceEvent& event = GetEventAt(index); |
141 if (category == event.category_enabled() && | 142 if (category == event.category_group_enabled() && |
142 strcmp(event_name.c_str(), event.name()) == 0) { | 143 strcmp(event_name.c_str(), event.name()) == 0) { |
143 ++notify_count; | 144 ++notify_count; |
144 } | 145 } |
145 index = NextIndex(index); | 146 index = NextIndex(index); |
146 } | 147 } |
147 return notify_count; | 148 return notify_count; |
148 } | 149 } |
149 | 150 |
150 const TraceEvent& GetEventAt(size_t index) const OVERRIDE { | 151 const TraceEvent& GetEventAt(size_t index) const OVERRIDE { |
151 DCHECK(index < logged_events_.size()); | 152 DCHECK(index < logged_events_.size()); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 | 194 |
194 bool IsFull() const OVERRIDE { | 195 bool IsFull() const OVERRIDE { |
195 return Size() >= kTraceEventBufferSize; | 196 return Size() >= kTraceEventBufferSize; |
196 } | 197 } |
197 | 198 |
198 size_t CountEnabledByName(const unsigned char* category, | 199 size_t CountEnabledByName(const unsigned char* category, |
199 const std::string& event_name) const OVERRIDE { | 200 const std::string& event_name) const OVERRIDE { |
200 size_t notify_count = 0; | 201 size_t notify_count = 0; |
201 for (size_t i = 0; i < Size(); i++) { | 202 for (size_t i = 0; i < Size(); i++) { |
202 const TraceEvent& event = GetEventAt(i); | 203 const TraceEvent& event = GetEventAt(i); |
203 if (category == event.category_enabled() && | 204 if (category == event.category_group_enabled() && |
204 strcmp(event_name.c_str(), event.name()) == 0) { | 205 strcmp(event_name.c_str(), event.name()) == 0) { |
205 ++notify_count; | 206 ++notify_count; |
206 } | 207 } |
207 } | 208 } |
208 return notify_count; | 209 return notify_count; |
209 } | 210 } |
210 | 211 |
211 const TraceEvent& GetEventAt(size_t index) const OVERRIDE { | 212 const TraceEvent& GetEventAt(size_t index) const OVERRIDE { |
212 DCHECK(index < logged_events_.size()); | 213 DCHECK(index < logged_events_.size()); |
213 return logged_events_[index]; | 214 return logged_events_[index]; |
(...skipping 30 matching lines...) Expand all Loading... |
244 DCHECK_LE(static_cast<int>(written), end - *buffer); | 245 DCHECK_LE(static_cast<int>(written), end - *buffer); |
245 *member = *buffer; | 246 *member = *buffer; |
246 *buffer += written; | 247 *buffer += written; |
247 } | 248 } |
248 } | 249 } |
249 | 250 |
250 } // namespace | 251 } // namespace |
251 | 252 |
252 TraceEvent::TraceEvent() | 253 TraceEvent::TraceEvent() |
253 : id_(0u), | 254 : id_(0u), |
254 category_enabled_(NULL), | 255 category_group_enabled_(NULL), |
255 name_(NULL), | 256 name_(NULL), |
256 thread_id_(0), | 257 thread_id_(0), |
257 phase_(TRACE_EVENT_PHASE_BEGIN), | 258 phase_(TRACE_EVENT_PHASE_BEGIN), |
258 flags_(0) { | 259 flags_(0) { |
259 arg_names_[0] = NULL; | 260 arg_names_[0] = NULL; |
260 arg_names_[1] = NULL; | 261 arg_names_[1] = NULL; |
261 memset(arg_values_, 0, sizeof(arg_values_)); | 262 memset(arg_values_, 0, sizeof(arg_values_)); |
262 } | 263 } |
263 | 264 |
264 TraceEvent::TraceEvent(int thread_id, | 265 TraceEvent::TraceEvent(int thread_id, |
265 TimeTicks timestamp, | 266 TimeTicks timestamp, |
266 char phase, | 267 char phase, |
267 const unsigned char* category_enabled, | 268 const unsigned char* category_group_enabled, |
268 const char* name, | 269 const char* name, |
269 unsigned long long id, | 270 unsigned long long id, |
270 int num_args, | 271 int num_args, |
271 const char** arg_names, | 272 const char** arg_names, |
272 const unsigned char* arg_types, | 273 const unsigned char* arg_types, |
273 const unsigned long long* arg_values, | 274 const unsigned long long* arg_values, |
274 unsigned char flags) | 275 unsigned char flags) |
275 : timestamp_(timestamp), | 276 : timestamp_(timestamp), |
276 id_(id), | 277 id_(id), |
277 category_enabled_(category_enabled), | 278 category_group_enabled_(category_group_enabled), |
278 name_(name), | 279 name_(name), |
279 thread_id_(thread_id), | 280 thread_id_(thread_id), |
280 phase_(phase), | 281 phase_(phase), |
281 flags_(flags) { | 282 flags_(flags) { |
282 // Clamp num_args since it may have been set by a third_party library. | 283 // Clamp num_args since it may have been set by a third_party library. |
283 num_args = (num_args > kTraceMaxNumArgs) ? kTraceMaxNumArgs : num_args; | 284 num_args = (num_args > kTraceMaxNumArgs) ? kTraceMaxNumArgs : num_args; |
284 int i = 0; | 285 int i = 0; |
285 for (; i < num_args; ++i) { | 286 for (; i < num_args; ++i) { |
286 arg_names_[i] = arg_names[i]; | 287 arg_names_[i] = arg_names[i]; |
287 arg_values_[i].as_uint = arg_values[i]; | 288 arg_values_[i].as_uint = arg_values[i]; |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
374 break; | 375 break; |
375 default: | 376 default: |
376 NOTREACHED() << "Don't know how to print this value"; | 377 NOTREACHED() << "Don't know how to print this value"; |
377 break; | 378 break; |
378 } | 379 } |
379 } | 380 } |
380 | 381 |
381 void TraceEvent::AppendAsJSON(std::string* out) const { | 382 void TraceEvent::AppendAsJSON(std::string* out) const { |
382 int64 time_int64 = timestamp_.ToInternalValue(); | 383 int64 time_int64 = timestamp_.ToInternalValue(); |
383 int process_id = TraceLog::GetInstance()->process_id(); | 384 int process_id = TraceLog::GetInstance()->process_id(); |
384 // Category name checked at category creation time. | 385 // Category group checked at category creation time. |
385 DCHECK(!strchr(name_, '"')); | 386 DCHECK(!strchr(name_, '"')); |
386 StringAppendF(out, | 387 StringAppendF(out, |
387 "{\"cat\":\"%s\",\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64 "," | 388 "{\"cat\":\"%s\",\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64 "," |
388 "\"ph\":\"%c\",\"name\":\"%s\",\"args\":{", | 389 "\"ph\":\"%c\",\"name\":\"%s\",\"args\":{", |
389 TraceLog::GetCategoryName(category_enabled_), | 390 TraceLog::GetCategoryGroupName(category_group_enabled_), |
390 process_id, | 391 process_id, |
391 thread_id_, | 392 thread_id_, |
392 time_int64, | 393 time_int64, |
393 phase_, | 394 phase_, |
394 name_); | 395 name_); |
395 | 396 |
396 // Output argument names and values, stop at first NULL argument name. | 397 // Output argument names and values, stop at first NULL argument name. |
397 for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) { | 398 for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) { |
398 if (i > 0) | 399 if (i > 0) |
399 *out += ","; | 400 *out += ","; |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
530 } | 531 } |
531 | 532 |
532 // static | 533 // static |
533 void TraceSamplingThread::DefaultSampleCallback(TraceBucketData* bucket_data) { | 534 void TraceSamplingThread::DefaultSampleCallback(TraceBucketData* bucket_data) { |
534 TRACE_EVENT_API_ATOMIC_WORD category_and_name = | 535 TRACE_EVENT_API_ATOMIC_WORD category_and_name = |
535 TRACE_EVENT_API_ATOMIC_LOAD(*bucket_data->bucket); | 536 TRACE_EVENT_API_ATOMIC_LOAD(*bucket_data->bucket); |
536 if (!category_and_name) | 537 if (!category_and_name) |
537 return; | 538 return; |
538 const char* const combined = | 539 const char* const combined = |
539 reinterpret_cast<const char* const>(category_and_name); | 540 reinterpret_cast<const char* const>(category_and_name); |
540 const char* category; | 541 const char* category_group; |
541 const char* name; | 542 const char* name; |
542 ExtractCategoryAndName(combined, &category, &name); | 543 ExtractCategoryAndName(combined, &category_group, &name); |
543 TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_SAMPLE, | 544 TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_SAMPLE, |
544 TraceLog::GetCategoryEnabled(category), | 545 TraceLog::GetCategoryGroupEnabled( |
| 546 category_group), |
545 name, | 547 name, |
546 0, | 548 0, |
547 0, | 549 0, |
548 NULL, | 550 NULL, |
549 NULL, | 551 NULL, |
550 NULL, | 552 NULL, |
551 0); | 553 0); |
552 } | 554 } |
553 | 555 |
554 void TraceSamplingThread::GetSamples() { | 556 void TraceSamplingThread::GetSamples() { |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
651 | 653 |
652 return static_cast<Options>(ret); | 654 return static_cast<Options>(ret); |
653 } | 655 } |
654 | 656 |
655 TraceLog::TraceLog() | 657 TraceLog::TraceLog() |
656 : enable_count_(0), | 658 : enable_count_(0), |
657 logged_events_(NULL), | 659 logged_events_(NULL), |
658 dispatching_to_observer_list_(false), | 660 dispatching_to_observer_list_(false), |
659 watch_category_(NULL), | 661 watch_category_(NULL), |
660 trace_options_(RECORD_UNTIL_FULL), | 662 trace_options_(RECORD_UNTIL_FULL), |
661 sampling_thread_handle_(0) { | 663 sampling_thread_handle_(0), |
| 664 category_filter_(CategoryFilter::kDefaultCategoryFilterString) { |
662 // Trace is enabled or disabled on one thread while other threads are | 665 // Trace is enabled or disabled on one thread while other threads are |
663 // accessing the enabled flag. We don't care whether edge-case events are | 666 // accessing the enabled flag. We don't care whether edge-case events are |
664 // traced or not, so we allow races on the enabled flag to keep the trace | 667 // traced or not, so we allow races on the enabled flag to keep the trace |
665 // macros fast. | 668 // macros fast. |
666 // TODO(jbates): ANNOTATE_BENIGN_RACE_SIZED crashes windows TSAN bots: | 669 // TODO(jbates): ANNOTATE_BENIGN_RACE_SIZED crashes windows TSAN bots: |
667 // ANNOTATE_BENIGN_RACE_SIZED(g_category_enabled, sizeof(g_category_enabled), | 670 // ANNOTATE_BENIGN_RACE_SIZED(g_category_group_enabled, |
668 // "trace_event category enabled"); | 671 // sizeof(g_category_group_enabled), |
669 for (int i = 0; i < TRACE_EVENT_MAX_CATEGORIES; ++i) { | 672 // "trace_event category enabled"); |
670 ANNOTATE_BENIGN_RACE(&g_category_enabled[i], | 673 for (int i = 0; i < MAX_CATEGORY_GROUPS; ++i) { |
| 674 ANNOTATE_BENIGN_RACE(&g_category_group_enabled[i], |
671 "trace_event category enabled"); | 675 "trace_event category enabled"); |
672 } | 676 } |
673 #if defined(OS_NACL) // NaCl shouldn't expose the process id. | 677 #if defined(OS_NACL) // NaCl shouldn't expose the process id. |
674 SetProcessID(0); | 678 SetProcessID(0); |
675 #else | 679 #else |
676 SetProcessID(static_cast<int>(GetCurrentProcId())); | 680 SetProcessID(static_cast<int>(GetCurrentProcId())); |
677 #endif | 681 #endif |
678 | 682 |
679 logged_events_.reset(GetTraceBuffer()); | 683 logged_events_.reset(GetTraceBuffer()); |
680 } | 684 } |
681 | 685 |
682 TraceLog::~TraceLog() { | 686 TraceLog::~TraceLog() { |
683 } | 687 } |
684 | 688 |
685 const unsigned char* TraceLog::GetCategoryEnabled(const char* name) { | 689 const unsigned char* TraceLog::GetCategoryGroupEnabled( |
| 690 const char* category_group) { |
686 TraceLog* tracelog = GetInstance(); | 691 TraceLog* tracelog = GetInstance(); |
687 if (!tracelog) { | 692 if (!tracelog) { |
688 DCHECK(!g_category_enabled[g_category_already_shutdown]); | 693 DCHECK(!g_category_group_enabled[g_category_already_shutdown]); |
689 return &g_category_enabled[g_category_already_shutdown]; | 694 return &g_category_group_enabled[g_category_already_shutdown]; |
690 } | 695 } |
691 return tracelog->GetCategoryEnabledInternal(name); | 696 return tracelog->GetCategoryGroupEnabledInternal(category_group); |
692 } | 697 } |
693 | 698 |
694 const char* TraceLog::GetCategoryName(const unsigned char* category_enabled) { | 699 const char* TraceLog::GetCategoryGroupName( |
695 // Calculate the index of the category by finding category_enabled in | 700 const unsigned char* category_group_enabled) { |
696 // g_category_enabled array. | 701 // Calculate the index of the category group by finding |
697 uintptr_t category_begin = reinterpret_cast<uintptr_t>(g_category_enabled); | 702 // category_group_enabled in g_category_group_enabled array. |
698 uintptr_t category_ptr = reinterpret_cast<uintptr_t>(category_enabled); | 703 uintptr_t category_begin = |
| 704 reinterpret_cast<uintptr_t>(g_category_group_enabled); |
| 705 uintptr_t category_ptr = reinterpret_cast<uintptr_t>(category_group_enabled); |
699 DCHECK(category_ptr >= category_begin && | 706 DCHECK(category_ptr >= category_begin && |
700 category_ptr < reinterpret_cast<uintptr_t>(g_category_enabled + | 707 category_ptr < reinterpret_cast<uintptr_t>( |
701 TRACE_EVENT_MAX_CATEGORIES)) << | 708 g_category_group_enabled + MAX_CATEGORY_GROUPS)) << |
702 "out of bounds category pointer"; | 709 "out of bounds category pointer"; |
703 uintptr_t category_index = | 710 uintptr_t category_index = |
704 (category_ptr - category_begin) / sizeof(g_category_enabled[0]); | 711 (category_ptr - category_begin) / sizeof(g_category_group_enabled[0]); |
705 return g_categories[category_index]; | 712 return g_category_groups[category_index]; |
706 } | 713 } |
707 | 714 |
708 static void EnableMatchingCategory(int category_index, | 715 void TraceLog::EnableIncludedCategoryGroup(int category_index) { |
709 const std::vector<std::string>& patterns, | 716 bool is_enabled = category_filter_.IsCategoryGroupEnabled( |
710 unsigned char matched_value, | 717 g_category_groups[category_index]); |
711 unsigned char unmatched_value) { | 718 g_category_group_enabled[category_index] = |
712 std::vector<std::string>::const_iterator ci = patterns.begin(); | 719 is_enabled ? TraceLog::CATEGORY_ENABLED : 0; |
713 bool is_match = false; | |
714 for (; ci != patterns.end(); ++ci) { | |
715 is_match = MatchPattern(g_categories[category_index], ci->c_str()); | |
716 if (is_match) | |
717 break; | |
718 } | |
719 g_category_enabled[category_index] = is_match ? | |
720 matched_value : unmatched_value; | |
721 } | 720 } |
722 | 721 |
723 // Enable/disable each category based on the category filters in |patterns|. | 722 void TraceLog::EnableIncludedCategoryGroups() { |
724 // If the category name matches one of the patterns, its enabled status is set | |
725 // to |matched_value|. Otherwise its enabled status is set to |unmatched_value|. | |
726 static void EnableMatchingCategories(const std::vector<std::string>& patterns, | |
727 unsigned char matched_value, | |
728 unsigned char unmatched_value) { | |
729 for (int i = 0; i < g_category_index; i++) | 723 for (int i = 0; i < g_category_index; i++) |
730 EnableMatchingCategory(i, patterns, matched_value, unmatched_value); | 724 EnableIncludedCategoryGroup(i); |
731 } | 725 } |
732 | 726 |
733 const unsigned char* TraceLog::GetCategoryEnabledInternal(const char* name) { | 727 const unsigned char* TraceLog::GetCategoryGroupEnabledInternal( |
| 728 const char* category_group) { |
| 729 DCHECK(!strchr(category_group, '"')) << |
| 730 "Category groups may not contain double quote"; |
734 AutoLock lock(lock_); | 731 AutoLock lock(lock_); |
735 DCHECK(!strchr(name, '"')) << "Category names may not contain double quote"; | |
736 | 732 |
737 unsigned char* category_enabled = NULL; | 733 unsigned char* category_group_enabled = NULL; |
738 // Search for pre-existing category matching this name | 734 // Search for pre-existing category group. |
739 for (int i = 0; i < g_category_index; i++) { | 735 for (int i = 0; i < g_category_index; i++) { |
740 if (strcmp(g_categories[i], name) == 0) { | 736 if (strcmp(g_category_groups[i], category_group) == 0) { |
741 category_enabled = &g_category_enabled[i]; | 737 category_group_enabled = &g_category_group_enabled[i]; |
742 break; | 738 break; |
743 } | 739 } |
744 } | 740 } |
745 | 741 |
746 if (!category_enabled) { | 742 if (!category_group_enabled) { |
747 // Create a new category | 743 // Create a new category group |
748 DCHECK(g_category_index < TRACE_EVENT_MAX_CATEGORIES) << | 744 DCHECK(g_category_index < MAX_CATEGORY_GROUPS) << |
749 "must increase TRACE_EVENT_MAX_CATEGORIES"; | 745 "must increase MAX_CATEGORY_GROUPS"; |
750 if (g_category_index < TRACE_EVENT_MAX_CATEGORIES) { | 746 if (g_category_index < MAX_CATEGORY_GROUPS) { |
751 int new_index = g_category_index++; | 747 int new_index = g_category_index++; |
752 // Don't hold on to the name pointer, so that we can create categories | 748 // Don't hold on to the category_group pointer, so that we can create |
753 // with strings not known at compile time (this is required by | 749 // category groups with strings not known at compile time (this is |
754 // SetWatchEvent). | 750 // required by SetWatchEvent). |
755 const char* new_name = strdup(name); | 751 const char* new_group = strdup(category_group); |
756 ANNOTATE_LEAKING_OBJECT_PTR(new_name); | 752 ANNOTATE_LEAKING_OBJECT_PTR(new_group); |
757 g_categories[new_index] = new_name; | 753 g_category_groups[new_index] = new_group; |
758 DCHECK(!g_category_enabled[new_index]); | 754 DCHECK(!g_category_group_enabled[new_index]); |
759 if (enable_count_) { | 755 if (enable_count_) { |
760 // Note that if both included and excluded_categories are empty, the | 756 // Note that if both included and excluded patterns in the |
761 // else clause below excludes nothing, thereby enabling this category. | 757 // CategoryFilter are empty, we exclude nothing, |
762 if (!included_categories_.empty()) { | 758 // thereby enabling this category group. |
763 EnableMatchingCategory(new_index, included_categories_, | 759 EnableIncludedCategoryGroup(new_index); |
764 CATEGORY_ENABLED, 0); | |
765 } else { | |
766 EnableMatchingCategory(new_index, excluded_categories_, | |
767 0, CATEGORY_ENABLED); | |
768 } | |
769 } else { | 760 } else { |
770 g_category_enabled[new_index] = 0; | 761 g_category_group_enabled[new_index] = 0; |
771 } | 762 } |
772 category_enabled = &g_category_enabled[new_index]; | 763 category_group_enabled = &g_category_group_enabled[new_index]; |
773 } else { | 764 } else { |
774 category_enabled = &g_category_enabled[g_category_categories_exhausted]; | 765 category_group_enabled = |
| 766 &g_category_group_enabled[g_category_categories_exhausted]; |
775 } | 767 } |
776 } | 768 } |
777 #if defined(OS_ANDROID) | 769 #if defined(OS_ANDROID) |
778 ApplyATraceEnabledFlag(category_enabled); | 770 ApplyATraceEnabledFlag(category_group_enabled); |
779 #endif | 771 #endif |
780 return category_enabled; | 772 return category_group_enabled; |
781 } | 773 } |
782 | 774 |
783 void TraceLog::GetKnownCategories(std::vector<std::string>* categories) { | 775 void TraceLog::GetKnownCategoryGroups( |
| 776 std::vector<std::string>* category_groups) { |
784 AutoLock lock(lock_); | 777 AutoLock lock(lock_); |
785 for (int i = 0; i < g_category_index; i++) | 778 for (int i = 0; i < g_category_index; i++) |
786 categories->push_back(g_categories[i]); | 779 category_groups->push_back(g_category_groups[i]); |
787 } | 780 } |
788 | 781 |
789 void TraceLog::SetEnabled(const std::vector<std::string>& included_categories, | 782 void TraceLog::SetEnabled(const CategoryFilter& category_filter, |
790 const std::vector<std::string>& excluded_categories, | |
791 Options options) { | 783 Options options) { |
792 AutoLock lock(lock_); | 784 AutoLock lock(lock_); |
793 | 785 |
794 if (enable_count_++ > 0) { | 786 if (enable_count_++ > 0) { |
795 if (options != trace_options_) { | 787 if (options != trace_options_) { |
796 DLOG(ERROR) << "Attemting to re-enable tracing with a different " | 788 DLOG(ERROR) << "Attemting to re-enable tracing with a different " |
797 << "set of options."; | 789 << "set of options."; |
798 } | 790 } |
799 | 791 |
800 // Tracing is already enabled, so just merge in enabled categories. | 792 // Tracing is already enabled, so just merge in enabled categories. |
801 // We only expand the set of enabled categories upon nested SetEnable(). | 793 // We only expand the set of enabled categories upon nested SetEnable(). |
802 if (!included_categories_.empty() && !included_categories.empty()) { | 794 if (category_filter_.HasIncludedPatterns() && |
803 included_categories_.insert(included_categories_.end(), | 795 category_filter.HasIncludedPatterns()) { |
804 included_categories.begin(), | 796 category_filter_.Merge(category_filter); |
805 included_categories.end()); | |
806 EnableMatchingCategories(included_categories_, CATEGORY_ENABLED, 0); | |
807 } else { | 797 } else { |
808 // If either old or new included categories are empty, allow all events. | 798 // If either old or new included categories are empty, allow all events. |
809 included_categories_.clear(); | 799 category_filter_.Clear(); |
810 excluded_categories_.clear(); | |
811 EnableMatchingCategories(excluded_categories_, 0, CATEGORY_ENABLED); | |
812 } | 800 } |
| 801 EnableIncludedCategoryGroups(); |
813 return; | 802 return; |
814 } | 803 } |
815 | 804 |
816 if (options != trace_options_) { | 805 if (options != trace_options_) { |
817 trace_options_ = options; | 806 trace_options_ = options; |
818 logged_events_.reset(GetTraceBuffer()); | 807 logged_events_.reset(GetTraceBuffer()); |
819 } | 808 } |
820 | 809 |
821 if (dispatching_to_observer_list_) { | 810 if (dispatching_to_observer_list_) { |
822 DLOG(ERROR) << | 811 DLOG(ERROR) << |
823 "Cannot manipulate TraceLog::Enabled state from an observer."; | 812 "Cannot manipulate TraceLog::Enabled state from an observer."; |
824 return; | 813 return; |
825 } | 814 } |
826 | 815 |
827 dispatching_to_observer_list_ = true; | 816 dispatching_to_observer_list_ = true; |
828 FOR_EACH_OBSERVER(EnabledStateChangedObserver, enabled_state_observer_list_, | 817 FOR_EACH_OBSERVER(EnabledStateChangedObserver, enabled_state_observer_list_, |
829 OnTraceLogWillEnable()); | 818 OnTraceLogWillEnable()); |
830 dispatching_to_observer_list_ = false; | 819 dispatching_to_observer_list_ = false; |
831 | 820 |
832 included_categories_ = included_categories; | 821 category_filter_ = CategoryFilter(category_filter); |
833 excluded_categories_ = excluded_categories; | 822 EnableIncludedCategoryGroups(); |
834 // Note that if both included and excluded_categories are empty, the else | |
835 // clause below excludes nothing, thereby enabling all categories. | |
836 if (!included_categories_.empty()) | |
837 EnableMatchingCategories(included_categories_, CATEGORY_ENABLED, 0); | |
838 else | |
839 EnableMatchingCategories(excluded_categories_, 0, CATEGORY_ENABLED); | |
840 | 823 |
841 if (options & ENABLE_SAMPLING) { | 824 if (options & ENABLE_SAMPLING) { |
842 sampling_thread_.reset(new TraceSamplingThread); | 825 sampling_thread_.reset(new TraceSamplingThread); |
843 sampling_thread_->RegisterSampleBucket( | 826 sampling_thread_->RegisterSampleBucket( |
844 &g_trace_state0, | 827 &g_trace_state0, |
845 "bucket0", | 828 "bucket0", |
846 Bind(&TraceSamplingThread::DefaultSampleCallback)); | 829 Bind(&TraceSamplingThread::DefaultSampleCallback)); |
847 sampling_thread_->RegisterSampleBucket( | 830 sampling_thread_->RegisterSampleBucket( |
848 &g_trace_state1, | 831 &g_trace_state1, |
849 "bucket1", | 832 "bucket1", |
850 Bind(&TraceSamplingThread::DefaultSampleCallback)); | 833 Bind(&TraceSamplingThread::DefaultSampleCallback)); |
851 sampling_thread_->RegisterSampleBucket( | 834 sampling_thread_->RegisterSampleBucket( |
852 &g_trace_state2, | 835 &g_trace_state2, |
853 "bucket2", | 836 "bucket2", |
854 Bind(&TraceSamplingThread::DefaultSampleCallback)); | 837 Bind(&TraceSamplingThread::DefaultSampleCallback)); |
855 if (!PlatformThread::Create( | 838 if (!PlatformThread::Create( |
856 0, sampling_thread_.get(), &sampling_thread_handle_)) { | 839 0, sampling_thread_.get(), &sampling_thread_handle_)) { |
857 DCHECK(false) << "failed to create thread"; | 840 DCHECK(false) << "failed to create thread"; |
858 } | 841 } |
859 } | 842 } |
860 } | 843 } |
861 | 844 |
862 void TraceLog::SetEnabled(const std::string& categories, Options options) { | 845 const CategoryFilter& TraceLog::GetCurrentCategoryFilter() { |
863 std::vector<std::string> included, excluded; | |
864 // Tokenize list of categories, delimited by ','. | |
865 StringTokenizer tokens(categories, ","); | |
866 while (tokens.GetNext()) { | |
867 bool is_included = true; | |
868 std::string category = tokens.token(); | |
869 // Excluded categories start with '-'. | |
870 if (category.at(0) == '-') { | |
871 // Remove '-' from category string. | |
872 category = category.substr(1); | |
873 is_included = false; | |
874 } | |
875 if (is_included) | |
876 included.push_back(category); | |
877 else | |
878 excluded.push_back(category); | |
879 } | |
880 SetEnabled(included, excluded, options); | |
881 } | |
882 | |
883 void TraceLog::GetEnabledTraceCategories( | |
884 std::vector<std::string>* included_out, | |
885 std::vector<std::string>* excluded_out) { | |
886 AutoLock lock(lock_); | 846 AutoLock lock(lock_); |
887 if (enable_count_) { | 847 DCHECK(enable_count_ > 0); |
888 *included_out = included_categories_; | 848 return category_filter_; |
889 *excluded_out = excluded_categories_; | |
890 } | |
891 } | 849 } |
892 | 850 |
893 void TraceLog::SetDisabled() { | 851 void TraceLog::SetDisabled() { |
894 AutoLock lock(lock_); | 852 AutoLock lock(lock_); |
895 DCHECK(enable_count_ > 0); | 853 DCHECK(enable_count_ > 0); |
896 if (--enable_count_ != 0) | 854 if (--enable_count_ != 0) |
897 return; | 855 return; |
898 | 856 |
899 if (dispatching_to_observer_list_) { | 857 if (dispatching_to_observer_list_) { |
900 DLOG(ERROR) | 858 DLOG(ERROR) |
(...skipping 10 matching lines...) Expand all Loading... |
911 sampling_thread_handle_ = 0; | 869 sampling_thread_handle_ = 0; |
912 sampling_thread_.reset(); | 870 sampling_thread_.reset(); |
913 } | 871 } |
914 | 872 |
915 dispatching_to_observer_list_ = true; | 873 dispatching_to_observer_list_ = true; |
916 FOR_EACH_OBSERVER(EnabledStateChangedObserver, | 874 FOR_EACH_OBSERVER(EnabledStateChangedObserver, |
917 enabled_state_observer_list_, | 875 enabled_state_observer_list_, |
918 OnTraceLogWillDisable()); | 876 OnTraceLogWillDisable()); |
919 dispatching_to_observer_list_ = false; | 877 dispatching_to_observer_list_ = false; |
920 | 878 |
921 included_categories_.clear(); | 879 category_filter_.Clear(); |
922 excluded_categories_.clear(); | |
923 watch_category_ = NULL; | 880 watch_category_ = NULL; |
924 watch_event_name_ = ""; | 881 watch_event_name_ = ""; |
925 for (int i = 0; i < g_category_index; i++) | 882 for (int i = 0; i < g_category_index; i++) |
926 g_category_enabled[i] = 0; | 883 g_category_group_enabled[i] = 0; |
927 AddThreadNameMetadataEvents(); | 884 AddThreadNameMetadataEvents(); |
928 } | 885 } |
929 | 886 |
930 void TraceLog::SetEnabled(bool enabled, Options options) { | |
931 if (enabled) | |
932 SetEnabled(std::vector<std::string>(), std::vector<std::string>(), options); | |
933 else | |
934 SetDisabled(); | |
935 } | |
936 | |
937 void TraceLog::AddEnabledStateObserver(EnabledStateChangedObserver* listener) { | 887 void TraceLog::AddEnabledStateObserver(EnabledStateChangedObserver* listener) { |
938 enabled_state_observer_list_.AddObserver(listener); | 888 enabled_state_observer_list_.AddObserver(listener); |
939 } | 889 } |
940 | 890 |
941 void TraceLog::RemoveEnabledStateObserver( | 891 void TraceLog::RemoveEnabledStateObserver( |
942 EnabledStateChangedObserver* listener) { | 892 EnabledStateChangedObserver* listener) { |
943 enabled_state_observer_list_.RemoveObserver(listener); | 893 enabled_state_observer_list_.RemoveObserver(listener); |
944 } | 894 } |
945 | 895 |
946 float TraceLog::GetBufferPercentFull() const { | 896 float TraceLog::GetBufferPercentFull() const { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
985 | 935 |
986 if (!previous_logged_events->HasMoreEvents()) | 936 if (!previous_logged_events->HasMoreEvents()) |
987 break; | 937 break; |
988 } | 938 } |
989 | 939 |
990 cb.Run(json_events_str_ptr); | 940 cb.Run(json_events_str_ptr); |
991 } | 941 } |
992 } | 942 } |
993 | 943 |
994 void TraceLog::AddTraceEvent(char phase, | 944 void TraceLog::AddTraceEvent(char phase, |
995 const unsigned char* category_enabled, | 945 const unsigned char* category_group_enabled, |
996 const char* name, | 946 const char* name, |
997 unsigned long long id, | 947 unsigned long long id, |
998 int num_args, | 948 int num_args, |
999 const char** arg_names, | 949 const char** arg_names, |
1000 const unsigned char* arg_types, | 950 const unsigned char* arg_types, |
1001 const unsigned long long* arg_values, | 951 const unsigned long long* arg_values, |
1002 unsigned char flags) { | 952 unsigned char flags) { |
1003 int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); | 953 int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); |
1004 base::TimeTicks now = base::TimeTicks::NowFromSystemTraceTime(); | 954 base::TimeTicks now = base::TimeTicks::NowFromSystemTraceTime(); |
1005 AddTraceEventWithThreadIdAndTimestamp(phase, category_enabled, name, id, | 955 AddTraceEventWithThreadIdAndTimestamp(phase, category_group_enabled, name, id, |
1006 thread_id, now, num_args, arg_names, | 956 thread_id, now, num_args, arg_names, |
1007 arg_types, arg_values, flags); | 957 arg_types, arg_values, flags); |
1008 } | 958 } |
1009 | 959 |
1010 void TraceLog::AddTraceEventWithThreadIdAndTimestamp( | 960 void TraceLog::AddTraceEventWithThreadIdAndTimestamp( |
1011 char phase, | 961 char phase, |
1012 const unsigned char* category_enabled, | 962 const unsigned char* category_group_enabled, |
1013 const char* name, | 963 const char* name, |
1014 unsigned long long id, | 964 unsigned long long id, |
1015 int thread_id, | 965 int thread_id, |
1016 const TimeTicks& timestamp, | 966 const TimeTicks& timestamp, |
1017 int num_args, | 967 int num_args, |
1018 const char** arg_names, | 968 const char** arg_names, |
1019 const unsigned char* arg_types, | 969 const unsigned char* arg_types, |
1020 const unsigned long long* arg_values, | 970 const unsigned long long* arg_values, |
1021 unsigned char flags) { | 971 unsigned char flags) { |
1022 DCHECK(name); | 972 DCHECK(name); |
1023 | 973 |
1024 if (flags & TRACE_EVENT_FLAG_MANGLE_ID) | 974 if (flags & TRACE_EVENT_FLAG_MANGLE_ID) |
1025 id ^= process_id_hash_; | 975 id ^= process_id_hash_; |
1026 | 976 |
1027 #if defined(OS_ANDROID) | 977 #if defined(OS_ANDROID) |
1028 SendToATrace(phase, GetCategoryName(category_enabled), name, id, | 978 SendToATrace(phase, GetCategoryGroupName(category__group_enabled), name, id, |
1029 num_args, arg_names, arg_types, arg_values, flags); | 979 num_args, arg_names, arg_types, arg_values, flags); |
1030 #endif | 980 #endif |
1031 | 981 |
1032 TimeTicks now = timestamp - time_offset_; | 982 TimeTicks now = timestamp - time_offset_; |
1033 EventCallback event_callback_copy; | 983 EventCallback event_callback_copy; |
1034 | 984 |
1035 NotificationHelper notifier(this); | 985 NotificationHelper notifier(this); |
1036 | 986 |
1037 { | 987 { |
1038 AutoLock lock(lock_); | 988 AutoLock lock(lock_); |
1039 if (*category_enabled != CATEGORY_ENABLED) | 989 if (*category_group_enabled != CATEGORY_ENABLED) |
1040 return; | 990 return; |
1041 if (logged_events_->IsFull()) | 991 if (logged_events_->IsFull()) |
1042 return; | 992 return; |
1043 | 993 |
1044 const char* new_name = ThreadIdNameManager::GetInstance()-> | 994 const char* new_name = ThreadIdNameManager::GetInstance()-> |
1045 GetName(thread_id); | 995 GetName(thread_id); |
1046 // Check if the thread name has been set or changed since the previous | 996 // Check if the thread name has been set or changed since the previous |
1047 // call (if any), but don't bother if the new name is empty. Note this will | 997 // call (if any), but don't bother if the new name is empty. Note this will |
1048 // not detect a thread name change within the same char* buffer address: we | 998 // not detect a thread name change within the same char* buffer address: we |
1049 // favor common case performance over corner case correctness. | 999 // favor common case performance over corner case correctness. |
(...skipping 15 matching lines...) Expand all Loading... |
1065 existing_names.end(), | 1015 existing_names.end(), |
1066 new_name) != existing_names.end(); | 1016 new_name) != existing_names.end(); |
1067 if (!found) { | 1017 if (!found) { |
1068 existing_name->second.push_back(','); | 1018 existing_name->second.push_back(','); |
1069 existing_name->second.append(new_name); | 1019 existing_name->second.append(new_name); |
1070 } | 1020 } |
1071 } | 1021 } |
1072 } | 1022 } |
1073 | 1023 |
1074 logged_events_->AddEvent(TraceEvent(thread_id, | 1024 logged_events_->AddEvent(TraceEvent(thread_id, |
1075 now, phase, category_enabled, name, id, | 1025 now, phase, category_group_enabled, name, id, |
1076 num_args, arg_names, arg_types, arg_values, | 1026 num_args, arg_names, arg_types, arg_values, |
1077 flags)); | 1027 flags)); |
1078 | 1028 |
1079 if (logged_events_->IsFull()) | 1029 if (logged_events_->IsFull()) |
1080 notifier.AddNotificationWhileLocked(TRACE_BUFFER_FULL); | 1030 notifier.AddNotificationWhileLocked(TRACE_BUFFER_FULL); |
1081 | 1031 |
1082 if (watch_category_ == category_enabled && watch_event_name_ == name) | 1032 if (watch_category_ == category_group_enabled && watch_event_name_ == name) |
1083 notifier.AddNotificationWhileLocked(EVENT_WATCH_NOTIFICATION); | 1033 notifier.AddNotificationWhileLocked(EVENT_WATCH_NOTIFICATION); |
1084 | 1034 |
1085 event_callback_copy = event_callback_; | 1035 event_callback_copy = event_callback_; |
1086 } // release lock | 1036 } // release lock |
1087 | 1037 |
1088 notifier.SendNotificationIfAny(); | 1038 notifier.SendNotificationIfAny(); |
1089 if (event_callback_copy != NULL) { | 1039 if (event_callback_copy != NULL) { |
1090 event_callback_copy(phase, category_enabled, name, id, | 1040 event_callback_copy(phase, category_group_enabled, name, id, |
1091 num_args, arg_names, arg_types, arg_values, | 1041 num_args, arg_names, arg_types, arg_values, |
1092 flags); | 1042 flags); |
1093 } | 1043 } |
1094 } | 1044 } |
1095 | 1045 |
1096 void TraceLog::AddTraceEventEtw(char phase, | 1046 void TraceLog::AddTraceEventEtw(char phase, |
1097 const char* name, | 1047 const char* name, |
1098 const void* id, | 1048 const void* id, |
1099 const char* extra) { | 1049 const char* extra) { |
1100 #if defined(OS_WIN) | 1050 #if defined(OS_WIN) |
(...skipping 10 matching lines...) Expand all Loading... |
1111 { | 1061 { |
1112 #if defined(OS_WIN) | 1062 #if defined(OS_WIN) |
1113 TraceEventETWProvider::Trace(name, phase, id, extra); | 1063 TraceEventETWProvider::Trace(name, phase, id, extra); |
1114 #endif | 1064 #endif |
1115 INTERNAL_TRACE_EVENT_ADD(phase, "ETW Trace Event", name, | 1065 INTERNAL_TRACE_EVENT_ADD(phase, "ETW Trace Event", name, |
1116 TRACE_EVENT_FLAG_COPY, "id", id, "extra", extra); | 1066 TRACE_EVENT_FLAG_COPY, "id", id, "extra", extra); |
1117 } | 1067 } |
1118 | 1068 |
1119 void TraceLog::SetWatchEvent(const std::string& category_name, | 1069 void TraceLog::SetWatchEvent(const std::string& category_name, |
1120 const std::string& event_name) { | 1070 const std::string& event_name) { |
1121 const unsigned char* category = GetCategoryEnabled(category_name.c_str()); | 1071 const unsigned char* category = GetCategoryGroupEnabled( |
| 1072 category_name.c_str()); |
1122 size_t notify_count = 0; | 1073 size_t notify_count = 0; |
1123 { | 1074 { |
1124 AutoLock lock(lock_); | 1075 AutoLock lock(lock_); |
1125 watch_category_ = category; | 1076 watch_category_ = category; |
1126 watch_event_name_ = event_name; | 1077 watch_event_name_ = event_name; |
1127 | 1078 |
1128 // First, search existing events for watch event because we want to catch | 1079 // First, search existing events for watch event because we want to catch |
1129 // it even if it has already occurred. | 1080 // it even if it has already occurred. |
1130 notify_count = logged_events_->CountEnabledByName(category, event_name); | 1081 notify_count = logged_events_->CountEnabledByName(category, event_name); |
1131 } // release lock | 1082 } // release lock |
(...skipping 20 matching lines...) Expand all Loading... |
1152 it != thread_names_.end(); | 1103 it != thread_names_.end(); |
1153 it++) { | 1104 it++) { |
1154 if (!it->second.empty()) { | 1105 if (!it->second.empty()) { |
1155 int num_args = 1; | 1106 int num_args = 1; |
1156 const char* arg_name = "name"; | 1107 const char* arg_name = "name"; |
1157 unsigned char arg_type; | 1108 unsigned char arg_type; |
1158 unsigned long long arg_value; | 1109 unsigned long long arg_value; |
1159 trace_event_internal::SetTraceValue(it->second, &arg_type, &arg_value); | 1110 trace_event_internal::SetTraceValue(it->second, &arg_type, &arg_value); |
1160 logged_events_->AddEvent(TraceEvent(it->first, | 1111 logged_events_->AddEvent(TraceEvent(it->first, |
1161 TimeTicks(), TRACE_EVENT_PHASE_METADATA, | 1112 TimeTicks(), TRACE_EVENT_PHASE_METADATA, |
1162 &g_category_enabled[g_category_metadata], | 1113 &g_category_group_enabled[g_category_metadata], |
1163 "thread_name", trace_event_internal::kNoEventId, | 1114 "thread_name", trace_event_internal::kNoEventId, |
1164 num_args, &arg_name, &arg_type, &arg_value, | 1115 num_args, &arg_name, &arg_type, &arg_value, |
1165 TRACE_EVENT_FLAG_NONE)); | 1116 TRACE_EVENT_FLAG_NONE)); |
1166 } | 1117 } |
1167 } | 1118 } |
1168 } | 1119 } |
1169 | 1120 |
1170 void TraceLog::InstallWaitableEventForSamplingTesting( | 1121 void TraceLog::InstallWaitableEventForSamplingTesting( |
1171 WaitableEvent* waitable_event) { | 1122 WaitableEvent* waitable_event) { |
1172 sampling_thread_->InstallWaitableEventForSamplingTesting(waitable_event); | 1123 sampling_thread_->InstallWaitableEventForSamplingTesting(waitable_event); |
(...skipping 14 matching lines...) Expand all Loading... |
1187 unsigned long long offset_basis = 14695981039346656037ull; | 1138 unsigned long long offset_basis = 14695981039346656037ull; |
1188 unsigned long long fnv_prime = 1099511628211ull; | 1139 unsigned long long fnv_prime = 1099511628211ull; |
1189 unsigned long long pid = static_cast<unsigned long long>(process_id_); | 1140 unsigned long long pid = static_cast<unsigned long long>(process_id_); |
1190 process_id_hash_ = (offset_basis ^ pid) * fnv_prime; | 1141 process_id_hash_ = (offset_basis ^ pid) * fnv_prime; |
1191 } | 1142 } |
1192 | 1143 |
1193 void TraceLog::SetTimeOffset(TimeDelta offset) { | 1144 void TraceLog::SetTimeOffset(TimeDelta offset) { |
1194 time_offset_ = offset; | 1145 time_offset_ = offset; |
1195 } | 1146 } |
1196 | 1147 |
| 1148 bool CategoryFilter::IsEmptyOrContainsLeadingOrTrailingWhitespace( |
| 1149 const std::string str) { |
| 1150 return str.empty() || |
| 1151 str.at(0) == ' ' || |
| 1152 str.at(str.length() - 1) == ' '; |
| 1153 } |
| 1154 |
| 1155 static bool DoesCategoryGroupContainCategory(const char* category_group, |
| 1156 const char* category) { |
| 1157 DCHECK(category); |
| 1158 CStringTokenizer category_group_tokens(category_group, |
| 1159 category_group + strlen(category_group), ","); |
| 1160 while (category_group_tokens.GetNext()) { |
| 1161 std::string category_group_token = category_group_tokens.token(); |
| 1162 // Don't allow empty tokens, nor tokens with leading or trailing space. |
| 1163 DCHECK(!CategoryFilter::IsEmptyOrContainsLeadingOrTrailingWhitespace( |
| 1164 category_group_token)) |
| 1165 << "Disallowed category string"; |
| 1166 if (MatchPattern(category_group_token.c_str(), category)) |
| 1167 return true; |
| 1168 } |
| 1169 return false; |
| 1170 } |
| 1171 |
| 1172 // Enable everything but debug and test categories by default. |
| 1173 const char* CategoryFilter::kDefaultCategoryFilterString = "-*Debug,-*Test"; |
| 1174 |
| 1175 CategoryFilter::CategoryFilter(const std::string& filter_string) { |
| 1176 if (!filter_string.empty()) |
| 1177 Initialize(filter_string); |
| 1178 else |
| 1179 Initialize(CategoryFilter::kDefaultCategoryFilterString); |
| 1180 } |
| 1181 |
| 1182 CategoryFilter::CategoryFilter(const CategoryFilter& cf) |
| 1183 : included_(cf.included_), |
| 1184 excluded_(cf.excluded_) { |
| 1185 } |
| 1186 |
| 1187 CategoryFilter& CategoryFilter::operator=(const CategoryFilter& rhs) { |
| 1188 if (this == &rhs) |
| 1189 return *this; |
| 1190 |
| 1191 included_ = rhs.included_; |
| 1192 excluded_ = rhs.excluded_; |
| 1193 return *this; |
| 1194 } |
| 1195 |
| 1196 void CategoryFilter::Initialize(const std::string& filter_string) { |
| 1197 // Tokenize list of categories, delimited by ','. |
| 1198 StringTokenizer tokens(filter_string, ","); |
| 1199 // Add each token to the appropriate list (included_,excluded_). |
| 1200 while (tokens.GetNext()) { |
| 1201 std::string category = tokens.token(); |
| 1202 // Ignore empty categories. |
| 1203 if (category.empty()) |
| 1204 continue; |
| 1205 // Excluded categories start with '-'. |
| 1206 if (category.at(0) == '-') { |
| 1207 // Remove '-' from category string. |
| 1208 category = category.substr(1); |
| 1209 excluded_.push_back(category); |
| 1210 } else { |
| 1211 included_.push_back(category); |
| 1212 } |
| 1213 } |
| 1214 } |
| 1215 |
| 1216 void CategoryFilter::WriteString(std::string* out, |
| 1217 bool included) const { |
| 1218 std::vector<std::string>::const_iterator ci; |
| 1219 std::vector<std::string>::const_iterator end; |
| 1220 if (included) { |
| 1221 ci = included_.begin(); |
| 1222 end = included_.end(); |
| 1223 } else { |
| 1224 ci = excluded_.begin(); |
| 1225 end = excluded_.end(); |
| 1226 } |
| 1227 |
| 1228 // Prepend commas for all excluded categories IF we have included categories. |
| 1229 bool prepend_comma_for_first_excluded = !included && !included_.empty(); |
| 1230 int token_cnt = 0; |
| 1231 for (; ci != end; ++ci) { |
| 1232 if (token_cnt > 0 || prepend_comma_for_first_excluded) |
| 1233 StringAppendF(out, ","); |
| 1234 StringAppendF(out, "%s%s", (included ? "" : "-"), ci->c_str()); |
| 1235 ++token_cnt; |
| 1236 } |
| 1237 } |
| 1238 |
| 1239 std::string CategoryFilter::ToString() const { |
| 1240 std::string filter_string; |
| 1241 WriteString(&filter_string, true); |
| 1242 WriteString(&filter_string, false); |
| 1243 |
| 1244 return filter_string; |
| 1245 } |
| 1246 |
| 1247 bool CategoryFilter::IsCategoryGroupEnabled( |
| 1248 const char* category_group_name) const { |
| 1249 // TraceLog should call this method only as part of enabling/disabling |
| 1250 // categories. |
| 1251 std::vector<std::string>::const_iterator ci = included_.begin(); |
| 1252 for (; ci != included_.end(); ++ci) { |
| 1253 if (DoesCategoryGroupContainCategory(category_group_name, ci->c_str())) |
| 1254 return true; |
| 1255 } |
| 1256 ci = excluded_.begin(); |
| 1257 for (; ci != excluded_.end(); ++ci) { |
| 1258 if (DoesCategoryGroupContainCategory(category_group_name, ci->c_str())) |
| 1259 return false; |
| 1260 } |
| 1261 // If the category group is not excluded, and there are no included patterns |
| 1262 // we consider this pattern enabled. |
| 1263 return included_.empty(); |
| 1264 } |
| 1265 |
| 1266 void CategoryFilter::Merge(const CategoryFilter& nested_filter) { |
| 1267 included_.insert(included_.end(), |
| 1268 nested_filter.included_.begin(), |
| 1269 nested_filter.included_.end()); |
| 1270 excluded_.insert(excluded_.end(), |
| 1271 nested_filter.excluded_.begin(), |
| 1272 nested_filter.excluded_.end()); |
| 1273 } |
| 1274 |
| 1275 bool CategoryFilter::HasIncludedPatterns() const { |
| 1276 return !included_.empty(); |
| 1277 } |
| 1278 |
| 1279 void CategoryFilter::Clear() { |
| 1280 included_.clear(); |
| 1281 excluded_.clear(); |
| 1282 } |
| 1283 |
1197 } // namespace debug | 1284 } // namespace debug |
1198 } // namespace base | 1285 } // namespace base |
1199 | 1286 |
1200 namespace trace_event_internal { | 1287 namespace trace_event_internal { |
1201 | 1288 |
1202 ScopedTrace::ScopedTrace( | 1289 ScopedTrace::ScopedTrace( |
1203 TRACE_EVENT_API_ATOMIC_WORD* event_uid, const char* name) { | 1290 TRACE_EVENT_API_ATOMIC_WORD* event_uid, const char* name) { |
1204 category_enabled_ = | 1291 category_enabled_ = |
1205 reinterpret_cast<const unsigned char*>(TRACE_EVENT_API_ATOMIC_LOAD( | 1292 reinterpret_cast<const unsigned char*>(TRACE_EVENT_API_ATOMIC_LOAD( |
1206 *event_uid)); | 1293 *event_uid)); |
1207 if (!category_enabled_) { | 1294 if (!category_enabled_) { |
1208 category_enabled_ = TRACE_EVENT_API_GET_CATEGORY_ENABLED("gpu"); | 1295 category_enabled_ = TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED("gpu"); |
1209 TRACE_EVENT_API_ATOMIC_STORE( | 1296 TRACE_EVENT_API_ATOMIC_STORE( |
1210 *event_uid, | 1297 *event_uid, |
1211 reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>(category_enabled_)); | 1298 reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>(category_enabled_)); |
1212 } | 1299 } |
1213 if (*category_enabled_) { | 1300 if (*category_enabled_) { |
1214 name_ = name; | 1301 name_ = name; |
1215 TRACE_EVENT_API_ADD_TRACE_EVENT( | 1302 TRACE_EVENT_API_ADD_TRACE_EVENT( |
1216 TRACE_EVENT_PHASE_BEGIN, // phase | 1303 TRACE_EVENT_PHASE_BEGIN, // phase |
1217 category_enabled_, // category enabled | 1304 category_enabled_, // category enabled |
1218 name, // name | 1305 name, // name |
(...skipping 18 matching lines...) Expand all Loading... |
1237 0, // num_args | 1324 0, // num_args |
1238 NULL, // arg_names | 1325 NULL, // arg_names |
1239 NULL, // arg_types | 1326 NULL, // arg_types |
1240 NULL, // arg_values | 1327 NULL, // arg_values |
1241 TRACE_EVENT_FLAG_NONE); // flags | 1328 TRACE_EVENT_FLAG_NONE); // flags |
1242 } | 1329 } |
1243 } | 1330 } |
1244 | 1331 |
1245 } // namespace trace_event_internal | 1332 } // namespace trace_event_internal |
1246 | 1333 |
OLD | NEW |