| 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 |