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 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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |