Chromium Code Reviews| 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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 46 BASE_EXPORT TRACE_EVENT_API_ATOMIC_WORD g_trace_state2; | 46 BASE_EXPORT TRACE_EVENT_API_ATOMIC_WORD g_trace_state2; |
| 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 | 55 |
| 56 #define TRACE_EVENT_MAX_CATEGORIES 100 | 56 #define MAX_CATEGORY_GROUPS 100 |
| 57 | 57 |
| 58 namespace { | 58 namespace { |
| 59 | 59 |
| 60 // Parallel arrays g_categories and g_category_enabled are separate so that | 60 // Parallel arrays g_category_groups and g_category_group_enabled are separate |
| 61 // a pointer to a member of g_category_enabled can be easily converted to an | 61 // so that a pointer to a member of g_category_group_enabled can be easily |
| 62 // index into g_categories. This allows macros to deal only with char enabled | 62 // converted to an index into g_category_groups. This allows macros to deal |
| 63 // pointers from g_category_enabled, and we can convert internally to determine | 63 // only with char enabled pointers from g_category_group_enabled, and we can |
| 64 // the category name from the char enabled pointer. | 64 // convert internally to determine the category name from the char enabled |
| 65 const char* g_categories[TRACE_EVENT_MAX_CATEGORIES] = { | 65 // pointer. |
| 66 const char* g_category_groups[MAX_CATEGORY_GROUPS] = { | |
| 66 "tracing already shutdown", | 67 "tracing already shutdown", |
| 67 "tracing categories exhausted; must increase TRACE_EVENT_MAX_CATEGORIES", | 68 "tracing categories exhausted; must increase MAX_CATEGORY_GROUPS", |
| 68 "__metadata", | 69 "__metadata", |
| 69 }; | 70 }; |
| 70 // The enabled flag is char instead of bool so that the API can be used from C. | 71 // The enabled flag is char instead of bool so that the API can be used from C. |
| 71 unsigned char g_category_enabled[TRACE_EVENT_MAX_CATEGORIES] = { 0 }; | 72 unsigned char g_category_group_enabled[MAX_CATEGORY_GROUPS] = { 0 }; |
| 72 const int g_category_already_shutdown = 0; | 73 const int g_category_already_shutdown = 0; |
| 73 const int g_category_categories_exhausted = 1; | 74 const int g_category_categories_exhausted = 1; |
| 74 const int g_category_metadata = 2; | 75 const int g_category_metadata = 2; |
| 75 int g_category_index = 3; // skip initial 3 categories | 76 int g_category_index = 3; // skip initial 3 categories |
| 76 | 77 |
| 77 // The name of the current thread. This is used to decide if the current | 78 // The name of the current thread. This is used to decide if the current |
| 78 // thread name has changed. We combine all the seen thread names into the | 79 // thread name has changed. We combine all the seen thread names into the |
| 79 // output name for the thread. | 80 // output name for the thread. |
| 80 LazyInstance<ThreadLocalPointer<const char> >::Leaky | 81 LazyInstance<ThreadLocalPointer<const char> >::Leaky |
| 81 g_current_thread_name = LAZY_INSTANCE_INITIALIZER; | 82 g_current_thread_name = LAZY_INSTANCE_INITIALIZER; |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 104 DCHECK_LE(static_cast<int>(written), end - *buffer); | 105 DCHECK_LE(static_cast<int>(written), end - *buffer); |
| 105 *member = *buffer; | 106 *member = *buffer; |
| 106 *buffer += written; | 107 *buffer += written; |
| 107 } | 108 } |
| 108 } | 109 } |
| 109 | 110 |
| 110 } // namespace | 111 } // namespace |
| 111 | 112 |
| 112 TraceEvent::TraceEvent() | 113 TraceEvent::TraceEvent() |
| 113 : id_(0u), | 114 : id_(0u), |
| 114 category_enabled_(NULL), | 115 category_group_enabled_(NULL), |
| 115 name_(NULL), | 116 name_(NULL), |
| 116 thread_id_(0), | 117 thread_id_(0), |
| 117 phase_(TRACE_EVENT_PHASE_BEGIN), | 118 phase_(TRACE_EVENT_PHASE_BEGIN), |
| 118 flags_(0) { | 119 flags_(0) { |
| 119 arg_names_[0] = NULL; | 120 arg_names_[0] = NULL; |
| 120 arg_names_[1] = NULL; | 121 arg_names_[1] = NULL; |
| 121 memset(arg_values_, 0, sizeof(arg_values_)); | 122 memset(arg_values_, 0, sizeof(arg_values_)); |
| 122 } | 123 } |
| 123 | 124 |
| 124 TraceEvent::TraceEvent(int thread_id, | 125 TraceEvent::TraceEvent(int thread_id, |
| 125 TimeTicks timestamp, | 126 TimeTicks timestamp, |
| 126 char phase, | 127 char phase, |
| 127 const unsigned char* category_enabled, | 128 const unsigned char* category_group_enabled, |
| 128 const char* name, | 129 const char* name, |
| 129 unsigned long long id, | 130 unsigned long long id, |
| 130 int num_args, | 131 int num_args, |
| 131 const char** arg_names, | 132 const char** arg_names, |
| 132 const unsigned char* arg_types, | 133 const unsigned char* arg_types, |
| 133 const unsigned long long* arg_values, | 134 const unsigned long long* arg_values, |
| 134 unsigned char flags) | 135 unsigned char flags) |
| 135 : timestamp_(timestamp), | 136 : timestamp_(timestamp), |
| 136 id_(id), | 137 id_(id), |
| 137 category_enabled_(category_enabled), | 138 category_group_enabled_(category_group_enabled), |
| 138 name_(name), | 139 name_(name), |
| 139 thread_id_(thread_id), | 140 thread_id_(thread_id), |
| 140 phase_(phase), | 141 phase_(phase), |
| 141 flags_(flags) { | 142 flags_(flags) { |
| 142 // Clamp num_args since it may have been set by a third_party library. | 143 // Clamp num_args since it may have been set by a third_party library. |
| 143 num_args = (num_args > kTraceMaxNumArgs) ? kTraceMaxNumArgs : num_args; | 144 num_args = (num_args > kTraceMaxNumArgs) ? kTraceMaxNumArgs : num_args; |
| 144 int i = 0; | 145 int i = 0; |
| 145 for (; i < num_args; ++i) { | 146 for (; i < num_args; ++i) { |
| 146 arg_names_[i] = arg_names[i]; | 147 arg_names_[i] = arg_names[i]; |
| 147 arg_values_[i].as_uint = arg_values[i]; | 148 arg_values_[i].as_uint = arg_values[i]; |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 245 for (size_t i = 0; i < count && start + i < events.size(); ++i) { | 246 for (size_t i = 0; i < count && start + i < events.size(); ++i) { |
| 246 if (i > 0) | 247 if (i > 0) |
| 247 *out += ","; | 248 *out += ","; |
| 248 events[i + start].AppendAsJSON(out); | 249 events[i + start].AppendAsJSON(out); |
| 249 } | 250 } |
| 250 } | 251 } |
| 251 | 252 |
| 252 void TraceEvent::AppendAsJSON(std::string* out) const { | 253 void TraceEvent::AppendAsJSON(std::string* out) const { |
| 253 int64 time_int64 = timestamp_.ToInternalValue(); | 254 int64 time_int64 = timestamp_.ToInternalValue(); |
| 254 int process_id = TraceLog::GetInstance()->process_id(); | 255 int process_id = TraceLog::GetInstance()->process_id(); |
| 255 // Category name checked at category creation time. | 256 // Category group checked at category creation time. |
| 256 DCHECK(!strchr(name_, '"')); | 257 DCHECK(!strchr(name_, '"')); |
| 257 StringAppendF(out, | 258 StringAppendF(out, |
| 258 "{\"cat\":\"%s\",\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64 "," | 259 "{\"cat\":\"%s\",\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64 "," |
| 259 "\"ph\":\"%c\",\"name\":\"%s\",\"args\":{", | 260 "\"ph\":\"%c\",\"name\":\"%s\",\"args\":{", |
| 260 TraceLog::GetCategoryName(category_enabled_), | 261 TraceLog::GetCategoryGroupName(category_group_enabled_), |
| 261 process_id, | 262 process_id, |
| 262 thread_id_, | 263 thread_id_, |
| 263 time_int64, | 264 time_int64, |
| 264 phase_, | 265 phase_, |
| 265 name_); | 266 name_); |
| 266 | 267 |
| 267 // Output argument names and values, stop at first NULL argument name. | 268 // Output argument names and values, stop at first NULL argument name. |
| 268 for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) { | 269 for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) { |
| 269 if (i > 0) | 270 if (i > 0) |
| 270 *out += ","; | 271 *out += ","; |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 401 } | 402 } |
| 402 | 403 |
| 403 // static | 404 // static |
| 404 void TraceSamplingThread::DefaultSampleCallback(TraceBucketData* bucket_data) { | 405 void TraceSamplingThread::DefaultSampleCallback(TraceBucketData* bucket_data) { |
| 405 TRACE_EVENT_API_ATOMIC_WORD category_and_name = | 406 TRACE_EVENT_API_ATOMIC_WORD category_and_name = |
| 406 TRACE_EVENT_API_ATOMIC_LOAD(*bucket_data->bucket); | 407 TRACE_EVENT_API_ATOMIC_LOAD(*bucket_data->bucket); |
| 407 if (!category_and_name) | 408 if (!category_and_name) |
| 408 return; | 409 return; |
| 409 const char* const combined = | 410 const char* const combined = |
| 410 reinterpret_cast<const char* const>(category_and_name); | 411 reinterpret_cast<const char* const>(category_and_name); |
| 411 const char* category; | 412 const char* category_group; |
| 412 const char* name; | 413 const char* name; |
| 413 ExtractCategoryAndName(combined, &category, &name); | 414 ExtractCategoryAndName(combined, &category_group, &name); |
| 414 TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_SAMPLE, | 415 TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_SAMPLE, |
| 415 TraceLog::GetCategoryEnabled(category), | 416 TraceLog::GetCategoryGroupEnabled( |
| 417 category_group), | |
| 416 name, | 418 name, |
| 417 0, | 419 0, |
| 418 0, | 420 0, |
| 419 NULL, | 421 NULL, |
| 420 NULL, | 422 NULL, |
| 421 NULL, | 423 NULL, |
| 422 0); | 424 0); |
| 423 } | 425 } |
| 424 | 426 |
| 425 void TraceSamplingThread::GetSamples() { | 427 void TraceSamplingThread::GetSamples() { |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 529 : enable_count_(0), | 531 : enable_count_(0), |
| 530 dispatching_to_observer_list_(false), | 532 dispatching_to_observer_list_(false), |
| 531 watch_category_(NULL), | 533 watch_category_(NULL), |
| 532 trace_options_(RECORD_UNTIL_FULL), | 534 trace_options_(RECORD_UNTIL_FULL), |
| 533 sampling_thread_handle_(0) { | 535 sampling_thread_handle_(0) { |
| 534 // Trace is enabled or disabled on one thread while other threads are | 536 // Trace is enabled or disabled on one thread while other threads are |
| 535 // accessing the enabled flag. We don't care whether edge-case events are | 537 // accessing the enabled flag. We don't care whether edge-case events are |
| 536 // traced or not, so we allow races on the enabled flag to keep the trace | 538 // traced or not, so we allow races on the enabled flag to keep the trace |
| 537 // macros fast. | 539 // macros fast. |
| 538 // TODO(jbates): ANNOTATE_BENIGN_RACE_SIZED crashes windows TSAN bots: | 540 // TODO(jbates): ANNOTATE_BENIGN_RACE_SIZED crashes windows TSAN bots: |
| 539 // ANNOTATE_BENIGN_RACE_SIZED(g_category_enabled, sizeof(g_category_enabled), | 541 // ANNOTATE_BENIGN_RACE_SIZED(g_category_group_enabled, |
| 540 // "trace_event category enabled"); | 542 // sizeof(g_category_group_enabled), |
| 541 for (int i = 0; i < TRACE_EVENT_MAX_CATEGORIES; ++i) { | 543 // "trace_event category enabled"); |
| 542 ANNOTATE_BENIGN_RACE(&g_category_enabled[i], | 544 for (int i = 0; i < MAX_CATEGORY_GROUPS; ++i) { |
| 545 ANNOTATE_BENIGN_RACE(&g_category_group_enabled[i], | |
| 543 "trace_event category enabled"); | 546 "trace_event category enabled"); |
| 544 } | 547 } |
| 545 #if defined(OS_NACL) // NaCl shouldn't expose the process id. | 548 #if defined(OS_NACL) // NaCl shouldn't expose the process id. |
| 546 SetProcessID(0); | 549 SetProcessID(0); |
| 547 #else | 550 #else |
| 548 SetProcessID(static_cast<int>(GetCurrentProcId())); | 551 SetProcessID(static_cast<int>(GetCurrentProcId())); |
| 549 #endif | 552 #endif |
| 550 } | 553 } |
| 551 | 554 |
| 552 TraceLog::~TraceLog() { | 555 TraceLog::~TraceLog() { |
| 553 } | 556 } |
| 554 | 557 |
| 555 const unsigned char* TraceLog::GetCategoryEnabled(const char* name) { | 558 const unsigned char* TraceLog::GetCategoryGroupEnabled( |
| 559 const char* category_group) { | |
| 556 TraceLog* tracelog = GetInstance(); | 560 TraceLog* tracelog = GetInstance(); |
| 557 if (!tracelog) { | 561 if (!tracelog) { |
| 558 DCHECK(!g_category_enabled[g_category_already_shutdown]); | 562 DCHECK(!g_category_group_enabled[g_category_already_shutdown]); |
| 559 return &g_category_enabled[g_category_already_shutdown]; | 563 return &g_category_group_enabled[g_category_already_shutdown]; |
| 560 } | 564 } |
| 561 return tracelog->GetCategoryEnabledInternal(name); | 565 return tracelog->GetCategoryGroupEnabledInternal(category_group); |
| 562 } | 566 } |
| 563 | 567 |
| 564 const char* TraceLog::GetCategoryName(const unsigned char* category_enabled) { | 568 const char* TraceLog::GetCategoryGroupName( |
| 565 // Calculate the index of the category by finding category_enabled in | 569 const unsigned char* category_group_enabled) { |
| 566 // g_category_enabled array. | 570 // Calculate the index of the category group by finding |
| 567 uintptr_t category_begin = reinterpret_cast<uintptr_t>(g_category_enabled); | 571 // category_group_enabled in g_category_group_enabled array. |
| 568 uintptr_t category_ptr = reinterpret_cast<uintptr_t>(category_enabled); | 572 uintptr_t category_begin = |
| 573 reinterpret_cast<uintptr_t>(g_category_group_enabled); | |
| 574 uintptr_t category_ptr = reinterpret_cast<uintptr_t>(category_group_enabled); | |
| 569 DCHECK(category_ptr >= category_begin && | 575 DCHECK(category_ptr >= category_begin && |
| 570 category_ptr < reinterpret_cast<uintptr_t>(g_category_enabled + | 576 category_ptr < reinterpret_cast<uintptr_t>( |
| 571 TRACE_EVENT_MAX_CATEGORIES)) << | 577 g_category_group_enabled + MAX_CATEGORY_GROUPS)) << |
|
dsinclair
2013/03/12 21:27:24
Indenting, should be in 4 more.
rterrazas
2013/03/20 08:48:49
Done.
| |
| 572 "out of bounds category pointer"; | 578 "out of bounds category pointer"; |
| 573 uintptr_t category_index = | 579 uintptr_t category_index = |
| 574 (category_ptr - category_begin) / sizeof(g_category_enabled[0]); | 580 (category_ptr - category_begin) / sizeof(g_category_group_enabled[0]); |
| 575 return g_categories[category_index]; | 581 return g_category_groups[category_index]; |
| 576 } | 582 } |
| 577 | 583 |
| 578 static void EnableMatchingCategory(int category_index, | 584 void TraceLog::EnableIncludedCategoryGroup(int category_index) { |
| 579 const std::vector<std::string>& patterns, | 585 bool is_enabled = category_filter_.IsCategoryGroupEnabled( |
| 580 unsigned char matched_value, | 586 g_category_groups[category_index]); |
| 581 unsigned char unmatched_value) { | 587 g_category_group_enabled[category_index] = |
| 582 std::vector<std::string>::const_iterator ci = patterns.begin(); | 588 is_enabled ? TraceLog::CATEGORY_ENABLED : 0; |
| 583 bool is_match = false; | |
| 584 for (; ci != patterns.end(); ++ci) { | |
| 585 is_match = MatchPattern(g_categories[category_index], ci->c_str()); | |
| 586 if (is_match) | |
| 587 break; | |
| 588 } | |
| 589 g_category_enabled[category_index] = is_match ? | |
| 590 matched_value : unmatched_value; | |
| 591 } | 589 } |
| 592 | 590 |
| 593 // Enable/disable each category based on the category filters in |patterns|. | 591 void TraceLog::EnableIncludedCategoryGroups() { |
| 594 // If the category name matches one of the patterns, its enabled status is set | |
| 595 // to |matched_value|. Otherwise its enabled status is set to |unmatched_value|. | |
| 596 static void EnableMatchingCategories(const std::vector<std::string>& patterns, | |
| 597 unsigned char matched_value, | |
| 598 unsigned char unmatched_value) { | |
| 599 for (int i = 0; i < g_category_index; i++) | 592 for (int i = 0; i < g_category_index; i++) |
| 600 EnableMatchingCategory(i, patterns, matched_value, unmatched_value); | 593 EnableIncludedCategoryGroup(i); |
| 601 } | 594 } |
| 602 | 595 |
| 603 const unsigned char* TraceLog::GetCategoryEnabledInternal(const char* name) { | 596 const unsigned char* TraceLog::GetCategoryGroupEnabledInternal( |
| 597 const char* category_group) { | |
| 598 DCHECK(!strchr(category_group, '"')) << | |
| 599 "Category groups may not contain double quote"; | |
| 604 AutoLock lock(lock_); | 600 AutoLock lock(lock_); |
| 605 DCHECK(!strchr(name, '"')) << "Category names may not contain double quote"; | |
| 606 | 601 |
| 607 unsigned char* category_enabled = NULL; | 602 unsigned char* category_group_enabled = NULL; |
| 608 // Search for pre-existing category matching this name | 603 // Search for pre-existing category group. |
| 609 for (int i = 0; i < g_category_index; i++) { | 604 for (int i = 0; i < g_category_index; i++) { |
| 610 if (strcmp(g_categories[i], name) == 0) { | 605 if (strcmp(g_category_groups[i], category_group) == 0) { |
| 611 category_enabled = &g_category_enabled[i]; | 606 category_group_enabled = &g_category_group_enabled[i]; |
| 612 break; | 607 break; |
| 613 } | 608 } |
| 614 } | 609 } |
| 615 | 610 |
| 616 if (!category_enabled) { | 611 if (!category_group_enabled) { |
| 617 // Create a new category | 612 // Create a new category group |
| 618 DCHECK(g_category_index < TRACE_EVENT_MAX_CATEGORIES) << | 613 DCHECK(g_category_index < MAX_CATEGORY_GROUPS) << |
| 619 "must increase TRACE_EVENT_MAX_CATEGORIES"; | 614 "must increase MAX_CATEGORY_GROUPS"; |
| 620 if (g_category_index < TRACE_EVENT_MAX_CATEGORIES) { | 615 if (g_category_index < MAX_CATEGORY_GROUPS) { |
| 621 int new_index = g_category_index++; | 616 int new_index = g_category_index++; |
| 622 // Don't hold on to the name pointer, so that we can create categories | 617 // Don't hold on to the category_group pointer, so that we can create |
| 623 // with strings not known at compile time (this is required by | 618 // category groups with strings not known at compile time (this is |
| 624 // SetWatchEvent). | 619 // required by SetWatchEvent). |
| 625 const char* new_name = strdup(name); | 620 const char* new_group = strdup(category_group); |
| 626 ANNOTATE_LEAKING_OBJECT_PTR(new_name); | 621 ANNOTATE_LEAKING_OBJECT_PTR(new_group); |
| 627 g_categories[new_index] = new_name; | 622 g_category_groups[new_index] = new_group; |
| 628 DCHECK(!g_category_enabled[new_index]); | 623 DCHECK(!g_category_group_enabled[new_index]); |
| 629 if (enable_count_) { | 624 if (enable_count_) { |
| 630 // Note that if both included and excluded_categories are empty, the | 625 // Note that if both included and excluded patterns in the |
| 631 // else clause below excludes nothing, thereby enabling this category. | 626 // CategoryFilter are empty, we exclude nothing, |
| 632 if (!included_categories_.empty()) { | 627 // thereby enabling this category group. |
| 633 EnableMatchingCategory(new_index, included_categories_, | 628 EnableIncludedCategoryGroup(new_index); |
| 634 CATEGORY_ENABLED, 0); | |
| 635 } else { | |
| 636 EnableMatchingCategory(new_index, excluded_categories_, | |
| 637 0, CATEGORY_ENABLED); | |
| 638 } | |
| 639 } else { | 629 } else { |
| 640 g_category_enabled[new_index] = 0; | 630 g_category_group_enabled[new_index] = 0; |
| 641 } | 631 } |
| 642 category_enabled = &g_category_enabled[new_index]; | 632 category_group_enabled = &g_category_group_enabled[new_index]; |
| 643 } else { | 633 } else { |
| 644 category_enabled = &g_category_enabled[g_category_categories_exhausted]; | 634 category_group_enabled = |
| 635 &g_category_group_enabled[g_category_categories_exhausted]; | |
| 645 } | 636 } |
| 646 } | 637 } |
| 647 #if defined(OS_ANDROID) | 638 #if defined(OS_ANDROID) |
| 648 ApplyATraceEnabledFlag(category_enabled); | 639 ApplyATraceEnabledFlag(category_group_enabled); |
| 649 #endif | 640 #endif |
| 650 return category_enabled; | 641 return category_group_enabled; |
| 651 } | 642 } |
| 652 | 643 |
| 653 void TraceLog::GetKnownCategories(std::vector<std::string>* categories) { | 644 void TraceLog::GetKnownCategoryGroups( |
| 645 std::vector<std::string>* category_groups) { | |
| 654 AutoLock lock(lock_); | 646 AutoLock lock(lock_); |
| 655 for (int i = 0; i < g_category_index; i++) | 647 for (int i = 0; i < g_category_index; i++) |
| 656 categories->push_back(g_categories[i]); | 648 category_groups->push_back(g_category_groups[i]); |
| 657 } | 649 } |
| 658 | 650 |
| 659 void TraceLog::SetEnabled(const std::vector<std::string>& included_categories, | 651 void TraceLog::SetEnabled(const CategoryFilter& category_filter, |
| 660 const std::vector<std::string>& excluded_categories, | |
| 661 Options options) { | 652 Options options) { |
| 662 AutoLock lock(lock_); | 653 AutoLock lock(lock_); |
| 663 | 654 |
| 664 if (enable_count_++ > 0) { | 655 if (enable_count_++ > 0) { |
| 665 if (options != trace_options_) { | 656 if (options != trace_options_) { |
| 666 DLOG(ERROR) << "Attemting to re-enable tracing with a different " | 657 DLOG(ERROR) << "Attemting to re-enable tracing with a different " |
| 667 << "set of options."; | 658 << "set of options."; |
| 668 } | 659 } |
| 669 | 660 |
| 670 // Tracing is already enabled, so just merge in enabled categories. | 661 // Tracing is already enabled, so just merge in enabled categories. |
| 671 // We only expand the set of enabled categories upon nested SetEnable(). | 662 // We only expand the set of enabled categories upon nested SetEnable(). |
| 672 if (!included_categories_.empty() && !included_categories.empty()) { | 663 if (category_filter_.HasAllowedPatterns() && |
| 673 included_categories_.insert(included_categories_.end(), | 664 category_filter.HasAllowedPatterns()) { |
| 674 included_categories.begin(), | 665 category_filter_.Merge(category_filter); |
| 675 included_categories.end()); | |
| 676 EnableMatchingCategories(included_categories_, CATEGORY_ENABLED, 0); | |
| 677 } else { | 666 } else { |
| 678 // If either old or new included categories are empty, allow all events. | 667 // If either old or new included categories are empty, allow all events. |
| 679 included_categories_.clear(); | 668 category_filter_.Clear(); |
| 680 excluded_categories_.clear(); | |
| 681 EnableMatchingCategories(excluded_categories_, 0, CATEGORY_ENABLED); | |
| 682 } | 669 } |
| 670 EnableIncludedCategoryGroups(); | |
| 683 return; | 671 return; |
| 684 } | 672 } |
| 685 trace_options_ = options; | 673 trace_options_ = options; |
| 686 | 674 |
| 687 if (dispatching_to_observer_list_) { | 675 if (dispatching_to_observer_list_) { |
| 688 DLOG(ERROR) << | 676 DLOG(ERROR) << |
| 689 "Cannot manipulate TraceLog::Enabled state from an observer."; | 677 "Cannot manipulate TraceLog::Enabled state from an observer."; |
| 690 return; | 678 return; |
| 691 } | 679 } |
| 692 | 680 |
| 693 dispatching_to_observer_list_ = true; | 681 dispatching_to_observer_list_ = true; |
| 694 FOR_EACH_OBSERVER(EnabledStateChangedObserver, enabled_state_observer_list_, | 682 FOR_EACH_OBSERVER(EnabledStateChangedObserver, enabled_state_observer_list_, |
| 695 OnTraceLogWillEnable()); | 683 OnTraceLogWillEnable()); |
| 696 dispatching_to_observer_list_ = false; | 684 dispatching_to_observer_list_ = false; |
| 697 | 685 |
| 698 logged_events_.reserve(1024); | 686 logged_events_.reserve(1024); |
| 699 included_categories_ = included_categories; | 687 category_filter_ = CategoryFilter(category_filter); |
| 700 excluded_categories_ = excluded_categories; | 688 EnableIncludedCategoryGroups(); |
| 701 // Note that if both included and excluded_categories are empty, the else | |
| 702 // clause below excludes nothing, thereby enabling all categories. | |
| 703 if (!included_categories_.empty()) | |
| 704 EnableMatchingCategories(included_categories_, CATEGORY_ENABLED, 0); | |
| 705 else | |
| 706 EnableMatchingCategories(excluded_categories_, 0, CATEGORY_ENABLED); | |
| 707 | 689 |
| 708 if (options & ENABLE_SAMPLING) { | 690 if (options & ENABLE_SAMPLING) { |
| 709 sampling_thread_.reset(new TraceSamplingThread); | 691 sampling_thread_.reset(new TraceSamplingThread); |
| 710 sampling_thread_->RegisterSampleBucket( | 692 sampling_thread_->RegisterSampleBucket( |
| 711 &g_trace_state0, | 693 &g_trace_state0, |
| 712 "bucket0", | 694 "bucket0", |
| 713 Bind(&TraceSamplingThread::DefaultSampleCallback)); | 695 Bind(&TraceSamplingThread::DefaultSampleCallback)); |
| 714 sampling_thread_->RegisterSampleBucket( | 696 sampling_thread_->RegisterSampleBucket( |
| 715 &g_trace_state1, | 697 &g_trace_state1, |
| 716 "bucket1", | 698 "bucket1", |
| 717 Bind(&TraceSamplingThread::DefaultSampleCallback)); | 699 Bind(&TraceSamplingThread::DefaultSampleCallback)); |
| 718 sampling_thread_->RegisterSampleBucket( | 700 sampling_thread_->RegisterSampleBucket( |
| 719 &g_trace_state2, | 701 &g_trace_state2, |
| 720 "bucket2", | 702 "bucket2", |
| 721 Bind(&TraceSamplingThread::DefaultSampleCallback)); | 703 Bind(&TraceSamplingThread::DefaultSampleCallback)); |
| 722 if (!PlatformThread::Create( | 704 if (!PlatformThread::Create( |
| 723 0, sampling_thread_.get(), &sampling_thread_handle_)) { | 705 0, sampling_thread_.get(), &sampling_thread_handle_)) { |
| 724 DCHECK(false) << "failed to create thread"; | 706 DCHECK(false) << "failed to create thread"; |
| 725 } | 707 } |
| 726 } | 708 } |
| 727 } | 709 } |
| 728 | 710 |
| 729 void TraceLog::SetEnabled(const std::string& categories, Options options) { | 711 const CategoryFilter& TraceLog::GetCurrentCategoryFilter() { |
| 730 std::vector<std::string> included, excluded; | |
| 731 // Tokenize list of categories, delimited by ','. | |
| 732 StringTokenizer tokens(categories, ","); | |
| 733 while (tokens.GetNext()) { | |
| 734 bool is_included = true; | |
| 735 std::string category = tokens.token(); | |
| 736 // Excluded categories start with '-'. | |
| 737 if (category.at(0) == '-') { | |
| 738 // Remove '-' from category string. | |
| 739 category = category.substr(1); | |
| 740 is_included = false; | |
| 741 } | |
| 742 if (is_included) | |
| 743 included.push_back(category); | |
| 744 else | |
| 745 excluded.push_back(category); | |
| 746 } | |
| 747 SetEnabled(included, excluded, options); | |
| 748 } | |
| 749 | |
| 750 void TraceLog::GetEnabledTraceCategories( | |
| 751 std::vector<std::string>* included_out, | |
| 752 std::vector<std::string>* excluded_out) { | |
| 753 AutoLock lock(lock_); | 712 AutoLock lock(lock_); |
| 754 if (enable_count_) { | 713 DCHECK(enable_count_ > 0); |
| 755 *included_out = included_categories_; | 714 return category_filter_; |
| 756 *excluded_out = excluded_categories_; | |
| 757 } | |
| 758 } | 715 } |
| 759 | 716 |
| 760 void TraceLog::SetDisabled() { | 717 void TraceLog::SetDisabled() { |
| 761 AutoLock lock(lock_); | 718 AutoLock lock(lock_); |
| 762 DCHECK(enable_count_ > 0); | 719 DCHECK(enable_count_ > 0); |
| 763 if (--enable_count_ != 0) | 720 if (--enable_count_ != 0) |
| 764 return; | 721 return; |
| 765 | 722 |
| 766 if (dispatching_to_observer_list_) { | 723 if (dispatching_to_observer_list_) { |
| 767 DLOG(ERROR) | 724 DLOG(ERROR) |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 778 sampling_thread_handle_ = 0; | 735 sampling_thread_handle_ = 0; |
| 779 sampling_thread_.reset(); | 736 sampling_thread_.reset(); |
| 780 } | 737 } |
| 781 | 738 |
| 782 dispatching_to_observer_list_ = true; | 739 dispatching_to_observer_list_ = true; |
| 783 FOR_EACH_OBSERVER(EnabledStateChangedObserver, | 740 FOR_EACH_OBSERVER(EnabledStateChangedObserver, |
| 784 enabled_state_observer_list_, | 741 enabled_state_observer_list_, |
| 785 OnTraceLogWillDisable()); | 742 OnTraceLogWillDisable()); |
| 786 dispatching_to_observer_list_ = false; | 743 dispatching_to_observer_list_ = false; |
| 787 | 744 |
| 788 included_categories_.clear(); | 745 category_filter_.Clear(); |
| 789 excluded_categories_.clear(); | |
| 790 watch_category_ = NULL; | 746 watch_category_ = NULL; |
| 791 watch_event_name_ = ""; | 747 watch_event_name_ = ""; |
| 792 for (int i = 0; i < g_category_index; i++) | 748 for (int i = 0; i < g_category_index; i++) |
| 793 g_category_enabled[i] = 0; | 749 g_category_group_enabled[i] = 0; |
| 794 AddThreadNameMetadataEvents(); | 750 AddThreadNameMetadataEvents(); |
| 795 } | 751 } |
| 796 | 752 |
| 797 void TraceLog::SetEnabled(bool enabled, Options options) { | |
| 798 if (enabled) | |
| 799 SetEnabled(std::vector<std::string>(), std::vector<std::string>(), options); | |
| 800 else | |
| 801 SetDisabled(); | |
| 802 } | |
| 803 | |
| 804 void TraceLog::AddEnabledStateObserver(EnabledStateChangedObserver* listener) { | 753 void TraceLog::AddEnabledStateObserver(EnabledStateChangedObserver* listener) { |
| 805 enabled_state_observer_list_.AddObserver(listener); | 754 enabled_state_observer_list_.AddObserver(listener); |
| 806 } | 755 } |
| 807 | 756 |
| 808 void TraceLog::RemoveEnabledStateObserver( | 757 void TraceLog::RemoveEnabledStateObserver( |
| 809 EnabledStateChangedObserver* listener) { | 758 EnabledStateChangedObserver* listener) { |
| 810 enabled_state_observer_list_.RemoveObserver(listener); | 759 enabled_state_observer_list_.RemoveObserver(listener); |
| 811 } | 760 } |
| 812 | 761 |
| 813 float TraceLog::GetBufferPercentFull() const { | 762 float TraceLog::GetBufferPercentFull() const { |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 839 new RefCountedString(); | 788 new RefCountedString(); |
| 840 TraceEvent::AppendEventsAsJSON(previous_logged_events, | 789 TraceEvent::AppendEventsAsJSON(previous_logged_events, |
| 841 i, | 790 i, |
| 842 kTraceEventBatchSize, | 791 kTraceEventBatchSize, |
| 843 &(json_events_str_ptr->data())); | 792 &(json_events_str_ptr->data())); |
| 844 cb.Run(json_events_str_ptr); | 793 cb.Run(json_events_str_ptr); |
| 845 } | 794 } |
| 846 } | 795 } |
| 847 | 796 |
| 848 void TraceLog::AddTraceEvent(char phase, | 797 void TraceLog::AddTraceEvent(char phase, |
| 849 const unsigned char* category_enabled, | 798 const unsigned char* category_group_enabled, |
| 850 const char* name, | 799 const char* name, |
| 851 unsigned long long id, | 800 unsigned long long id, |
| 852 int num_args, | 801 int num_args, |
| 853 const char** arg_names, | 802 const char** arg_names, |
| 854 const unsigned char* arg_types, | 803 const unsigned char* arg_types, |
| 855 const unsigned long long* arg_values, | 804 const unsigned long long* arg_values, |
| 856 unsigned char flags) { | 805 unsigned char flags) { |
| 857 int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); | 806 int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); |
| 858 base::TimeTicks now = base::TimeTicks::NowFromSystemTraceTime(); | 807 base::TimeTicks now = base::TimeTicks::NowFromSystemTraceTime(); |
| 859 AddTraceEventWithThreadIdAndTimestamp(phase, category_enabled, name, id, | 808 AddTraceEventWithThreadIdAndTimestamp(phase, category_group_enabled, name, id, |
| 860 thread_id, now, num_args, arg_names, | 809 thread_id, now, num_args, arg_names, |
| 861 arg_types, arg_values, flags); | 810 arg_types, arg_values, flags); |
| 862 } | 811 } |
| 863 | 812 |
| 864 void TraceLog::AddTraceEventWithThreadIdAndTimestamp( | 813 void TraceLog::AddTraceEventWithThreadIdAndTimestamp( |
| 865 char phase, | 814 char phase, |
| 866 const unsigned char* category_enabled, | 815 const unsigned char* category_group_enabled, |
| 867 const char* name, | 816 const char* name, |
| 868 unsigned long long id, | 817 unsigned long long id, |
| 869 int thread_id, | 818 int thread_id, |
| 870 const TimeTicks& timestamp, | 819 const TimeTicks& timestamp, |
| 871 int num_args, | 820 int num_args, |
| 872 const char** arg_names, | 821 const char** arg_names, |
| 873 const unsigned char* arg_types, | 822 const unsigned char* arg_types, |
| 874 const unsigned long long* arg_values, | 823 const unsigned long long* arg_values, |
| 875 unsigned char flags) { | 824 unsigned char flags) { |
| 876 DCHECK(name); | 825 DCHECK(name); |
| 877 | 826 |
| 878 #if defined(OS_ANDROID) | 827 #if defined(OS_ANDROID) |
| 879 SendToATrace(phase, GetCategoryName(category_enabled), name, | 828 SendToATrace(phase, GetCategoryGroupName(category_group_enabled), name, |
| 880 num_args, arg_names, arg_types, arg_values); | 829 num_args, arg_names, arg_types, arg_values); |
| 881 #endif | 830 #endif |
| 882 | 831 |
| 883 TimeTicks now = timestamp - time_offset_; | 832 TimeTicks now = timestamp - time_offset_; |
| 884 EventCallback event_callback_copy; | 833 EventCallback event_callback_copy; |
| 885 | 834 |
| 886 NotificationHelper notifier(this); | 835 NotificationHelper notifier(this); |
| 887 | 836 |
| 888 { | 837 { |
| 889 AutoLock lock(lock_); | 838 AutoLock lock(lock_); |
| 890 if (*category_enabled != CATEGORY_ENABLED) | 839 if (*category_group_enabled != CATEGORY_ENABLED) |
| 891 return; | 840 return; |
| 892 if (logged_events_.size() >= kTraceEventBufferSize) | 841 if (logged_events_.size() >= kTraceEventBufferSize) |
| 893 return; | 842 return; |
| 894 | 843 |
| 895 const char* new_name = ThreadIdNameManager::GetInstance()-> | 844 const char* new_name = ThreadIdNameManager::GetInstance()-> |
| 896 GetName(thread_id); | 845 GetName(thread_id); |
| 897 // Check if the thread name has been set or changed since the previous | 846 // Check if the thread name has been set or changed since the previous |
| 898 // call (if any), but don't bother if the new name is empty. Note this will | 847 // call (if any), but don't bother if the new name is empty. Note this will |
| 899 // not detect a thread name change within the same char* buffer address: we | 848 // not detect a thread name change within the same char* buffer address: we |
| 900 // favor common case performance over corner case correctness. | 849 // favor common case performance over corner case correctness. |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 920 existing_name->second.append(new_name); | 869 existing_name->second.append(new_name); |
| 921 } | 870 } |
| 922 } | 871 } |
| 923 } | 872 } |
| 924 | 873 |
| 925 if (flags & TRACE_EVENT_FLAG_MANGLE_ID) | 874 if (flags & TRACE_EVENT_FLAG_MANGLE_ID) |
| 926 id ^= process_id_hash_; | 875 id ^= process_id_hash_; |
| 927 | 876 |
| 928 logged_events_.push_back( | 877 logged_events_.push_back( |
| 929 TraceEvent(thread_id, | 878 TraceEvent(thread_id, |
| 930 now, phase, category_enabled, name, id, | 879 now, phase, category_group_enabled, name, id, |
| 931 num_args, arg_names, arg_types, arg_values, | 880 num_args, arg_names, arg_types, arg_values, |
| 932 flags)); | 881 flags)); |
| 933 | 882 |
| 934 if (logged_events_.size() == kTraceEventBufferSize) | 883 if (logged_events_.size() == kTraceEventBufferSize) |
| 935 notifier.AddNotificationWhileLocked(TRACE_BUFFER_FULL); | 884 notifier.AddNotificationWhileLocked(TRACE_BUFFER_FULL); |
| 936 | 885 |
| 937 if (watch_category_ == category_enabled && watch_event_name_ == name) | 886 if (watch_category_ == category_group_enabled && watch_event_name_ == name) |
| 938 notifier.AddNotificationWhileLocked(EVENT_WATCH_NOTIFICATION); | 887 notifier.AddNotificationWhileLocked(EVENT_WATCH_NOTIFICATION); |
| 939 | 888 |
| 940 event_callback_copy = event_callback_; | 889 event_callback_copy = event_callback_; |
| 941 } // release lock | 890 } // release lock |
| 942 | 891 |
| 943 notifier.SendNotificationIfAny(); | 892 notifier.SendNotificationIfAny(); |
| 944 if (event_callback_copy != NULL) { | 893 if (event_callback_copy != NULL) { |
| 945 event_callback_copy(phase, category_enabled, name, id, | 894 event_callback_copy(phase, category_group_enabled, name, id, |
| 946 num_args, arg_names, arg_types, arg_values, | 895 num_args, arg_names, arg_types, arg_values, |
| 947 flags); | 896 flags); |
| 948 } | 897 } |
| 949 } | 898 } |
| 950 | 899 |
| 951 void TraceLog::AddTraceEventEtw(char phase, | 900 void TraceLog::AddTraceEventEtw(char phase, |
| 952 const char* name, | 901 const char* name, |
| 953 const void* id, | 902 const void* id, |
| 954 const char* extra) { | 903 const char* extra) { |
| 955 #if defined(OS_WIN) | 904 #if defined(OS_WIN) |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 966 { | 915 { |
| 967 #if defined(OS_WIN) | 916 #if defined(OS_WIN) |
| 968 TraceEventETWProvider::Trace(name, phase, id, extra); | 917 TraceEventETWProvider::Trace(name, phase, id, extra); |
| 969 #endif | 918 #endif |
| 970 INTERNAL_TRACE_EVENT_ADD(phase, "ETW Trace Event", name, | 919 INTERNAL_TRACE_EVENT_ADD(phase, "ETW Trace Event", name, |
| 971 TRACE_EVENT_FLAG_COPY, "id", id, "extra", extra); | 920 TRACE_EVENT_FLAG_COPY, "id", id, "extra", extra); |
| 972 } | 921 } |
| 973 | 922 |
| 974 void TraceLog::SetWatchEvent(const std::string& category_name, | 923 void TraceLog::SetWatchEvent(const std::string& category_name, |
| 975 const std::string& event_name) { | 924 const std::string& event_name) { |
| 976 const unsigned char* category = GetCategoryEnabled(category_name.c_str()); | 925 const unsigned char* category = GetCategoryGroupEnabled( |
| 926 category_name.c_str()); | |
|
dsinclair
2013/03/12 21:27:24
nit: indenting.
rterrazas
2013/03/20 08:48:49
Done.
| |
| 977 int notify_count = 0; | 927 int notify_count = 0; |
| 978 { | 928 { |
| 979 AutoLock lock(lock_); | 929 AutoLock lock(lock_); |
| 980 watch_category_ = category; | 930 watch_category_ = category; |
| 981 watch_event_name_ = event_name; | 931 watch_event_name_ = event_name; |
| 982 | 932 |
| 983 // First, search existing events for watch event because we want to catch it | 933 // First, search existing events for watch event because we want to catch it |
| 984 // even if it has already occurred. | 934 // even if it has already occurred. |
| 985 for (size_t i = 0u; i < logged_events_.size(); ++i) { | 935 for (size_t i = 0u; i < logged_events_.size(); ++i) { |
| 986 if (category == logged_events_[i].category_enabled() && | 936 if (category == logged_events_[i].category_group_enabled() && |
| 987 strcmp(event_name.c_str(), logged_events_[i].name()) == 0) { | 937 strcmp(event_name.c_str(), logged_events_[i].name()) == 0) { |
| 988 ++notify_count; | 938 ++notify_count; |
| 989 } | 939 } |
| 990 } | 940 } |
| 991 } // release lock | 941 } // release lock |
| 992 | 942 |
| 993 // Send notification for each event found. | 943 // Send notification for each event found. |
| 994 for (int i = 0; i < notify_count; ++i) { | 944 for (int i = 0; i < notify_count; ++i) { |
| 995 NotificationHelper notifier(this); | 945 NotificationHelper notifier(this); |
| 996 lock_.Acquire(); | 946 lock_.Acquire(); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1013 it++) { | 963 it++) { |
| 1014 if (!it->second.empty()) { | 964 if (!it->second.empty()) { |
| 1015 int num_args = 1; | 965 int num_args = 1; |
| 1016 const char* arg_name = "name"; | 966 const char* arg_name = "name"; |
| 1017 unsigned char arg_type; | 967 unsigned char arg_type; |
| 1018 unsigned long long arg_value; | 968 unsigned long long arg_value; |
| 1019 trace_event_internal::SetTraceValue(it->second, &arg_type, &arg_value); | 969 trace_event_internal::SetTraceValue(it->second, &arg_type, &arg_value); |
| 1020 logged_events_.push_back( | 970 logged_events_.push_back( |
| 1021 TraceEvent(it->first, | 971 TraceEvent(it->first, |
| 1022 TimeTicks(), TRACE_EVENT_PHASE_METADATA, | 972 TimeTicks(), TRACE_EVENT_PHASE_METADATA, |
| 1023 &g_category_enabled[g_category_metadata], | 973 &g_category_group_enabled[g_category_metadata], |
| 1024 "thread_name", trace_event_internal::kNoEventId, | 974 "thread_name", trace_event_internal::kNoEventId, |
| 1025 num_args, &arg_name, &arg_type, &arg_value, | 975 num_args, &arg_name, &arg_type, &arg_value, |
| 1026 TRACE_EVENT_FLAG_NONE)); | 976 TRACE_EVENT_FLAG_NONE)); |
| 1027 } | 977 } |
| 1028 } | 978 } |
| 1029 } | 979 } |
| 1030 | 980 |
| 1031 void TraceLog::InstallWaitableEventForSamplingTesting( | 981 void TraceLog::InstallWaitableEventForSamplingTesting( |
| 1032 WaitableEvent* waitable_event) { | 982 WaitableEvent* waitable_event) { |
| 1033 sampling_thread_->InstallWaitableEventForSamplingTesting(waitable_event); | 983 sampling_thread_->InstallWaitableEventForSamplingTesting(waitable_event); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 1048 unsigned long long offset_basis = 14695981039346656037ull; | 998 unsigned long long offset_basis = 14695981039346656037ull; |
| 1049 unsigned long long fnv_prime = 1099511628211ull; | 999 unsigned long long fnv_prime = 1099511628211ull; |
| 1050 unsigned long long pid = static_cast<unsigned long long>(process_id_); | 1000 unsigned long long pid = static_cast<unsigned long long>(process_id_); |
| 1051 process_id_hash_ = (offset_basis ^ pid) * fnv_prime; | 1001 process_id_hash_ = (offset_basis ^ pid) * fnv_prime; |
| 1052 } | 1002 } |
| 1053 | 1003 |
| 1054 void TraceLog::SetTimeOffset(TimeDelta offset) { | 1004 void TraceLog::SetTimeOffset(TimeDelta offset) { |
| 1055 time_offset_ = offset; | 1005 time_offset_ = offset; |
| 1056 } | 1006 } |
| 1057 | 1007 |
| 1008 static bool DoesCategoryGroupContainCategory(const char* category_group, | |
| 1009 const char* category) { | |
| 1010 DCHECK(category); | |
| 1011 CStringTokenizer category_group_tokens(category_group, | |
| 1012 category_group + strlen(category_group), ","); | |
| 1013 while (category_group_tokens.GetNext()) { | |
| 1014 std::string category_group_token = category_group_tokens.token(); | |
| 1015 // Don't allow empty tokens, nor tokens with leading or trailing space. | |
| 1016 DCHECK(!category_group_token.empty() && | |
| 1017 category_group_token.at(0) != ' '&& | |
|
dsinclair
2013/03/12 21:27:24
nit: Space before &&
rterrazas
2013/03/20 08:48:49
Done.
| |
| 1018 category_group_token.at(category_group_token.length() - 1) != ' ') | |
| 1019 << "Disallowed category string"; | |
| 1020 if (MatchPattern(category_group_token.c_str(), category)) | |
| 1021 return true; | |
| 1022 } | |
| 1023 return false; | |
| 1024 } | |
| 1025 | |
| 1026 // Enable everything but debug and test categories by default. | |
| 1027 const char* CategoryFilter::kDefaultCategoryFilterString = "-*Debug,-*Test"; | |
| 1028 | |
| 1029 CategoryFilter::CategoryFilter() { | |
| 1030 Initialize(CategoryFilter::kDefaultCategoryFilterString); | |
| 1031 } | |
| 1032 | |
| 1033 CategoryFilter::CategoryFilter(const std::string& filter_string) { | |
| 1034 if (!filter_string.empty()) | |
| 1035 Initialize(filter_string); | |
| 1036 else | |
| 1037 Initialize(CategoryFilter::kDefaultCategoryFilterString); | |
| 1038 } | |
| 1039 | |
| 1040 void CategoryFilter::Initialize(const std::string& filter_string) { | |
| 1041 // Tokenize list of categories, delimited by ','. | |
| 1042 StringTokenizer tokens(filter_string, ","); | |
| 1043 // Add each token to the appropriate list (included_,excluded_). | |
| 1044 while (tokens.GetNext()) { | |
| 1045 std::string category = tokens.token(); | |
| 1046 // Ignore empty categories. | |
| 1047 if(category.empty()) | |
|
dsinclair
2013/03/12 21:27:24
nit: space before (
rterrazas
2013/03/20 08:48:49
Done.
| |
| 1048 continue; | |
| 1049 // Excluded categories start with '-'. | |
| 1050 if (category.at(0) == '-') { | |
|
dsinclair
2013/03/12 21:27:24
I'm not seeing on a quick check, does StringTokeni
rterrazas
2013/03/20 08:48:49
It does not, we'd need to strip the string of whit
| |
| 1051 // Remove '-' from category string. | |
| 1052 category = category.substr(1); | |
| 1053 excluded_.push_back(category); | |
| 1054 } else { | |
| 1055 included_.push_back(category); | |
| 1056 } | |
| 1057 } | |
| 1058 } | |
| 1059 | |
| 1060 void CategoryFilter::WriteString(std::string* out, | |
| 1061 bool included) const { | |
| 1062 std::vector<std::string>::const_iterator ci; | |
| 1063 std::vector<std::string>::const_iterator end; | |
| 1064 if (included) { | |
| 1065 ci = included_.begin(); | |
| 1066 end = included_.end(); | |
| 1067 } else { | |
| 1068 ci = excluded_.begin(); | |
| 1069 end = excluded_.end(); | |
| 1070 } | |
| 1071 | |
| 1072 // Prepend commas for all excluded categories IF we have included categories. | |
| 1073 bool prepend_comma_for_first_excluded = !included && !included_.empty(); | |
| 1074 int token_cnt = 0; | |
| 1075 for (; ci != end; ++ci) { | |
| 1076 if (token_cnt++ > 0 || prepend_comma_for_first_excluded) | |
|
dsinclair
2013/03/12 21:27:24
Can we move the token_cnt++ out to after the if st
rterrazas
2013/03/20 08:48:49
Done.
| |
| 1077 StringAppendF(out, ","); | |
| 1078 StringAppendF(out, "%s%s", (included ? "" : "-"), ci->c_str()); | |
| 1079 } | |
| 1080 } | |
| 1081 | |
| 1082 std::string CategoryFilter::ToString() const { | |
| 1083 std::string filter_string; | |
| 1084 WriteString(&filter_string, true); | |
| 1085 WriteString(&filter_string, false); | |
| 1086 | |
| 1087 return filter_string; | |
| 1088 } | |
| 1089 | |
| 1090 bool CategoryFilter::IsCategoryGroupEnabled( | |
| 1091 const char* category_group_name) const { | |
| 1092 // TraceLog should call this method only as part of enabling/disabling | |
| 1093 // categories. | |
| 1094 std::vector<std::string>::const_iterator ci = included_.begin(); | |
| 1095 for (; ci != included_.end(); ++ci) { | |
| 1096 if (DoesCategoryGroupContainCategory(category_group_name, ci->c_str())) | |
| 1097 return true; | |
| 1098 } | |
| 1099 ci = excluded_.begin(); | |
| 1100 for (; ci != excluded_.end(); ++ci) { | |
| 1101 if (DoesCategoryGroupContainCategory(category_group_name, ci->c_str())) | |
| 1102 return false; | |
| 1103 } | |
| 1104 // If the category group is not excluded, and there are no included patterns | |
| 1105 // we consider this pattern enabled. | |
| 1106 return included_.empty(); | |
| 1107 } | |
| 1108 | |
| 1109 void CategoryFilter::Merge(const CategoryFilter& nested_filter) { | |
| 1110 included_.insert(included_.end(), | |
| 1111 nested_filter.included_.begin(), | |
| 1112 nested_filter.included_.end()); | |
| 1113 excluded_.insert(excluded_.end(), | |
| 1114 nested_filter.excluded_.begin(), | |
| 1115 nested_filter.excluded_.end()); | |
| 1116 } | |
| 1117 | |
| 1118 bool CategoryFilter::HasAllowedPatterns() const { | |
|
dsinclair
2013/03/12 21:27:24
Would HasIncludedPatterns be a better name then Al
rterrazas
2013/03/20 08:48:49
Yeah, I think had named it originally to HasInclud
| |
| 1119 return !included_.empty(); | |
| 1120 } | |
| 1121 | |
| 1122 void CategoryFilter::Clear() { | |
| 1123 included_.clear(); | |
| 1124 excluded_.clear(); | |
| 1125 } | |
| 1126 | |
| 1058 } // namespace debug | 1127 } // namespace debug |
| 1059 } // namespace base | 1128 } // namespace base |
| 1060 | 1129 |
| 1061 namespace trace_event_internal { | 1130 namespace trace_event_internal { |
| 1062 | 1131 |
| 1063 ScopedTrace::ScopedTrace( | 1132 ScopedTrace::ScopedTrace( |
| 1064 TRACE_EVENT_API_ATOMIC_WORD* event_uid, const char* name) { | 1133 TRACE_EVENT_API_ATOMIC_WORD* event_uid, const char* name) { |
| 1065 category_enabled_ = | 1134 category_enabled_ = |
| 1066 reinterpret_cast<const unsigned char*>(TRACE_EVENT_API_ATOMIC_LOAD( | 1135 reinterpret_cast<const unsigned char*>(TRACE_EVENT_API_ATOMIC_LOAD( |
| 1067 *event_uid)); | 1136 *event_uid)); |
| 1068 if (!category_enabled_) { | 1137 if (!category_enabled_) { |
| 1069 category_enabled_ = TRACE_EVENT_API_GET_CATEGORY_ENABLED("gpu"); | 1138 category_enabled_ = TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED("gpu"); |
| 1070 TRACE_EVENT_API_ATOMIC_STORE( | 1139 TRACE_EVENT_API_ATOMIC_STORE( |
| 1071 *event_uid, | 1140 *event_uid, |
| 1072 reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>(category_enabled_)); | 1141 reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>(category_enabled_)); |
| 1073 } | 1142 } |
| 1074 if (*category_enabled_) { | 1143 if (*category_enabled_) { |
| 1075 name_ = name; | 1144 name_ = name; |
| 1076 TRACE_EVENT_API_ADD_TRACE_EVENT( | 1145 TRACE_EVENT_API_ADD_TRACE_EVENT( |
| 1077 TRACE_EVENT_PHASE_BEGIN, // phase | 1146 TRACE_EVENT_PHASE_BEGIN, // phase |
| 1078 category_enabled_, // category enabled | 1147 category_enabled_, // category enabled |
| 1079 name, // name | 1148 name, // name |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 1098 0, // num_args | 1167 0, // num_args |
| 1099 NULL, // arg_names | 1168 NULL, // arg_names |
| 1100 NULL, // arg_types | 1169 NULL, // arg_types |
| 1101 NULL, // arg_values | 1170 NULL, // arg_values |
| 1102 TRACE_EVENT_FLAG_NONE); // flags | 1171 TRACE_EVENT_FLAG_NONE); // flags |
| 1103 } | 1172 } |
| 1104 } | 1173 } |
| 1105 | 1174 |
| 1106 } // namespace trace_event_internal | 1175 } // namespace trace_event_internal |
| 1107 | 1176 |
| OLD | NEW |