Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(772)

Side by Side Diff: base/debug/trace_event_impl.cc

Issue 12150004: Category group support/Renamings. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Added destructor for CategoryFilter class per CQ failure. Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/debug/trace_event_impl.h ('k') | base/debug/trace_event_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 const int g_num_builtin_categories = 3; 78 const int g_num_builtin_categories = 3;
78 int g_category_index = g_num_builtin_categories; // Skip default categories. 79 int g_category_index = g_num_builtin_categories; // Skip default categories.
79 80
80 // The name of the current thread. This is used to decide if the current 81 // The name of the current thread. This is used to decide if the current
81 // thread name has changed. We combine all the seen thread names into the 82 // thread name has changed. We combine all the seen thread names into the
82 // output name for the thread. 83 // output name for the thread.
83 LazyInstance<ThreadLocalPointer<const char> >::Leaky 84 LazyInstance<ThreadLocalPointer<const char> >::Leaky
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 return false; 134 return false;
134 } 135 }
135 136
136 virtual size_t CountEnabledByName( 137 virtual size_t CountEnabledByName(
137 const unsigned char* category, 138 const unsigned char* category,
138 const std::string& event_name) const OVERRIDE { 139 const std::string& event_name) const OVERRIDE {
139 size_t notify_count = 0; 140 size_t notify_count = 0;
140 size_t index = oldest_event_index_; 141 size_t index = oldest_event_index_;
141 while (index != unused_event_index_) { 142 while (index != unused_event_index_) {
142 const TraceEvent& event = GetEventAt(index); 143 const TraceEvent& event = GetEventAt(index);
143 if (category == event.category_enabled() && 144 if (category == event.category_group_enabled() &&
144 strcmp(event_name.c_str(), event.name()) == 0) { 145 strcmp(event_name.c_str(), event.name()) == 0) {
145 ++notify_count; 146 ++notify_count;
146 } 147 }
147 index = NextIndex(index); 148 index = NextIndex(index);
148 } 149 }
149 return notify_count; 150 return notify_count;
150 } 151 }
151 152
152 virtual const TraceEvent& GetEventAt(size_t index) const OVERRIDE { 153 virtual const TraceEvent& GetEventAt(size_t index) const OVERRIDE {
153 DCHECK(index < logged_events_.size()); 154 DCHECK(index < logged_events_.size());
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 virtual bool IsFull() const OVERRIDE { 197 virtual bool IsFull() const OVERRIDE {
197 return Size() >= kTraceEventBufferSize; 198 return Size() >= kTraceEventBufferSize;
198 } 199 }
199 200
200 virtual size_t CountEnabledByName( 201 virtual size_t CountEnabledByName(
201 const unsigned char* category, 202 const unsigned char* category,
202 const std::string& event_name) const OVERRIDE { 203 const std::string& event_name) const OVERRIDE {
203 size_t notify_count = 0; 204 size_t notify_count = 0;
204 for (size_t i = 0; i < Size(); i++) { 205 for (size_t i = 0; i < Size(); i++) {
205 const TraceEvent& event = GetEventAt(i); 206 const TraceEvent& event = GetEventAt(i);
206 if (category == event.category_enabled() && 207 if (category == event.category_group_enabled() &&
207 strcmp(event_name.c_str(), event.name()) == 0) { 208 strcmp(event_name.c_str(), event.name()) == 0) {
208 ++notify_count; 209 ++notify_count;
209 } 210 }
210 } 211 }
211 return notify_count; 212 return notify_count;
212 } 213 }
213 214
214 virtual const TraceEvent& GetEventAt(size_t index) const OVERRIDE { 215 virtual const TraceEvent& GetEventAt(size_t index) const OVERRIDE {
215 DCHECK(index < logged_events_.size()); 216 DCHECK(index < logged_events_.size());
216 return logged_events_[index]; 217 return logged_events_[index];
(...skipping 30 matching lines...) Expand all
247 DCHECK_LE(static_cast<int>(written), end - *buffer); 248 DCHECK_LE(static_cast<int>(written), end - *buffer);
248 *member = *buffer; 249 *member = *buffer;
249 *buffer += written; 250 *buffer += written;
250 } 251 }
251 } 252 }
252 253
253 } // namespace 254 } // namespace
254 255
255 TraceEvent::TraceEvent() 256 TraceEvent::TraceEvent()
256 : id_(0u), 257 : id_(0u),
257 category_enabled_(NULL), 258 category_group_enabled_(NULL),
258 name_(NULL), 259 name_(NULL),
259 thread_id_(0), 260 thread_id_(0),
260 phase_(TRACE_EVENT_PHASE_BEGIN), 261 phase_(TRACE_EVENT_PHASE_BEGIN),
261 flags_(0) { 262 flags_(0) {
262 arg_names_[0] = NULL; 263 arg_names_[0] = NULL;
263 arg_names_[1] = NULL; 264 arg_names_[1] = NULL;
264 memset(arg_values_, 0, sizeof(arg_values_)); 265 memset(arg_values_, 0, sizeof(arg_values_));
265 } 266 }
266 267
267 TraceEvent::TraceEvent( 268 TraceEvent::TraceEvent(
268 int thread_id, 269 int thread_id,
269 TimeTicks timestamp, 270 TimeTicks timestamp,
270 char phase, 271 char phase,
271 const unsigned char* category_enabled, 272 const unsigned char* category_group_enabled,
272 const char* name, 273 const char* name,
273 unsigned long long id, 274 unsigned long long id,
274 int num_args, 275 int num_args,
275 const char** arg_names, 276 const char** arg_names,
276 const unsigned char* arg_types, 277 const unsigned char* arg_types,
277 const unsigned long long* arg_values, 278 const unsigned long long* arg_values,
278 scoped_ptr<ConvertableToTraceFormat> convertable_values[], 279 scoped_ptr<ConvertableToTraceFormat> convertable_values[],
279 unsigned char flags) 280 unsigned char flags)
280 : timestamp_(timestamp), 281 : timestamp_(timestamp),
281 id_(id), 282 id_(id),
282 category_enabled_(category_enabled), 283 category_group_enabled_(category_group_enabled),
283 name_(name), 284 name_(name),
284 thread_id_(thread_id), 285 thread_id_(thread_id),
285 phase_(phase), 286 phase_(phase),
286 flags_(flags) { 287 flags_(flags) {
287 // Clamp num_args since it may have been set by a third_party library. 288 // Clamp num_args since it may have been set by a third_party library.
288 num_args = (num_args > kTraceMaxNumArgs) ? kTraceMaxNumArgs : num_args; 289 num_args = (num_args > kTraceMaxNumArgs) ? kTraceMaxNumArgs : num_args;
289 int i = 0; 290 int i = 0;
290 for (; i < num_args; ++i) { 291 for (; i < num_args; ++i) {
291 arg_names_[i] = arg_names[i]; 292 arg_names_[i] = arg_names[i];
292 arg_types_[i] = arg_types[i]; 293 arg_types_[i] = arg_types[i];
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
345 if (arg_is_copy[i]) 346 if (arg_is_copy[i])
346 CopyTraceEventParameter(&ptr, &arg_values_[i].as_string, end); 347 CopyTraceEventParameter(&ptr, &arg_values_[i].as_string, end);
347 } 348 }
348 DCHECK_EQ(end, ptr) << "Overrun by " << ptr - end; 349 DCHECK_EQ(end, ptr) << "Overrun by " << ptr - end;
349 } 350 }
350 } 351 }
351 352
352 TraceEvent::TraceEvent(const TraceEvent& other) 353 TraceEvent::TraceEvent(const TraceEvent& other)
353 : timestamp_(other.timestamp_), 354 : timestamp_(other.timestamp_),
354 id_(other.id_), 355 id_(other.id_),
355 category_enabled_(other.category_enabled_), 356 category_group_enabled_(other.category_group_enabled_),
356 name_(other.name_), 357 name_(other.name_),
357 thread_id_(other.thread_id_), 358 thread_id_(other.thread_id_),
358 phase_(other.phase_), 359 phase_(other.phase_),
359 flags_(other.flags_) { 360 flags_(other.flags_) {
360 parameter_copy_storage_ = other.parameter_copy_storage_; 361 parameter_copy_storage_ = other.parameter_copy_storage_;
361 362
362 for (int i = 0; i < kTraceMaxNumArgs; ++i) { 363 for (int i = 0; i < kTraceMaxNumArgs; ++i) {
363 arg_values_[i] = other.arg_values_[i]; 364 arg_values_[i] = other.arg_values_[i];
364 arg_names_[i] = other.arg_names_[i]; 365 arg_names_[i] = other.arg_names_[i];
365 arg_types_[i] = other.arg_types_[i]; 366 arg_types_[i] = other.arg_types_[i];
366 367
367 if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE) { 368 if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE) {
368 convertable_values_[i].reset( 369 convertable_values_[i].reset(
369 const_cast<TraceEvent*>(&other)->convertable_values_[i].release()); 370 const_cast<TraceEvent*>(&other)->convertable_values_[i].release());
370 } else { 371 } else {
371 convertable_values_[i].reset(); 372 convertable_values_[i].reset();
372 } 373 }
373 } 374 }
374 } 375 }
375 376
376 TraceEvent& TraceEvent::operator=(const TraceEvent& other) { 377 TraceEvent& TraceEvent::operator=(const TraceEvent& other) {
377 if (this == &other) 378 if (this == &other)
378 return *this; 379 return *this;
379 380
380 timestamp_ = other.timestamp_; 381 timestamp_ = other.timestamp_;
381 id_ = other.id_; 382 id_ = other.id_;
382 category_enabled_ = other.category_enabled_; 383 category_group_enabled_ = other.category_group_enabled_;
383 name_ = other.name_; 384 name_ = other.name_;
384 parameter_copy_storage_ = other.parameter_copy_storage_; 385 parameter_copy_storage_ = other.parameter_copy_storage_;
385 thread_id_ = other.thread_id_; 386 thread_id_ = other.thread_id_;
386 phase_ = other.phase_; 387 phase_ = other.phase_;
387 flags_ = other.flags_; 388 flags_ = other.flags_;
388 389
389 for (int i = 0; i < kTraceMaxNumArgs; ++i) { 390 for (int i = 0; i < kTraceMaxNumArgs; ++i) {
390 arg_values_[i] = other.arg_values_[i]; 391 arg_values_[i] = other.arg_values_[i];
391 arg_names_[i] = other.arg_names_[i]; 392 arg_names_[i] = other.arg_names_[i];
392 arg_types_[i] = other.arg_types_[i]; 393 arg_types_[i] = other.arg_types_[i];
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 break; 446 break;
446 default: 447 default:
447 NOTREACHED() << "Don't know how to print this value"; 448 NOTREACHED() << "Don't know how to print this value";
448 break; 449 break;
449 } 450 }
450 } 451 }
451 452
452 void TraceEvent::AppendAsJSON(std::string* out) const { 453 void TraceEvent::AppendAsJSON(std::string* out) const {
453 int64 time_int64 = timestamp_.ToInternalValue(); 454 int64 time_int64 = timestamp_.ToInternalValue();
454 int process_id = TraceLog::GetInstance()->process_id(); 455 int process_id = TraceLog::GetInstance()->process_id();
455 // Category name checked at category creation time. 456 // Category group checked at category creation time.
456 DCHECK(!strchr(name_, '"')); 457 DCHECK(!strchr(name_, '"'));
457 StringAppendF(out, 458 StringAppendF(out,
458 "{\"cat\":\"%s\",\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64 "," 459 "{\"cat\":\"%s\",\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64 ","
459 "\"ph\":\"%c\",\"name\":\"%s\",\"args\":{", 460 "\"ph\":\"%c\",\"name\":\"%s\",\"args\":{",
460 TraceLog::GetCategoryName(category_enabled_), 461 TraceLog::GetCategoryGroupName(category_group_enabled_),
461 process_id, 462 process_id,
462 thread_id_, 463 thread_id_,
463 time_int64, 464 time_int64,
464 phase_, 465 phase_,
465 name_); 466 name_);
466 467
467 // Output argument names and values, stop at first NULL argument name. 468 // Output argument names and values, stop at first NULL argument name.
468 for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) { 469 for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) {
469 if (i > 0) 470 if (i > 0)
470 *out += ","; 471 *out += ",";
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
625 } 626 }
626 627
627 // static 628 // static
628 void TraceSamplingThread::DefaultSampleCallback(TraceBucketData* bucket_data) { 629 void TraceSamplingThread::DefaultSampleCallback(TraceBucketData* bucket_data) {
629 TRACE_EVENT_API_ATOMIC_WORD category_and_name = 630 TRACE_EVENT_API_ATOMIC_WORD category_and_name =
630 TRACE_EVENT_API_ATOMIC_LOAD(*bucket_data->bucket); 631 TRACE_EVENT_API_ATOMIC_LOAD(*bucket_data->bucket);
631 if (!category_and_name) 632 if (!category_and_name)
632 return; 633 return;
633 const char* const combined = 634 const char* const combined =
634 reinterpret_cast<const char* const>(category_and_name); 635 reinterpret_cast<const char* const>(category_and_name);
635 const char* category; 636 const char* category_group;
636 const char* name; 637 const char* name;
637 ExtractCategoryAndName(combined, &category, &name); 638 ExtractCategoryAndName(combined, &category_group, &name);
638 TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_SAMPLE, 639 TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_SAMPLE,
639 TraceLog::GetCategoryEnabled(category), 640 TraceLog::GetCategoryGroupEnabled(category_group),
640 name, 0, 0, NULL, NULL, NULL, NULL, 0); 641 name, 0, 0, NULL, NULL, NULL, NULL, 0);
641 } 642 }
642 643
643 void TraceSamplingThread::GetSamples() { 644 void TraceSamplingThread::GetSamples() {
644 for (size_t i = 0; i < sample_buckets_.size(); ++i) { 645 for (size_t i = 0; i < sample_buckets_.size(); ++i) {
645 TraceBucketData* bucket_data = &sample_buckets_[i]; 646 TraceBucketData* bucket_data = &sample_buckets_[i];
646 bucket_data->callback.Run(bucket_data); 647 bucket_data->callback.Run(bucket_data);
647 } 648 }
648 } 649 }
649 650
650 void TraceSamplingThread::RegisterSampleBucket( 651 void TraceSamplingThread::RegisterSampleBucket(
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
740 741
741 return static_cast<Options>(ret); 742 return static_cast<Options>(ret);
742 } 743 }
743 744
744 TraceLog::TraceLog() 745 TraceLog::TraceLog()
745 : enable_count_(0), 746 : enable_count_(0),
746 logged_events_(NULL), 747 logged_events_(NULL),
747 dispatching_to_observer_list_(false), 748 dispatching_to_observer_list_(false),
748 watch_category_(NULL), 749 watch_category_(NULL),
749 trace_options_(RECORD_UNTIL_FULL), 750 trace_options_(RECORD_UNTIL_FULL),
750 sampling_thread_handle_(0) { 751 sampling_thread_handle_(0),
752 category_filter_(CategoryFilter::kDefaultCategoryFilterString) {
751 // Trace is enabled or disabled on one thread while other threads are 753 // Trace is enabled or disabled on one thread while other threads are
752 // accessing the enabled flag. We don't care whether edge-case events are 754 // accessing the enabled flag. We don't care whether edge-case events are
753 // traced or not, so we allow races on the enabled flag to keep the trace 755 // traced or not, so we allow races on the enabled flag to keep the trace
754 // macros fast. 756 // macros fast.
755 // TODO(jbates): ANNOTATE_BENIGN_RACE_SIZED crashes windows TSAN bots: 757 // TODO(jbates): ANNOTATE_BENIGN_RACE_SIZED crashes windows TSAN bots:
756 // ANNOTATE_BENIGN_RACE_SIZED(g_category_enabled, sizeof(g_category_enabled), 758 // ANNOTATE_BENIGN_RACE_SIZED(g_category_group_enabled,
757 // "trace_event category enabled"); 759 // sizeof(g_category_group_enabled),
758 for (int i = 0; i < TRACE_EVENT_MAX_CATEGORIES; ++i) { 760 // "trace_event category enabled");
759 ANNOTATE_BENIGN_RACE(&g_category_enabled[i], 761 for (int i = 0; i < MAX_CATEGORY_GROUPS; ++i) {
762 ANNOTATE_BENIGN_RACE(&g_category_group_enabled[i],
760 "trace_event category enabled"); 763 "trace_event category enabled");
761 } 764 }
762 #if defined(OS_NACL) // NaCl shouldn't expose the process id. 765 #if defined(OS_NACL) // NaCl shouldn't expose the process id.
763 SetProcessID(0); 766 SetProcessID(0);
764 #else 767 #else
765 SetProcessID(static_cast<int>(GetCurrentProcId())); 768 SetProcessID(static_cast<int>(GetCurrentProcId()));
766 #endif 769 #endif
767 770
768 logged_events_.reset(GetTraceBuffer()); 771 logged_events_.reset(GetTraceBuffer());
769 } 772 }
770 773
771 TraceLog::~TraceLog() { 774 TraceLog::~TraceLog() {
772 } 775 }
773 776
774 const unsigned char* TraceLog::GetCategoryEnabled(const char* name) { 777 const unsigned char* TraceLog::GetCategoryGroupEnabled(
778 const char* category_group) {
775 TraceLog* tracelog = GetInstance(); 779 TraceLog* tracelog = GetInstance();
776 if (!tracelog) { 780 if (!tracelog) {
777 DCHECK(!g_category_enabled[g_category_already_shutdown]); 781 DCHECK(!g_category_group_enabled[g_category_already_shutdown]);
778 return &g_category_enabled[g_category_already_shutdown]; 782 return &g_category_group_enabled[g_category_already_shutdown];
779 } 783 }
780 return tracelog->GetCategoryEnabledInternal(name); 784 return tracelog->GetCategoryGroupEnabledInternal(category_group);
781 } 785 }
782 786
783 const char* TraceLog::GetCategoryName(const unsigned char* category_enabled) { 787 const char* TraceLog::GetCategoryGroupName(
784 // Calculate the index of the category by finding category_enabled in 788 const unsigned char* category_group_enabled) {
785 // g_category_enabled array. 789 // Calculate the index of the category group by finding
786 uintptr_t category_begin = reinterpret_cast<uintptr_t>(g_category_enabled); 790 // category_group_enabled in g_category_group_enabled array.
787 uintptr_t category_ptr = reinterpret_cast<uintptr_t>(category_enabled); 791 uintptr_t category_begin =
792 reinterpret_cast<uintptr_t>(g_category_group_enabled);
793 uintptr_t category_ptr = reinterpret_cast<uintptr_t>(category_group_enabled);
788 DCHECK(category_ptr >= category_begin && 794 DCHECK(category_ptr >= category_begin &&
789 category_ptr < reinterpret_cast<uintptr_t>(g_category_enabled + 795 category_ptr < reinterpret_cast<uintptr_t>(
790 TRACE_EVENT_MAX_CATEGORIES)) << 796 g_category_group_enabled + MAX_CATEGORY_GROUPS)) <<
791 "out of bounds category pointer"; 797 "out of bounds category pointer";
792 uintptr_t category_index = 798 uintptr_t category_index =
793 (category_ptr - category_begin) / sizeof(g_category_enabled[0]); 799 (category_ptr - category_begin) / sizeof(g_category_group_enabled[0]);
794 return g_categories[category_index]; 800 return g_category_groups[category_index];
795 } 801 }
796 802
797 static void EnableMatchingCategory(int category_index, 803 void TraceLog::EnableIncludedCategoryGroup(int category_index) {
798 const std::vector<std::string>& patterns, 804 bool is_enabled = category_filter_.IsCategoryGroupEnabled(
799 unsigned char matched_value, 805 g_category_groups[category_index]);
800 unsigned char unmatched_value) { 806 g_category_group_enabled[category_index] =
801 std::vector<std::string>::const_iterator ci = patterns.begin(); 807 is_enabled ? TraceLog::CATEGORY_ENABLED : 0;
802 bool is_match = false;
803 for (; ci != patterns.end(); ++ci) {
804 is_match = MatchPattern(g_categories[category_index], ci->c_str());
805 if (is_match)
806 break;
807 }
808 g_category_enabled[category_index] = is_match ?
809 matched_value : unmatched_value;
810 } 808 }
811 809
812 // Enable/disable each category based on the category filters in |patterns|. 810 void TraceLog::EnableIncludedCategoryGroups() {
813 // If the category name matches one of the patterns, its enabled status is set
814 // to |matched_value|. Otherwise its enabled status is set to |unmatched_value|.
815 static void EnableMatchingCategories(const std::vector<std::string>& patterns,
816 unsigned char matched_value,
817 unsigned char unmatched_value) {
818 for (int i = 0; i < g_category_index; i++) 811 for (int i = 0; i < g_category_index; i++)
819 EnableMatchingCategory(i, patterns, matched_value, unmatched_value); 812 EnableIncludedCategoryGroup(i);
820 } 813 }
821 814
822 const unsigned char* TraceLog::GetCategoryEnabledInternal(const char* name) { 815 const unsigned char* TraceLog::GetCategoryGroupEnabledInternal(
816 const char* category_group) {
817 DCHECK(!strchr(category_group, '"')) <<
818 "Category groups may not contain double quote";
823 AutoLock lock(lock_); 819 AutoLock lock(lock_);
824 DCHECK(!strchr(name, '"')) << "Category names may not contain double quote";
825 820
826 unsigned char* category_enabled = NULL; 821 unsigned char* category_group_enabled = NULL;
827 // Search for pre-existing category matching this name 822 // Search for pre-existing category group.
828 for (int i = 0; i < g_category_index; i++) { 823 for (int i = 0; i < g_category_index; i++) {
829 if (strcmp(g_categories[i], name) == 0) { 824 if (strcmp(g_category_groups[i], category_group) == 0) {
830 category_enabled = &g_category_enabled[i]; 825 category_group_enabled = &g_category_group_enabled[i];
831 break; 826 break;
832 } 827 }
833 } 828 }
834 829
835 if (!category_enabled) { 830 if (!category_group_enabled) {
836 // Create a new category 831 // Create a new category group
837 DCHECK(g_category_index < TRACE_EVENT_MAX_CATEGORIES) << 832 DCHECK(g_category_index < MAX_CATEGORY_GROUPS) <<
838 "must increase TRACE_EVENT_MAX_CATEGORIES"; 833 "must increase MAX_CATEGORY_GROUPS";
839 if (g_category_index < TRACE_EVENT_MAX_CATEGORIES) { 834 if (g_category_index < MAX_CATEGORY_GROUPS) {
840 int new_index = g_category_index++; 835 int new_index = g_category_index++;
841 // Don't hold on to the name pointer, so that we can create categories 836 // Don't hold on to the category_group pointer, so that we can create
842 // with strings not known at compile time (this is required by 837 // category groups with strings not known at compile time (this is
843 // SetWatchEvent). 838 // required by SetWatchEvent).
844 const char* new_name = strdup(name); 839 const char* new_group = strdup(category_group);
845 ANNOTATE_LEAKING_OBJECT_PTR(new_name); 840 ANNOTATE_LEAKING_OBJECT_PTR(new_group);
846 g_categories[new_index] = new_name; 841 g_category_groups[new_index] = new_group;
847 DCHECK(!g_category_enabled[new_index]); 842 DCHECK(!g_category_group_enabled[new_index]);
848 if (enable_count_) { 843 if (enable_count_) {
849 // Note that if both included and excluded_categories are empty, the 844 // Note that if both included and excluded patterns in the
850 // else clause below excludes nothing, thereby enabling this category. 845 // CategoryFilter are empty, we exclude nothing,
851 if (!included_categories_.empty()) { 846 // thereby enabling this category group.
852 EnableMatchingCategory(new_index, included_categories_, 847 EnableIncludedCategoryGroup(new_index);
853 CATEGORY_ENABLED, 0);
854 } else {
855 EnableMatchingCategory(new_index, excluded_categories_,
856 0, CATEGORY_ENABLED);
857 }
858 } else { 848 } else {
859 g_category_enabled[new_index] = 0; 849 g_category_group_enabled[new_index] = 0;
860 } 850 }
861 category_enabled = &g_category_enabled[new_index]; 851 category_group_enabled = &g_category_group_enabled[new_index];
862 } else { 852 } else {
863 category_enabled = &g_category_enabled[g_category_categories_exhausted]; 853 category_group_enabled =
854 &g_category_group_enabled[g_category_categories_exhausted];
864 } 855 }
865 } 856 }
866 #if defined(OS_ANDROID) 857 #if defined(OS_ANDROID)
867 ApplyATraceEnabledFlag(category_enabled); 858 ApplyATraceEnabledFlag(category_group_enabled);
868 #endif 859 #endif
869 return category_enabled; 860 return category_group_enabled;
870 } 861 }
871 862
872 void TraceLog::GetKnownCategories(std::vector<std::string>* categories) { 863 void TraceLog::GetKnownCategoryGroups(
864 std::vector<std::string>* category_groups) {
873 AutoLock lock(lock_); 865 AutoLock lock(lock_);
874 for (int i = g_num_builtin_categories; i < g_category_index; i++) 866 for (int i = 0; i < g_category_index; i++)
875 categories->push_back(g_categories[i]); 867 category_groups->push_back(g_category_groups[i]);
876 } 868 }
877 869
878 void TraceLog::SetEnabled(const std::vector<std::string>& included_categories, 870 void TraceLog::SetEnabled(const CategoryFilter& category_filter,
879 const std::vector<std::string>& excluded_categories,
880 Options options) { 871 Options options) {
881 AutoLock lock(lock_); 872 AutoLock lock(lock_);
882 873
883 if (enable_count_++ > 0) { 874 if (enable_count_++ > 0) {
884 if (options != trace_options_) { 875 if (options != trace_options_) {
885 DLOG(ERROR) << "Attemting to re-enable tracing with a different " 876 DLOG(ERROR) << "Attemting to re-enable tracing with a different "
886 << "set of options."; 877 << "set of options.";
887 } 878 }
888 879
889 // Tracing is already enabled, so just merge in enabled categories. 880 // Tracing is already enabled, so just merge in enabled categories.
890 // We only expand the set of enabled categories upon nested SetEnable(). 881 // We only expand the set of enabled categories upon nested SetEnable().
891 if (!included_categories_.empty() && !included_categories.empty()) { 882 if (category_filter_.HasIncludedPatterns() &&
892 included_categories_.insert(included_categories_.end(), 883 category_filter.HasIncludedPatterns()) {
893 included_categories.begin(), 884 category_filter_.Merge(category_filter);
894 included_categories.end());
895 EnableMatchingCategories(included_categories_, CATEGORY_ENABLED, 0);
896 } else { 885 } else {
897 // If either old or new included categories are empty, allow all events. 886 // If either old or new included categories are empty, allow all events.
898 included_categories_.clear(); 887 category_filter_.Clear();
899 excluded_categories_.clear();
900 EnableMatchingCategories(excluded_categories_, 0, CATEGORY_ENABLED);
901 } 888 }
889 EnableIncludedCategoryGroups();
902 return; 890 return;
903 } 891 }
904 892
905 if (options != trace_options_) { 893 if (options != trace_options_) {
906 trace_options_ = options; 894 trace_options_ = options;
907 logged_events_.reset(GetTraceBuffer()); 895 logged_events_.reset(GetTraceBuffer());
908 } 896 }
909 897
910 if (dispatching_to_observer_list_) { 898 if (dispatching_to_observer_list_) {
911 DLOG(ERROR) << 899 DLOG(ERROR) <<
912 "Cannot manipulate TraceLog::Enabled state from an observer."; 900 "Cannot manipulate TraceLog::Enabled state from an observer.";
913 return; 901 return;
914 } 902 }
915 903
916 dispatching_to_observer_list_ = true; 904 dispatching_to_observer_list_ = true;
917 FOR_EACH_OBSERVER(EnabledStateChangedObserver, enabled_state_observer_list_, 905 FOR_EACH_OBSERVER(EnabledStateChangedObserver, enabled_state_observer_list_,
918 OnTraceLogWillEnable()); 906 OnTraceLogWillEnable());
919 dispatching_to_observer_list_ = false; 907 dispatching_to_observer_list_ = false;
920 908
921 included_categories_ = included_categories; 909 category_filter_ = CategoryFilter(category_filter);
922 excluded_categories_ = excluded_categories; 910 EnableIncludedCategoryGroups();
923 // Note that if both included and excluded_categories are empty, the else
924 // clause below excludes nothing, thereby enabling all categories.
925 if (!included_categories_.empty())
926 EnableMatchingCategories(included_categories_, CATEGORY_ENABLED, 0);
927 else
928 EnableMatchingCategories(excluded_categories_, 0, CATEGORY_ENABLED);
929 911
930 if (options & ENABLE_SAMPLING) { 912 if (options & ENABLE_SAMPLING) {
931 sampling_thread_.reset(new TraceSamplingThread); 913 sampling_thread_.reset(new TraceSamplingThread);
932 sampling_thread_->RegisterSampleBucket( 914 sampling_thread_->RegisterSampleBucket(
933 &g_trace_state0, 915 &g_trace_state0,
934 "bucket0", 916 "bucket0",
935 Bind(&TraceSamplingThread::DefaultSampleCallback)); 917 Bind(&TraceSamplingThread::DefaultSampleCallback));
936 sampling_thread_->RegisterSampleBucket( 918 sampling_thread_->RegisterSampleBucket(
937 &g_trace_state1, 919 &g_trace_state1,
938 "bucket1", 920 "bucket1",
939 Bind(&TraceSamplingThread::DefaultSampleCallback)); 921 Bind(&TraceSamplingThread::DefaultSampleCallback));
940 sampling_thread_->RegisterSampleBucket( 922 sampling_thread_->RegisterSampleBucket(
941 &g_trace_state2, 923 &g_trace_state2,
942 "bucket2", 924 "bucket2",
943 Bind(&TraceSamplingThread::DefaultSampleCallback)); 925 Bind(&TraceSamplingThread::DefaultSampleCallback));
944 if (!PlatformThread::Create( 926 if (!PlatformThread::Create(
945 0, sampling_thread_.get(), &sampling_thread_handle_)) { 927 0, sampling_thread_.get(), &sampling_thread_handle_)) {
946 DCHECK(false) << "failed to create thread"; 928 DCHECK(false) << "failed to create thread";
947 } 929 }
948 } 930 }
949 } 931 }
950 932
951 void TraceLog::SetEnabled(const std::string& categories, Options options) { 933 const CategoryFilter& TraceLog::GetCurrentCategoryFilter() {
952 std::vector<std::string> included, excluded;
953 // Tokenize list of categories, delimited by ','.
954 StringTokenizer tokens(categories, ",");
955 while (tokens.GetNext()) {
956 bool is_included = true;
957 std::string category = tokens.token();
958 // Excluded categories start with '-'.
959 if (category.at(0) == '-') {
960 // Remove '-' from category string.
961 category = category.substr(1);
962 is_included = false;
963 }
964 if (is_included)
965 included.push_back(category);
966 else
967 excluded.push_back(category);
968 }
969 SetEnabled(included, excluded, options);
970 }
971
972 void TraceLog::GetEnabledTraceCategories(
973 std::vector<std::string>* included_out,
974 std::vector<std::string>* excluded_out) {
975 AutoLock lock(lock_); 934 AutoLock lock(lock_);
976 if (enable_count_) { 935 DCHECK(enable_count_ > 0);
977 *included_out = included_categories_; 936 return category_filter_;
978 *excluded_out = excluded_categories_;
979 }
980 } 937 }
981 938
982 void TraceLog::SetDisabled() { 939 void TraceLog::SetDisabled() {
983 AutoLock lock(lock_); 940 AutoLock lock(lock_);
984 DCHECK(enable_count_ > 0); 941 DCHECK(enable_count_ > 0);
985 if (--enable_count_ != 0) 942 if (--enable_count_ != 0)
986 return; 943 return;
987 944
988 if (dispatching_to_observer_list_) { 945 if (dispatching_to_observer_list_) {
989 DLOG(ERROR) 946 DLOG(ERROR)
(...skipping 10 matching lines...) Expand all
1000 sampling_thread_handle_ = 0; 957 sampling_thread_handle_ = 0;
1001 sampling_thread_.reset(); 958 sampling_thread_.reset();
1002 } 959 }
1003 960
1004 dispatching_to_observer_list_ = true; 961 dispatching_to_observer_list_ = true;
1005 FOR_EACH_OBSERVER(EnabledStateChangedObserver, 962 FOR_EACH_OBSERVER(EnabledStateChangedObserver,
1006 enabled_state_observer_list_, 963 enabled_state_observer_list_,
1007 OnTraceLogWillDisable()); 964 OnTraceLogWillDisable());
1008 dispatching_to_observer_list_ = false; 965 dispatching_to_observer_list_ = false;
1009 966
1010 included_categories_.clear(); 967 category_filter_.Clear();
1011 excluded_categories_.clear();
1012 watch_category_ = NULL; 968 watch_category_ = NULL;
1013 watch_event_name_ = ""; 969 watch_event_name_ = "";
1014 for (int i = 0; i < g_category_index; i++) 970 for (int i = 0; i < g_category_index; i++)
1015 g_category_enabled[i] = 0; 971 g_category_group_enabled[i] = 0;
1016 AddThreadNameMetadataEvents(); 972 AddThreadNameMetadataEvents();
1017 } 973 }
1018 974
1019 void TraceLog::SetEnabled(bool enabled, Options options) {
1020 if (enabled)
1021 SetEnabled(std::vector<std::string>(), std::vector<std::string>(), options);
1022 else
1023 SetDisabled();
1024 }
1025
1026 void TraceLog::AddEnabledStateObserver(EnabledStateChangedObserver* listener) { 975 void TraceLog::AddEnabledStateObserver(EnabledStateChangedObserver* listener) {
1027 enabled_state_observer_list_.AddObserver(listener); 976 enabled_state_observer_list_.AddObserver(listener);
1028 } 977 }
1029 978
1030 void TraceLog::RemoveEnabledStateObserver( 979 void TraceLog::RemoveEnabledStateObserver(
1031 EnabledStateChangedObserver* listener) { 980 EnabledStateChangedObserver* listener) {
1032 enabled_state_observer_list_.RemoveObserver(listener); 981 enabled_state_observer_list_.RemoveObserver(listener);
1033 } 982 }
1034 983
1035 float TraceLog::GetBufferPercentFull() const { 984 float TraceLog::GetBufferPercentFull() const {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1075 if (!previous_logged_events->HasMoreEvents()) 1024 if (!previous_logged_events->HasMoreEvents())
1076 break; 1025 break;
1077 } 1026 }
1078 1027
1079 cb.Run(json_events_str_ptr); 1028 cb.Run(json_events_str_ptr);
1080 } 1029 }
1081 } 1030 }
1082 1031
1083 void TraceLog::AddTraceEvent( 1032 void TraceLog::AddTraceEvent(
1084 char phase, 1033 char phase,
1085 const unsigned char* category_enabled, 1034 const unsigned char* category_group_enabled,
1086 const char* name, 1035 const char* name,
1087 unsigned long long id, 1036 unsigned long long id,
1088 int num_args, 1037 int num_args,
1089 const char** arg_names, 1038 const char** arg_names,
1090 const unsigned char* arg_types, 1039 const unsigned char* arg_types,
1091 const unsigned long long* arg_values, 1040 const unsigned long long* arg_values,
1092 scoped_ptr<ConvertableToTraceFormat> convertable_values[], 1041 scoped_ptr<ConvertableToTraceFormat> convertable_values[],
1093 unsigned char flags) { 1042 unsigned char flags) {
1094 int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); 1043 int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
1095 base::TimeTicks now = base::TimeTicks::NowFromSystemTraceTime(); 1044 base::TimeTicks now = base::TimeTicks::NowFromSystemTraceTime();
1096 AddTraceEventWithThreadIdAndTimestamp(phase, category_enabled, name, id, 1045 AddTraceEventWithThreadIdAndTimestamp(phase, category_group_enabled, name, id,
1097 thread_id, now, num_args, arg_names, 1046 thread_id, now, num_args, arg_names,
1098 arg_types, arg_values, 1047 arg_types, arg_values,
1099 convertable_values, flags); 1048 convertable_values, flags);
1100 } 1049 }
1101 1050
1102 void TraceLog::AddTraceEventWithThreadIdAndTimestamp( 1051 void TraceLog::AddTraceEventWithThreadIdAndTimestamp(
1103 char phase, 1052 char phase,
1104 const unsigned char* category_enabled, 1053 const unsigned char* category_group_enabled,
1105 const char* name, 1054 const char* name,
1106 unsigned long long id, 1055 unsigned long long id,
1107 int thread_id, 1056 int thread_id,
1108 const TimeTicks& timestamp, 1057 const TimeTicks& timestamp,
1109 int num_args, 1058 int num_args,
1110 const char** arg_names, 1059 const char** arg_names,
1111 const unsigned char* arg_types, 1060 const unsigned char* arg_types,
1112 const unsigned long long* arg_values, 1061 const unsigned long long* arg_values,
1113 scoped_ptr<ConvertableToTraceFormat> convertable_values[], 1062 scoped_ptr<ConvertableToTraceFormat> convertable_values[],
1114 unsigned char flags) { 1063 unsigned char flags) {
1115 DCHECK(name); 1064 DCHECK(name);
1116 1065
1117 if (flags & TRACE_EVENT_FLAG_MANGLE_ID) 1066 if (flags & TRACE_EVENT_FLAG_MANGLE_ID)
1118 id ^= process_id_hash_; 1067 id ^= process_id_hash_;
1119 1068
1120 #if defined(OS_ANDROID) 1069 #if defined(OS_ANDROID)
1121 SendToATrace(phase, GetCategoryName(category_enabled), name, id, 1070 SendToATrace(phase, GetCategoryGroupName(category_group_enabled), name, id,
1122 num_args, arg_names, arg_types, arg_values, flags); 1071 num_args, arg_names, arg_types, arg_values, flags);
1123 #endif 1072 #endif
1124 1073
1125 TimeTicks now = timestamp - time_offset_; 1074 TimeTicks now = timestamp - time_offset_;
1126 EventCallback event_callback_copy; 1075 EventCallback event_callback_copy;
1127 1076
1128 NotificationHelper notifier(this); 1077 NotificationHelper notifier(this);
1129 1078
1130 { 1079 {
1131 AutoLock lock(lock_); 1080 AutoLock lock(lock_);
1132 if (*category_enabled != CATEGORY_ENABLED) 1081 if (*category_group_enabled != CATEGORY_ENABLED)
1133 return; 1082 return;
1134 if (logged_events_->IsFull()) 1083 if (logged_events_->IsFull())
1135 return; 1084 return;
1136 1085
1137 const char* new_name = ThreadIdNameManager::GetInstance()-> 1086 const char* new_name = ThreadIdNameManager::GetInstance()->
1138 GetName(thread_id); 1087 GetName(thread_id);
1139 // Check if the thread name has been set or changed since the previous 1088 // Check if the thread name has been set or changed since the previous
1140 // call (if any), but don't bother if the new name is empty. Note this will 1089 // call (if any), but don't bother if the new name is empty. Note this will
1141 // not detect a thread name change within the same char* buffer address: we 1090 // not detect a thread name change within the same char* buffer address: we
1142 // favor common case performance over corner case correctness. 1091 // favor common case performance over corner case correctness.
(...skipping 15 matching lines...) Expand all
1158 existing_names.end(), 1107 existing_names.end(),
1159 new_name) != existing_names.end(); 1108 new_name) != existing_names.end();
1160 if (!found) { 1109 if (!found) {
1161 existing_name->second.push_back(','); 1110 existing_name->second.push_back(',');
1162 existing_name->second.append(new_name); 1111 existing_name->second.append(new_name);
1163 } 1112 }
1164 } 1113 }
1165 } 1114 }
1166 1115
1167 logged_events_->AddEvent(TraceEvent(thread_id, 1116 logged_events_->AddEvent(TraceEvent(thread_id,
1168 now, phase, category_enabled, name, id, 1117 now, phase, category_group_enabled, name, id,
1169 num_args, arg_names, arg_types, arg_values, 1118 num_args, arg_names, arg_types, arg_values,
1170 convertable_values, flags)); 1119 convertable_values, flags));
1171 1120
1172 if (logged_events_->IsFull()) 1121 if (logged_events_->IsFull())
1173 notifier.AddNotificationWhileLocked(TRACE_BUFFER_FULL); 1122 notifier.AddNotificationWhileLocked(TRACE_BUFFER_FULL);
1174 1123
1175 if (watch_category_ == category_enabled && watch_event_name_ == name) 1124 if (watch_category_ == category_group_enabled && watch_event_name_ == name)
1176 notifier.AddNotificationWhileLocked(EVENT_WATCH_NOTIFICATION); 1125 notifier.AddNotificationWhileLocked(EVENT_WATCH_NOTIFICATION);
1177 1126
1178 event_callback_copy = event_callback_; 1127 event_callback_copy = event_callback_;
1179 } // release lock 1128 } // release lock
1180 1129
1181 notifier.SendNotificationIfAny(); 1130 notifier.SendNotificationIfAny();
1182 if (event_callback_copy != NULL) { 1131 if (event_callback_copy != NULL) {
1183 event_callback_copy(phase, category_enabled, name, id, 1132 event_callback_copy(phase, category_group_enabled, name, id,
1184 num_args, arg_names, arg_types, arg_values, 1133 num_args, arg_names, arg_types, arg_values,
1185 flags); 1134 flags);
1186 } 1135 }
1187 } 1136 }
1188 1137
1189 void TraceLog::AddTraceEventEtw(char phase, 1138 void TraceLog::AddTraceEventEtw(char phase,
1190 const char* name, 1139 const char* name,
1191 const void* id, 1140 const void* id,
1192 const char* extra) { 1141 const char* extra) {
1193 #if defined(OS_WIN) 1142 #if defined(OS_WIN)
(...skipping 10 matching lines...) Expand all
1204 { 1153 {
1205 #if defined(OS_WIN) 1154 #if defined(OS_WIN)
1206 TraceEventETWProvider::Trace(name, phase, id, extra); 1155 TraceEventETWProvider::Trace(name, phase, id, extra);
1207 #endif 1156 #endif
1208 INTERNAL_TRACE_EVENT_ADD(phase, "ETW Trace Event", name, 1157 INTERNAL_TRACE_EVENT_ADD(phase, "ETW Trace Event", name,
1209 TRACE_EVENT_FLAG_COPY, "id", id, "extra", extra); 1158 TRACE_EVENT_FLAG_COPY, "id", id, "extra", extra);
1210 } 1159 }
1211 1160
1212 void TraceLog::SetWatchEvent(const std::string& category_name, 1161 void TraceLog::SetWatchEvent(const std::string& category_name,
1213 const std::string& event_name) { 1162 const std::string& event_name) {
1214 const unsigned char* category = GetCategoryEnabled(category_name.c_str()); 1163 const unsigned char* category = GetCategoryGroupEnabled(
1164 category_name.c_str());
1215 size_t notify_count = 0; 1165 size_t notify_count = 0;
1216 { 1166 {
1217 AutoLock lock(lock_); 1167 AutoLock lock(lock_);
1218 watch_category_ = category; 1168 watch_category_ = category;
1219 watch_event_name_ = event_name; 1169 watch_event_name_ = event_name;
1220 1170
1221 // First, search existing events for watch event because we want to catch 1171 // First, search existing events for watch event because we want to catch
1222 // it even if it has already occurred. 1172 // it even if it has already occurred.
1223 notify_count = logged_events_->CountEnabledByName(category, event_name); 1173 notify_count = logged_events_->CountEnabledByName(category, event_name);
1224 } // release lock 1174 } // release lock
(...skipping 20 matching lines...) Expand all
1245 it != thread_names_.end(); 1195 it != thread_names_.end();
1246 it++) { 1196 it++) {
1247 if (!it->second.empty()) { 1197 if (!it->second.empty()) {
1248 int num_args = 1; 1198 int num_args = 1;
1249 const char* arg_name = "name"; 1199 const char* arg_name = "name";
1250 unsigned char arg_type; 1200 unsigned char arg_type;
1251 unsigned long long arg_value; 1201 unsigned long long arg_value;
1252 trace_event_internal::SetTraceValue(it->second, &arg_type, &arg_value); 1202 trace_event_internal::SetTraceValue(it->second, &arg_type, &arg_value);
1253 logged_events_->AddEvent(TraceEvent(it->first, 1203 logged_events_->AddEvent(TraceEvent(it->first,
1254 TimeTicks(), TRACE_EVENT_PHASE_METADATA, 1204 TimeTicks(), TRACE_EVENT_PHASE_METADATA,
1255 &g_category_enabled[g_category_metadata], 1205 &g_category_group_enabled[g_category_metadata],
1256 "thread_name", trace_event_internal::kNoEventId, 1206 "thread_name", trace_event_internal::kNoEventId,
1257 num_args, &arg_name, &arg_type, &arg_value, NULL, 1207 num_args, &arg_name, &arg_type, &arg_value, NULL,
1258 TRACE_EVENT_FLAG_NONE)); 1208 TRACE_EVENT_FLAG_NONE));
1259 } 1209 }
1260 } 1210 }
1261 } 1211 }
1262 1212
1263 void TraceLog::InstallWaitableEventForSamplingTesting( 1213 void TraceLog::InstallWaitableEventForSamplingTesting(
1264 WaitableEvent* waitable_event) { 1214 WaitableEvent* waitable_event) {
1265 sampling_thread_->InstallWaitableEventForSamplingTesting(waitable_event); 1215 sampling_thread_->InstallWaitableEventForSamplingTesting(waitable_event);
(...skipping 14 matching lines...) Expand all
1280 unsigned long long offset_basis = 14695981039346656037ull; 1230 unsigned long long offset_basis = 14695981039346656037ull;
1281 unsigned long long fnv_prime = 1099511628211ull; 1231 unsigned long long fnv_prime = 1099511628211ull;
1282 unsigned long long pid = static_cast<unsigned long long>(process_id_); 1232 unsigned long long pid = static_cast<unsigned long long>(process_id_);
1283 process_id_hash_ = (offset_basis ^ pid) * fnv_prime; 1233 process_id_hash_ = (offset_basis ^ pid) * fnv_prime;
1284 } 1234 }
1285 1235
1286 void TraceLog::SetTimeOffset(TimeDelta offset) { 1236 void TraceLog::SetTimeOffset(TimeDelta offset) {
1287 time_offset_ = offset; 1237 time_offset_ = offset;
1288 } 1238 }
1289 1239
1240 bool CategoryFilter::IsEmptyOrContainsLeadingOrTrailingWhitespace(
1241 const std::string& str) {
1242 return str.empty() ||
1243 str.at(0) == ' ' ||
1244 str.at(str.length() - 1) == ' ';
1245 }
1246
1247 static bool DoesCategoryGroupContainCategory(const char* category_group,
1248 const char* category) {
1249 DCHECK(category);
1250 CStringTokenizer category_group_tokens(category_group,
1251 category_group + strlen(category_group), ",");
1252 while (category_group_tokens.GetNext()) {
1253 std::string category_group_token = category_group_tokens.token();
1254 // Don't allow empty tokens, nor tokens with leading or trailing space.
1255 DCHECK(!CategoryFilter::IsEmptyOrContainsLeadingOrTrailingWhitespace(
1256 category_group_token))
1257 << "Disallowed category string";
1258 if (MatchPattern(category_group_token.c_str(), category))
1259 return true;
1260 }
1261 return false;
1262 }
1263
1264 // Enable everything but debug and test categories by default.
1265 const char* CategoryFilter::kDefaultCategoryFilterString = "-*Debug,-*Test";
1266
1267 CategoryFilter::CategoryFilter(const std::string& filter_string) {
1268 if (!filter_string.empty())
1269 Initialize(filter_string);
1270 else
1271 Initialize(CategoryFilter::kDefaultCategoryFilterString);
1272 }
1273
1274 CategoryFilter::CategoryFilter(const CategoryFilter& cf)
1275 : included_(cf.included_),
1276 excluded_(cf.excluded_) {
1277 }
1278
1279 CategoryFilter::~CategoryFilter() {
1280 }
1281
1282 CategoryFilter& CategoryFilter::operator=(const CategoryFilter& rhs) {
1283 if (this == &rhs)
1284 return *this;
1285
1286 included_ = rhs.included_;
1287 excluded_ = rhs.excluded_;
1288 return *this;
1289 }
1290
1291 void CategoryFilter::Initialize(const std::string& filter_string) {
1292 // Tokenize list of categories, delimited by ','.
1293 StringTokenizer tokens(filter_string, ",");
1294 // Add each token to the appropriate list (included_,excluded_).
1295 while (tokens.GetNext()) {
1296 std::string category = tokens.token();
1297 // Ignore empty categories.
1298 if (category.empty())
1299 continue;
1300 // Excluded categories start with '-'.
1301 if (category.at(0) == '-') {
1302 // Remove '-' from category string.
1303 category = category.substr(1);
1304 excluded_.push_back(category);
1305 } else {
1306 included_.push_back(category);
1307 }
1308 }
1309 }
1310
1311 void CategoryFilter::WriteString(std::string* out,
1312 bool included) const {
1313 std::vector<std::string>::const_iterator ci;
1314 std::vector<std::string>::const_iterator end;
1315 if (included) {
1316 ci = included_.begin();
1317 end = included_.end();
1318 } else {
1319 ci = excluded_.begin();
1320 end = excluded_.end();
1321 }
1322
1323 // Prepend commas for all excluded categories IF we have included categories.
1324 bool prepend_comma_for_first_excluded = !included && !included_.empty();
1325 int token_cnt = 0;
1326 for (; ci != end; ++ci) {
1327 if (token_cnt > 0 || prepend_comma_for_first_excluded)
1328 StringAppendF(out, ",");
1329 StringAppendF(out, "%s%s", (included ? "" : "-"), ci->c_str());
1330 ++token_cnt;
1331 }
1332 }
1333
1334 std::string CategoryFilter::ToString() const {
1335 std::string filter_string;
1336 WriteString(&filter_string, true);
1337 WriteString(&filter_string, false);
1338
1339 return filter_string;
1340 }
1341
1342 bool CategoryFilter::IsCategoryGroupEnabled(
1343 const char* category_group_name) const {
1344 // TraceLog should call this method only as part of enabling/disabling
1345 // categories.
1346 std::vector<std::string>::const_iterator ci = included_.begin();
1347 for (; ci != included_.end(); ++ci) {
1348 if (DoesCategoryGroupContainCategory(category_group_name, ci->c_str()))
1349 return true;
1350 }
1351 ci = excluded_.begin();
1352 for (; ci != excluded_.end(); ++ci) {
1353 if (DoesCategoryGroupContainCategory(category_group_name, ci->c_str()))
1354 return false;
1355 }
1356 // If the category group is not excluded, and there are no included patterns
1357 // we consider this pattern enabled.
1358 return included_.empty();
1359 }
1360
1361 void CategoryFilter::Merge(const CategoryFilter& nested_filter) {
1362 included_.insert(included_.end(),
1363 nested_filter.included_.begin(),
1364 nested_filter.included_.end());
1365 excluded_.insert(excluded_.end(),
1366 nested_filter.excluded_.begin(),
1367 nested_filter.excluded_.end());
1368 }
1369
1370 bool CategoryFilter::HasIncludedPatterns() const {
1371 return !included_.empty();
1372 }
1373
1374 void CategoryFilter::Clear() {
1375 included_.clear();
1376 excluded_.clear();
1377 }
1378
1290 } // namespace debug 1379 } // namespace debug
1291 } // namespace base 1380 } // namespace base
1292 1381
1293 namespace trace_event_internal { 1382 namespace trace_event_internal {
1294 1383
1295 ScopedTrace::ScopedTrace( 1384 ScopedTrace::ScopedTrace(
1296 TRACE_EVENT_API_ATOMIC_WORD* event_uid, const char* name) { 1385 TRACE_EVENT_API_ATOMIC_WORD* event_uid, const char* name) {
1297 category_enabled_ = 1386 category_group_enabled_ =
1298 reinterpret_cast<const unsigned char*>(TRACE_EVENT_API_ATOMIC_LOAD( 1387 reinterpret_cast<const unsigned char*>(TRACE_EVENT_API_ATOMIC_LOAD(
1299 *event_uid)); 1388 *event_uid));
1300 if (!category_enabled_) { 1389 if (!category_group_enabled_) {
1301 category_enabled_ = TRACE_EVENT_API_GET_CATEGORY_ENABLED("gpu"); 1390 category_group_enabled_ = TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED("gpu");
1302 TRACE_EVENT_API_ATOMIC_STORE( 1391 TRACE_EVENT_API_ATOMIC_STORE(
1303 *event_uid, 1392 *event_uid,
1304 reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>(category_enabled_)); 1393 reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>(category_group_enabled_));
1305 } 1394 }
1306 if (*category_enabled_) { 1395 if (*category_group_enabled_) {
1307 name_ = name; 1396 name_ = name;
1308 TRACE_EVENT_API_ADD_TRACE_EVENT( 1397 TRACE_EVENT_API_ADD_TRACE_EVENT(
1309 TRACE_EVENT_PHASE_BEGIN, // phase 1398 TRACE_EVENT_PHASE_BEGIN, // phase
1310 category_enabled_, // category enabled 1399 category_group_enabled_, // category enabled
1311 name, // name 1400 name, // name
1312 0, // id 1401 0, // id
1313 0, // num_args 1402 0, // num_args
1314 NULL, // arg_names 1403 NULL, // arg_names
1315 NULL, // arg_types 1404 NULL, // arg_types
1316 NULL, // arg_values 1405 NULL, // arg_values
1317 NULL, // convertable_values 1406 NULL, // convertable_values
1318 TRACE_EVENT_FLAG_NONE); // flags 1407 TRACE_EVENT_FLAG_NONE); // flags
1319 } else { 1408 } else {
1320 category_enabled_ = NULL; 1409 category_group_enabled_ = NULL;
1321 } 1410 }
1322 } 1411 }
1323 1412
1324 ScopedTrace::~ScopedTrace() { 1413 ScopedTrace::~ScopedTrace() {
1325 if (category_enabled_ && *category_enabled_) { 1414 if (category_group_enabled_ && *category_group_enabled_) {
1326 TRACE_EVENT_API_ADD_TRACE_EVENT( 1415 TRACE_EVENT_API_ADD_TRACE_EVENT(
1327 TRACE_EVENT_PHASE_END, // phase 1416 TRACE_EVENT_PHASE_END, // phase
1328 category_enabled_, // category enabled 1417 category_group_enabled_, // category enabled
1329 name_, // name 1418 name_, // name
1330 0, // id 1419 0, // id
1331 0, // num_args 1420 0, // num_args
1332 NULL, // arg_names 1421 NULL, // arg_names
1333 NULL, // arg_types 1422 NULL, // arg_types
1334 NULL, // arg_values 1423 NULL, // arg_values
1335 NULL, // convertable values 1424 NULL, // convertable values
1336 TRACE_EVENT_FLAG_NONE); // flags 1425 TRACE_EVENT_FLAG_NONE); // flags
1337 } 1426 }
1338 } 1427 }
1339 1428
1340 } // namespace trace_event_internal 1429 } // namespace trace_event_internal
1341 1430
OLDNEW
« no previous file with comments | « base/debug/trace_event_impl.h ('k') | base/debug/trace_event_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698