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

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

Issue 12150004: Category group support/Renamings. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Fixed review comments + a few improvements. Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/debug/trace_event_impl.h" 5 #include "base/debug/trace_event_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/debug/leak_annotations.h" 10 #include "base/debug/leak_annotations.h"
(...skipping 28 matching lines...) Expand all
39 }; 39 };
40 40
41 namespace base { 41 namespace base {
42 namespace debug { 42 namespace debug {
43 43
44 // Controls the number of trace events we will buffer in-memory 44 // Controls the number of trace events we will buffer in-memory
45 // before throwing them away. 45 // before throwing them away.
46 const size_t kTraceEventBufferSize = 500000; 46 const size_t kTraceEventBufferSize = 500000;
47 const size_t kTraceEventBatchSize = 1000; 47 const size_t kTraceEventBatchSize = 1000;
48 48
49 #define TRACE_EVENT_MAX_CATEGORIES 100 49 #define MAX_CATEGORY_GROUPS 100
50 50
51 namespace { 51 namespace {
52 52
53 // Parallel arrays g_categories and g_category_enabled are separate so that 53 // Parallel arrays g_category_groups and g_category_group_enabled are separate
54 // a pointer to a member of g_category_enabled can be easily converted to an 54 // so that a pointer to a member of g_category_group_enabled can be easily
55 // index into g_categories. This allows macros to deal only with char enabled 55 // converted to an index into g_category_groups. This allows macros to deal
56 // pointers from g_category_enabled, and we can convert internally to determine 56 // only with char enabled pointers from g_category_group_enabled, and we can
57 // the category name from the char enabled pointer. 57 // convert internally to determine the category name from the char enabled
58 const char* g_categories[TRACE_EVENT_MAX_CATEGORIES] = { 58 // pointer.
59 const char* g_category_groups[MAX_CATEGORY_GROUPS] = {
59 "tracing already shutdown", 60 "tracing already shutdown",
60 "tracing categories exhausted; must increase TRACE_EVENT_MAX_CATEGORIES", 61 "tracing categories exhausted; must increase MAX_CATEGORY_GROUPS",
61 "__metadata", 62 "__metadata",
62 }; 63 };
63 // The enabled flag is char instead of bool so that the API can be used from C. 64 // The enabled flag is char instead of bool so that the API can be used from C.
64 unsigned char g_category_enabled[TRACE_EVENT_MAX_CATEGORIES] = { 0 }; 65 unsigned char g_category_group_enabled[MAX_CATEGORY_GROUPS] = { 0 };
65 const int g_category_already_shutdown = 0; 66 const int g_category_already_shutdown = 0;
66 const int g_category_categories_exhausted = 1; 67 const int g_category_categories_exhausted = 1;
67 const int g_category_metadata = 2; 68 const int g_category_metadata = 2;
68 int g_category_index = 3; // skip initial 3 categories 69 int g_category_index = 3; // skip initial 3 categories
69 70
70 // The name of the current thread. This is used to decide if the current 71 // The name of the current thread. This is used to decide if the current
71 // thread name has changed. We combine all the seen thread names into the 72 // thread name has changed. We combine all the seen thread names into the
72 // output name for the thread. 73 // output name for the thread.
73 LazyInstance<ThreadLocalPointer<const char> >::Leaky 74 LazyInstance<ThreadLocalPointer<const char> >::Leaky
74 g_current_thread_name = LAZY_INSTANCE_INITIALIZER; 75 g_current_thread_name = LAZY_INSTANCE_INITIALIZER;
(...skipping 22 matching lines...) Expand all
97 DCHECK_LE(static_cast<int>(written), end - *buffer); 98 DCHECK_LE(static_cast<int>(written), end - *buffer);
98 *member = *buffer; 99 *member = *buffer;
99 *buffer += written; 100 *buffer += written;
100 } 101 }
101 } 102 }
102 103
103 } // namespace 104 } // namespace
104 105
105 TraceEvent::TraceEvent() 106 TraceEvent::TraceEvent()
106 : id_(0u), 107 : id_(0u),
107 category_enabled_(NULL), 108 category_group_enabled_(NULL),
108 name_(NULL), 109 name_(NULL),
109 thread_id_(0), 110 thread_id_(0),
110 phase_(TRACE_EVENT_PHASE_BEGIN), 111 phase_(TRACE_EVENT_PHASE_BEGIN),
111 flags_(0) { 112 flags_(0) {
112 arg_names_[0] = NULL; 113 arg_names_[0] = NULL;
113 arg_names_[1] = NULL; 114 arg_names_[1] = NULL;
114 memset(arg_values_, 0, sizeof(arg_values_)); 115 memset(arg_values_, 0, sizeof(arg_values_));
115 } 116 }
116 117
117 TraceEvent::TraceEvent(int thread_id, 118 TraceEvent::TraceEvent(int thread_id,
118 TimeTicks timestamp, 119 TimeTicks timestamp,
119 char phase, 120 char phase,
120 const unsigned char* category_enabled, 121 const unsigned char* category_group_enabled,
121 const char* name, 122 const char* name,
122 unsigned long long id, 123 unsigned long long id,
123 int num_args, 124 int num_args,
124 const char** arg_names, 125 const char** arg_names,
125 const unsigned char* arg_types, 126 const unsigned char* arg_types,
126 const unsigned long long* arg_values, 127 const unsigned long long* arg_values,
127 unsigned char flags) 128 unsigned char flags)
128 : timestamp_(timestamp), 129 : timestamp_(timestamp),
129 id_(id), 130 id_(id),
130 category_enabled_(category_enabled), 131 category_group_enabled_(category_group_enabled),
131 name_(name), 132 name_(name),
132 thread_id_(thread_id), 133 thread_id_(thread_id),
133 phase_(phase), 134 phase_(phase),
134 flags_(flags) { 135 flags_(flags) {
135 // Clamp num_args since it may have been set by a third_party library. 136 // Clamp num_args since it may have been set by a third_party library.
136 num_args = (num_args > kTraceMaxNumArgs) ? kTraceMaxNumArgs : num_args; 137 num_args = (num_args > kTraceMaxNumArgs) ? kTraceMaxNumArgs : num_args;
137 int i = 0; 138 int i = 0;
138 for (; i < num_args; ++i) { 139 for (; i < num_args; ++i) {
139 arg_names_[i] = arg_names[i]; 140 arg_names_[i] = arg_names[i];
140 arg_values_[i].as_uint = arg_values[i]; 141 arg_values_[i].as_uint = arg_values[i];
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 for (size_t i = 0; i < count && start + i < events.size(); ++i) { 239 for (size_t i = 0; i < count && start + i < events.size(); ++i) {
239 if (i > 0) 240 if (i > 0)
240 *out += ","; 241 *out += ",";
241 events[i + start].AppendAsJSON(out); 242 events[i + start].AppendAsJSON(out);
242 } 243 }
243 } 244 }
244 245
245 void TraceEvent::AppendAsJSON(std::string* out) const { 246 void TraceEvent::AppendAsJSON(std::string* out) const {
246 int64 time_int64 = timestamp_.ToInternalValue(); 247 int64 time_int64 = timestamp_.ToInternalValue();
247 int process_id = TraceLog::GetInstance()->process_id(); 248 int process_id = TraceLog::GetInstance()->process_id();
248 // Category name checked at category creation time. 249 // Category group checked at category creation time.
249 DCHECK(!strchr(name_, '"')); 250 DCHECK(!strchr(name_, '"'));
250 StringAppendF(out, 251 StringAppendF(out,
251 "{\"cat\":\"%s\",\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64 "," 252 "{\"cat\":\"%s\",\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64 ","
252 "\"ph\":\"%c\",\"name\":\"%s\",\"args\":{", 253 "\"ph\":\"%c\",\"name\":\"%s\",\"args\":{",
253 TraceLog::GetCategoryName(category_enabled_), 254 TraceLog::GetCategoryGroupName(category_group_enabled_),
254 process_id, 255 process_id,
255 thread_id_, 256 thread_id_,
256 time_int64, 257 time_int64,
257 phase_, 258 phase_,
258 name_); 259 name_);
259 260
260 // Output argument names and values, stop at first NULL argument name. 261 // Output argument names and values, stop at first NULL argument name.
261 for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) { 262 for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) {
262 if (i > 0) 263 if (i > 0)
263 *out += ","; 264 *out += ",";
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 TraceLog::TraceLog() 381 TraceLog::TraceLog()
381 : enable_count_(0), 382 : enable_count_(0),
382 dispatching_to_observer_list_(false), 383 dispatching_to_observer_list_(false),
383 watch_category_(NULL), 384 watch_category_(NULL),
384 trace_options_(RECORD_UNTIL_FULL) { 385 trace_options_(RECORD_UNTIL_FULL) {
385 // Trace is enabled or disabled on one thread while other threads are 386 // Trace is enabled or disabled on one thread while other threads are
386 // accessing the enabled flag. We don't care whether edge-case events are 387 // accessing the enabled flag. We don't care whether edge-case events are
387 // traced or not, so we allow races on the enabled flag to keep the trace 388 // traced or not, so we allow races on the enabled flag to keep the trace
388 // macros fast. 389 // macros fast.
389 // TODO(jbates): ANNOTATE_BENIGN_RACE_SIZED crashes windows TSAN bots: 390 // TODO(jbates): ANNOTATE_BENIGN_RACE_SIZED crashes windows TSAN bots:
390 // ANNOTATE_BENIGN_RACE_SIZED(g_category_enabled, sizeof(g_category_enabled), 391 // ANNOTATE_BENIGN_RACE_SIZED(g_category_group_enabled,
391 // "trace_event category enabled"); 392 // sizeof(g_category_group_enabled),
392 for (int i = 0; i < TRACE_EVENT_MAX_CATEGORIES; ++i) { 393 // "trace_event category enabled");
393 ANNOTATE_BENIGN_RACE(&g_category_enabled[i], 394 for (int i = 0; i < MAX_CATEGORY_GROUPS; ++i) {
395 ANNOTATE_BENIGN_RACE(&g_category_group_enabled[i],
394 "trace_event category enabled"); 396 "trace_event category enabled");
395 } 397 }
396 #if defined(OS_NACL) // NaCl shouldn't expose the process id. 398 #if defined(OS_NACL) // NaCl shouldn't expose the process id.
397 SetProcessID(0); 399 SetProcessID(0);
398 #else 400 #else
399 SetProcessID(static_cast<int>(GetCurrentProcId())); 401 SetProcessID(static_cast<int>(GetCurrentProcId()));
400 #endif 402 #endif
401 } 403 }
402 404
403 TraceLog::~TraceLog() { 405 TraceLog::~TraceLog() {
404 } 406 }
405 407
406 const unsigned char* TraceLog::GetCategoryEnabled(const char* name) { 408 const unsigned char* TraceLog::GetCategoryGroupEnabled(
409 const char* category_group) {
407 TraceLog* tracelog = GetInstance(); 410 TraceLog* tracelog = GetInstance();
408 if (!tracelog) { 411 if (!tracelog) {
409 DCHECK(!g_category_enabled[g_category_already_shutdown]); 412 DCHECK(!g_category_group_enabled[g_category_already_shutdown]);
410 return &g_category_enabled[g_category_already_shutdown]; 413 return &g_category_group_enabled[g_category_already_shutdown];
411 } 414 }
412 return tracelog->GetCategoryEnabledInternal(name); 415 return tracelog->GetCategoryGroupEnabledInternal(category_group);
413 } 416 }
414 417
415 const char* TraceLog::GetCategoryName(const unsigned char* category_enabled) { 418 const char* TraceLog::GetCategoryGroupName(
416 // Calculate the index of the category by finding category_enabled in 419 const unsigned char* category_group_enabled) {
417 // g_category_enabled array. 420 // Calculate the index of the category group by finding
418 uintptr_t category_begin = reinterpret_cast<uintptr_t>(g_category_enabled); 421 // category_group_enabled in g_category_group_enabled array.
419 uintptr_t category_ptr = reinterpret_cast<uintptr_t>(category_enabled); 422 uintptr_t category_begin =
423 reinterpret_cast<uintptr_t>(g_category_group_enabled);
424 uintptr_t category_ptr = reinterpret_cast<uintptr_t>(category_group_enabled);
420 DCHECK(category_ptr >= category_begin && 425 DCHECK(category_ptr >= category_begin &&
421 category_ptr < reinterpret_cast<uintptr_t>(g_category_enabled + 426 category_ptr < reinterpret_cast<uintptr_t>(
422 TRACE_EVENT_MAX_CATEGORIES)) << 427 g_category_group_enabled + MAX_CATEGORY_GROUPS)) <<
423 "out of bounds category pointer"; 428 "out of bounds category pointer";
424 uintptr_t category_index = 429 uintptr_t category_index =
425 (category_ptr - category_begin) / sizeof(g_category_enabled[0]); 430 (category_ptr - category_begin) / sizeof(g_category_group_enabled[0]);
426 return g_categories[category_index]; 431 return g_category_groups[category_index];
427 } 432 }
428 433
429 static void EnableMatchingCategory(int category_index, 434 void TraceLog::EnableIncludedCategoryGroup(int category_index) {
430 const std::vector<std::string>& patterns, 435 bool is_enabled = category_filter_.IsCategoryGroupEnabled(
431 unsigned char matched_value, 436 g_category_groups[category_index]);
432 unsigned char unmatched_value) { 437 g_category_group_enabled[category_index] =
433 std::vector<std::string>::const_iterator ci = patterns.begin(); 438 is_enabled ? TraceLog::CATEGORY_ENABLED : 0;
434 bool is_match = false;
435 for (; ci != patterns.end(); ++ci) {
436 is_match = MatchPattern(g_categories[category_index], ci->c_str());
437 if (is_match)
438 break;
439 }
440 g_category_enabled[category_index] = is_match ?
441 matched_value : unmatched_value;
442 } 439 }
443 440
444 // Enable/disable each category based on the category filters in |patterns|. 441 void TraceLog::EnableIncludedCategoryGroups() {
445 // If the category name matches one of the patterns, its enabled status is set
446 // to |matched_value|. Otherwise its enabled status is set to |unmatched_value|.
447 static void EnableMatchingCategories(const std::vector<std::string>& patterns,
448 unsigned char matched_value,
449 unsigned char unmatched_value) {
450 for (int i = 0; i < g_category_index; i++) 442 for (int i = 0; i < g_category_index; i++)
451 EnableMatchingCategory(i, patterns, matched_value, unmatched_value); 443 EnableIncludedCategoryGroup(i);
452 } 444 }
453 445
454 const unsigned char* TraceLog::GetCategoryEnabledInternal(const char* name) { 446 const unsigned char* TraceLog::GetCategoryGroupEnabledInternal(
447 const char* category_group) {
448 DCHECK(!strchr(category_group, '"')) <<
449 "Category groups may not contain double quote";
455 AutoLock lock(lock_); 450 AutoLock lock(lock_);
456 DCHECK(!strchr(name, '"')) << "Category names may not contain double quote";
457 451
458 unsigned char* category_enabled = NULL; 452 unsigned char* category_group_enabled = NULL;
459 // Search for pre-existing category matching this name 453 // Search for pre-existing category group.
460 for (int i = 0; i < g_category_index; i++) { 454 for (int i = 0; i < g_category_index; i++) {
461 if (strcmp(g_categories[i], name) == 0) { 455 if (strcmp(g_category_groups[i], category_group) == 0) {
462 category_enabled = &g_category_enabled[i]; 456 category_group_enabled = &g_category_group_enabled[i];
463 break; 457 break;
464 } 458 }
465 } 459 }
466 460
467 if (!category_enabled) { 461 if (!category_group_enabled) {
468 // Create a new category 462 // Create a new category group
469 DCHECK(g_category_index < TRACE_EVENT_MAX_CATEGORIES) << 463 DCHECK(g_category_index < MAX_CATEGORY_GROUPS) <<
470 "must increase TRACE_EVENT_MAX_CATEGORIES"; 464 "must increase MAX_CATEGORY_GROUPS";
471 if (g_category_index < TRACE_EVENT_MAX_CATEGORIES) { 465 if (g_category_index < MAX_CATEGORY_GROUPS) {
472 int new_index = g_category_index++; 466 int new_index = g_category_index++;
473 // Don't hold on to the name pointer, so that we can create categories 467 // Don't hold on to the category_group pointer, so that we can create
474 // with strings not known at compile time (this is required by 468 // category groups with strings not known at compile time (this is
475 // SetWatchEvent). 469 // required by SetWatchEvent).
476 const char* new_name = strdup(name); 470 const char* new_group = strdup(category_group);
477 ANNOTATE_LEAKING_OBJECT_PTR(new_name); 471 ANNOTATE_LEAKING_OBJECT_PTR(new_group);
478 g_categories[new_index] = new_name; 472 g_category_groups[new_index] = new_group;
479 DCHECK(!g_category_enabled[new_index]); 473 DCHECK(!g_category_group_enabled[new_index]);
480 if (enable_count_) { 474 if (enable_count_) {
481 // Note that if both included and excluded_categories are empty, the 475 // Note that if both included and excluded patterns in the
482 // else clause below excludes nothing, thereby enabling this category. 476 // CategoryFilter are empty, we exclude nothing,
483 if (!included_categories_.empty()) { 477 // thereby enabling this category group.
484 EnableMatchingCategory(new_index, included_categories_, 478 EnableIncludedCategoryGroup(new_index);
485 CATEGORY_ENABLED, 0);
486 } else {
487 EnableMatchingCategory(new_index, excluded_categories_,
488 0, CATEGORY_ENABLED);
489 }
490 } else { 479 } else {
491 g_category_enabled[new_index] = 0; 480 g_category_group_enabled[new_index] = 0;
492 } 481 }
493 category_enabled = &g_category_enabled[new_index]; 482 category_group_enabled = &g_category_group_enabled[new_index];
494 } else { 483 } else {
495 category_enabled = &g_category_enabled[g_category_categories_exhausted]; 484 category_group_enabled =
485 &g_category_group_enabled[g_category_categories_exhausted];
496 } 486 }
497 } 487 }
498 #if defined(OS_ANDROID) 488 #if defined(OS_ANDROID)
499 ApplyATraceEnabledFlag(category_enabled); 489 ApplyATraceEnabledFlag(category_group_enabled);
500 #endif 490 #endif
501 return category_enabled; 491 return category_group_enabled;
502 } 492 }
503 493
504 void TraceLog::GetKnownCategories(std::vector<std::string>* categories) { 494 void TraceLog::GetKnownCategoryGroups(
495 std::vector<std::string>* category_groups) {
505 AutoLock lock(lock_); 496 AutoLock lock(lock_);
506 for (int i = 0; i < g_category_index; i++) 497 for (int i = 0; i < g_category_index; i++)
507 categories->push_back(g_categories[i]); 498 category_groups->push_back(g_category_groups[i]);
508 } 499 }
509 500
510 void TraceLog::SetEnabled(const std::vector<std::string>& included_categories, 501 void TraceLog::SetEnabled(const CategoryFilter& category_filter,
511 const std::vector<std::string>& excluded_categories,
512 Options options) { 502 Options options) {
513 AutoLock lock(lock_); 503 AutoLock lock(lock_);
514 504
515 if (enable_count_++ > 0) { 505 if (enable_count_++ > 0) {
516 if (options != trace_options_) { 506 if (options != trace_options_) {
517 DLOG(ERROR) << "Attemting to re-enable tracing with a different " 507 DLOG(ERROR) << "Attemting to re-enable tracing with a different "
518 << "set of options."; 508 << "set of options.";
519 } 509 }
520 510
521 // Tracing is already enabled, so just merge in enabled categories. 511 // Tracing is already enabled, so just merge in enabled categories.
522 // We only expand the set of enabled categories upon nested SetEnable(). 512 // We only expand the set of enabled categories upon nested SetEnable().
523 if (!included_categories_.empty() && !included_categories.empty()) { 513 if (category_filter_.HasAllowedPatterns() &&
524 included_categories_.insert(included_categories_.end(), 514 category_filter.HasAllowedPatterns()) {
525 included_categories.begin(), 515 category_filter_.Merge(category_filter);
526 included_categories.end());
527 EnableMatchingCategories(included_categories_, CATEGORY_ENABLED, 0);
528 } else { 516 } else {
529 // If either old or new included categories are empty, allow all events. 517 // If either old or new included categories are empty, allow all events.
530 included_categories_.clear(); 518 category_filter_.Clear();
531 excluded_categories_.clear();
532 EnableMatchingCategories(excluded_categories_, 0, CATEGORY_ENABLED);
533 } 519 }
520 EnableIncludedCategoryGroups();
534 return; 521 return;
535 } 522 }
536 trace_options_ = options; 523 trace_options_ = options;
537 524
538 if (dispatching_to_observer_list_) { 525 if (dispatching_to_observer_list_) {
539 DLOG(ERROR) << 526 DLOG(ERROR) <<
540 "Cannot manipulate TraceLog::Enabled state from an observer."; 527 "Cannot manipulate TraceLog::Enabled state from an observer.";
541 return; 528 return;
542 } 529 }
543 530
544 dispatching_to_observer_list_ = true; 531 dispatching_to_observer_list_ = true;
545 FOR_EACH_OBSERVER(EnabledStateChangedObserver, enabled_state_observer_list_, 532 FOR_EACH_OBSERVER(EnabledStateChangedObserver, enabled_state_observer_list_,
546 OnTraceLogWillEnable()); 533 OnTraceLogWillEnable());
547 dispatching_to_observer_list_ = false; 534 dispatching_to_observer_list_ = false;
548 535
549 logged_events_.reserve(1024); 536 logged_events_.reserve(1024);
550 included_categories_ = included_categories; 537 category_filter_ = CategoryFilter(category_filter);
551 excluded_categories_ = excluded_categories; 538 EnableIncludedCategoryGroups();
552 // Note that if both included and excluded_categories are empty, the else
553 // clause below excludes nothing, thereby enabling all categories.
554 if (!included_categories_.empty())
555 EnableMatchingCategories(included_categories_, CATEGORY_ENABLED, 0);
556 else
557 EnableMatchingCategories(excluded_categories_, 0, CATEGORY_ENABLED);
558 } 539 }
559 540
560 void TraceLog::SetEnabled(const std::string& categories, Options options) { 541 const CategoryFilter& TraceLog::GetCurrentCategoryFilter() {
561 std::vector<std::string> included, excluded;
562 // Tokenize list of categories, delimited by ','.
563 StringTokenizer tokens(categories, ",");
564 while (tokens.GetNext()) {
565 bool is_included = true;
566 std::string category = tokens.token();
567 // Excluded categories start with '-'.
568 if (category.at(0) == '-') {
569 // Remove '-' from category string.
570 category = category.substr(1);
571 is_included = false;
572 }
573 if (is_included)
574 included.push_back(category);
575 else
576 excluded.push_back(category);
577 }
578 SetEnabled(included, excluded, options);
579 }
580
581 void TraceLog::GetEnabledTraceCategories(
582 std::vector<std::string>* included_out,
583 std::vector<std::string>* excluded_out) {
584 AutoLock lock(lock_); 542 AutoLock lock(lock_);
585 if (enable_count_) { 543 DCHECK(enable_count_ > 0);
586 *included_out = included_categories_; 544 return category_filter_;
587 *excluded_out = excluded_categories_;
588 }
589 } 545 }
590 546
591 void TraceLog::SetDisabled() { 547 void TraceLog::SetDisabled() {
592 AutoLock lock(lock_); 548 AutoLock lock(lock_);
593 DCHECK(enable_count_ > 0); 549 DCHECK(enable_count_ > 0);
594 if (--enable_count_ != 0) 550 if (--enable_count_ != 0)
595 return; 551 return;
596 552
597 if (dispatching_to_observer_list_) { 553 if (dispatching_to_observer_list_) {
598 DLOG(ERROR) 554 DLOG(ERROR)
599 << "Cannot manipulate TraceLog::Enabled state from an observer."; 555 << "Cannot manipulate TraceLog::Enabled state from an observer.";
600 return; 556 return;
601 } 557 }
602 558
603 dispatching_to_observer_list_ = true; 559 dispatching_to_observer_list_ = true;
604 FOR_EACH_OBSERVER(EnabledStateChangedObserver, enabled_state_observer_list_, 560 FOR_EACH_OBSERVER(EnabledStateChangedObserver, enabled_state_observer_list_,
605 OnTraceLogWillDisable()); 561 OnTraceLogWillDisable());
606 dispatching_to_observer_list_ = false; 562 dispatching_to_observer_list_ = false;
607 563
608 included_categories_.clear(); 564 category_filter_.Clear();
609 excluded_categories_.clear();
610 watch_category_ = NULL; 565 watch_category_ = NULL;
611 watch_event_name_ = ""; 566 watch_event_name_ = "";
612 for (int i = 0; i < g_category_index; i++) 567 for (int i = 0; i < g_category_index; i++)
613 g_category_enabled[i] = 0; 568 g_category_group_enabled[i] = 0;
614 AddThreadNameMetadataEvents(); 569 AddThreadNameMetadataEvents();
615 } 570 }
616 571
617 void TraceLog::SetEnabled(bool enabled, Options options) {
618 if (enabled)
619 SetEnabled(std::vector<std::string>(), std::vector<std::string>(), options);
620 else
621 SetDisabled();
622 }
623
624 void TraceLog::AddEnabledStateObserver(EnabledStateChangedObserver* listener) { 572 void TraceLog::AddEnabledStateObserver(EnabledStateChangedObserver* listener) {
625 enabled_state_observer_list_.AddObserver(listener); 573 enabled_state_observer_list_.AddObserver(listener);
626 } 574 }
627 575
628 void TraceLog::RemoveEnabledStateObserver( 576 void TraceLog::RemoveEnabledStateObserver(
629 EnabledStateChangedObserver* listener) { 577 EnabledStateChangedObserver* listener) {
630 enabled_state_observer_list_.RemoveObserver(listener); 578 enabled_state_observer_list_.RemoveObserver(listener);
631 } 579 }
632 580
633 float TraceLog::GetBufferPercentFull() const { 581 float TraceLog::GetBufferPercentFull() const {
(...skipping 20 matching lines...) Expand all
654 new RefCountedString(); 602 new RefCountedString();
655 TraceEvent::AppendEventsAsJSON(previous_logged_events, 603 TraceEvent::AppendEventsAsJSON(previous_logged_events,
656 i, 604 i,
657 kTraceEventBatchSize, 605 kTraceEventBatchSize,
658 &(json_events_str_ptr->data())); 606 &(json_events_str_ptr->data()));
659 cb.Run(json_events_str_ptr); 607 cb.Run(json_events_str_ptr);
660 } 608 }
661 } 609 }
662 610
663 void TraceLog::AddTraceEvent(char phase, 611 void TraceLog::AddTraceEvent(char phase,
664 const unsigned char* category_enabled, 612 const unsigned char* category_group_enabled,
665 const char* name, 613 const char* name,
666 unsigned long long id, 614 unsigned long long id,
667 int num_args, 615 int num_args,
668 const char** arg_names, 616 const char** arg_names,
669 const unsigned char* arg_types, 617 const unsigned char* arg_types,
670 const unsigned long long* arg_values, 618 const unsigned long long* arg_values,
671 unsigned char flags) { 619 unsigned char flags) {
672 int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); 620 int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
673 base::TimeTicks now = base::TimeTicks::NowFromSystemTraceTime(); 621 base::TimeTicks now = base::TimeTicks::NowFromSystemTraceTime();
674 AddTraceEventWithThreadIdAndTimestamp(phase, category_enabled, name, id, 622 AddTraceEventWithThreadIdAndTimestamp(phase, category_group_enabled, name, id,
675 thread_id, now, num_args, arg_names, 623 thread_id, now, num_args, arg_names,
676 arg_types, arg_values, flags); 624 arg_types, arg_values, flags);
677 } 625 }
678 626
679 void TraceLog::AddTraceEventWithThreadIdAndTimestamp( 627 void TraceLog::AddTraceEventWithThreadIdAndTimestamp(
680 char phase, 628 char phase,
681 const unsigned char* category_enabled, 629 const unsigned char* category_group_enabled,
682 const char* name, 630 const char* name,
683 unsigned long long id, 631 unsigned long long id,
684 int thread_id, 632 int thread_id,
685 const TimeTicks& timestamp, 633 const TimeTicks& timestamp,
686 int num_args, 634 int num_args,
687 const char** arg_names, 635 const char** arg_names,
688 const unsigned char* arg_types, 636 const unsigned char* arg_types,
689 const unsigned long long* arg_values, 637 const unsigned long long* arg_values,
690 unsigned char flags) { 638 unsigned char flags) {
691 DCHECK(name); 639 DCHECK(name);
692 640
693 #if defined(OS_ANDROID) 641 #if defined(OS_ANDROID)
694 SendToATrace(phase, GetCategoryName(category_enabled), name, 642 SendToATrace(phase, GetCategoryGroupName(category_group_enabled), name,
695 num_args, arg_names, arg_types, arg_values); 643 num_args, arg_names, arg_types, arg_values);
696 #endif 644 #endif
697 645
698 TimeTicks now = timestamp - time_offset_; 646 TimeTicks now = timestamp - time_offset_;
699 NotificationHelper notifier(this); 647 NotificationHelper notifier(this);
700 648
701 { 649 {
702 AutoLock lock(lock_); 650 AutoLock lock(lock_);
703 if (*category_enabled != CATEGORY_ENABLED) 651 if (*category_group_enabled != CATEGORY_ENABLED)
704 return; 652 return;
705 if (logged_events_.size() >= kTraceEventBufferSize) 653 if (logged_events_.size() >= kTraceEventBufferSize)
706 return; 654 return;
707 655
708 const char* new_name = ThreadIdNameManager::GetInstance()-> 656 const char* new_name = ThreadIdNameManager::GetInstance()->
709 GetName(thread_id); 657 GetName(thread_id);
710 // Check if the thread name has been set or changed since the previous 658 // Check if the thread name has been set or changed since the previous
711 // call (if any), but don't bother if the new name is empty. Note this will 659 // call (if any), but don't bother if the new name is empty. Note this will
712 // not detect a thread name change within the same char* buffer address: we 660 // not detect a thread name change within the same char* buffer address: we
713 // favor common case performance over corner case correctness. 661 // favor common case performance over corner case correctness.
(...skipping 19 matching lines...) Expand all
733 existing_name->second.append(new_name); 681 existing_name->second.append(new_name);
734 } 682 }
735 } 683 }
736 } 684 }
737 685
738 if (flags & TRACE_EVENT_FLAG_MANGLE_ID) 686 if (flags & TRACE_EVENT_FLAG_MANGLE_ID)
739 id ^= process_id_hash_; 687 id ^= process_id_hash_;
740 688
741 logged_events_.push_back( 689 logged_events_.push_back(
742 TraceEvent(thread_id, 690 TraceEvent(thread_id,
743 now, phase, category_enabled, name, id, 691 now, phase, category_group_enabled, name, id,
744 num_args, arg_names, arg_types, arg_values, 692 num_args, arg_names, arg_types, arg_values,
745 flags)); 693 flags));
746 694
747 if (logged_events_.size() == kTraceEventBufferSize) 695 if (logged_events_.size() == kTraceEventBufferSize)
748 notifier.AddNotificationWhileLocked(TRACE_BUFFER_FULL); 696 notifier.AddNotificationWhileLocked(TRACE_BUFFER_FULL);
749 697
750 if (watch_category_ == category_enabled && watch_event_name_ == name) 698 if (watch_category_ == category_group_enabled && watch_event_name_ == name)
751 notifier.AddNotificationWhileLocked(EVENT_WATCH_NOTIFICATION); 699 notifier.AddNotificationWhileLocked(EVENT_WATCH_NOTIFICATION);
752 } // release lock 700 } // release lock
753 701
754 notifier.SendNotificationIfAny(); 702 notifier.SendNotificationIfAny();
755 } 703 }
756 704
757 void TraceLog::AddTraceEventEtw(char phase, 705 void TraceLog::AddTraceEventEtw(char phase,
758 const char* name, 706 const char* name,
759 const void* id, 707 const void* id,
760 const char* extra) { 708 const char* extra) {
(...skipping 11 matching lines...) Expand all
772 { 720 {
773 #if defined(OS_WIN) 721 #if defined(OS_WIN)
774 TraceEventETWProvider::Trace(name, phase, id, extra); 722 TraceEventETWProvider::Trace(name, phase, id, extra);
775 #endif 723 #endif
776 INTERNAL_TRACE_EVENT_ADD(phase, "ETW Trace Event", name, 724 INTERNAL_TRACE_EVENT_ADD(phase, "ETW Trace Event", name,
777 TRACE_EVENT_FLAG_COPY, "id", id, "extra", extra); 725 TRACE_EVENT_FLAG_COPY, "id", id, "extra", extra);
778 } 726 }
779 727
780 void TraceLog::SetWatchEvent(const std::string& category_name, 728 void TraceLog::SetWatchEvent(const std::string& category_name,
781 const std::string& event_name) { 729 const std::string& event_name) {
782 const unsigned char* category = GetCategoryEnabled(category_name.c_str()); 730 const unsigned char* category = GetCategoryGroupEnabled(
731 category_name.c_str());
783 int notify_count = 0; 732 int notify_count = 0;
784 { 733 {
785 AutoLock lock(lock_); 734 AutoLock lock(lock_);
786 watch_category_ = category; 735 watch_category_ = category;
787 watch_event_name_ = event_name; 736 watch_event_name_ = event_name;
788 737
789 // First, search existing events for watch event because we want to catch it 738 // First, search existing events for watch event because we want to catch it
790 // even if it has already occurred. 739 // even if it has already occurred.
791 for (size_t i = 0u; i < logged_events_.size(); ++i) { 740 for (size_t i = 0u; i < logged_events_.size(); ++i) {
792 if (category == logged_events_[i].category_enabled() && 741 if (category == logged_events_[i].category_group_enabled() &&
793 strcmp(event_name.c_str(), logged_events_[i].name()) == 0) { 742 strcmp(event_name.c_str(), logged_events_[i].name()) == 0) {
794 ++notify_count; 743 ++notify_count;
795 } 744 }
796 } 745 }
797 } // release lock 746 } // release lock
798 747
799 // Send notification for each event found. 748 // Send notification for each event found.
800 for (int i = 0; i < notify_count; ++i) { 749 for (int i = 0; i < notify_count; ++i) {
801 NotificationHelper notifier(this); 750 NotificationHelper notifier(this);
802 lock_.Acquire(); 751 lock_.Acquire();
(...skipping 16 matching lines...) Expand all
819 it++) { 768 it++) {
820 if (!it->second.empty()) { 769 if (!it->second.empty()) {
821 int num_args = 1; 770 int num_args = 1;
822 const char* arg_name = "name"; 771 const char* arg_name = "name";
823 unsigned char arg_type; 772 unsigned char arg_type;
824 unsigned long long arg_value; 773 unsigned long long arg_value;
825 trace_event_internal::SetTraceValue(it->second, &arg_type, &arg_value); 774 trace_event_internal::SetTraceValue(it->second, &arg_type, &arg_value);
826 logged_events_.push_back( 775 logged_events_.push_back(
827 TraceEvent(it->first, 776 TraceEvent(it->first,
828 TimeTicks(), TRACE_EVENT_PHASE_METADATA, 777 TimeTicks(), TRACE_EVENT_PHASE_METADATA,
829 &g_category_enabled[g_category_metadata], 778 &g_category_group_enabled[g_category_metadata],
830 "thread_name", trace_event_internal::kNoEventId, 779 "thread_name", trace_event_internal::kNoEventId,
831 num_args, &arg_name, &arg_type, &arg_value, 780 num_args, &arg_name, &arg_type, &arg_value,
832 TRACE_EVENT_FLAG_NONE)); 781 TRACE_EVENT_FLAG_NONE));
833 } 782 }
834 } 783 }
835 } 784 }
836 785
837 void TraceLog::DeleteForTesting() { 786 void TraceLog::DeleteForTesting() {
838 DeleteTraceLogForTesting::Delete(); 787 DeleteTraceLogForTesting::Delete();
839 } 788 }
840 789
841 void TraceLog::Resurrect() { 790 void TraceLog::Resurrect() {
842 StaticMemorySingletonTraits<TraceLog>::Resurrect(); 791 StaticMemorySingletonTraits<TraceLog>::Resurrect();
843 } 792 }
844 793
845 void TraceLog::SetProcessID(int process_id) { 794 void TraceLog::SetProcessID(int process_id) {
846 process_id_ = process_id; 795 process_id_ = process_id;
847 // Create a FNV hash from the process ID for XORing. 796 // Create a FNV hash from the process ID for XORing.
848 // See http://isthe.com/chongo/tech/comp/fnv/ for algorithm details. 797 // See http://isthe.com/chongo/tech/comp/fnv/ for algorithm details.
849 unsigned long long offset_basis = 14695981039346656037ull; 798 unsigned long long offset_basis = 14695981039346656037ull;
850 unsigned long long fnv_prime = 1099511628211ull; 799 unsigned long long fnv_prime = 1099511628211ull;
851 unsigned long long pid = static_cast<unsigned long long>(process_id_); 800 unsigned long long pid = static_cast<unsigned long long>(process_id_);
852 process_id_hash_ = (offset_basis ^ pid) * fnv_prime; 801 process_id_hash_ = (offset_basis ^ pid) * fnv_prime;
853 } 802 }
854 803
855 void TraceLog::SetTimeOffset(TimeDelta offset) { 804 void TraceLog::SetTimeOffset(TimeDelta offset) {
856 time_offset_ = offset; 805 time_offset_ = offset;
857 } 806 }
858 807
808 static bool DoesCategoryGroupContainCategory(const char* category_group,
809 const char* category) {
810 DCHECK(category);
811 CStringTokenizer category_group_tokens(category_group,
812 category_group + strlen(category_group), ",");
813 while (category_group_tokens.GetNext()) {
814 std::string category_group_token = category_group_tokens.token();
815 // Don't allow empty tokens, nor tokens with leading or trailing space.
816 DCHECK(!category_group_token.empty() &&
817 category_group_token.at(0) != ' '&&
818 category_group_token.at(category_group_token.length() - 1) != ' ')
819 << "Disallowed category string";
820 if (MatchPattern(category_group_token.c_str(), category))
821 return true;
822 }
823 return false;
824 }
825
826 const char* CategoryFilter::kDefaultCategoryFilterString = "-*Debug,-*Test";
827
828 CategoryFilter::CategoryFilter() {
829 Initialize(CategoryFilter::kDefaultCategoryFilterString);
830 }
831
832 CategoryFilter::CategoryFilter(const std::string& filter_string) {
833 Initialize(filter_string);
834 }
835
836 void CategoryFilter::Initialize(const std::string& filter_string) {
837 // Tokenize list of categories, delimited by ','.
838 StringTokenizer tokens(filter_string, ",");
839 // Add each token to the appropriate list (included_,excluded_).
840 while (tokens.GetNext()) {
841 std::string category = tokens.token();
842 // Ignore empty categories.
843 if(category.empty())
844 continue;
845 // Excluded categories start with '-'.
846 if (category.at(0) == '-') {
847 // Remove '-' from category string.
848 category = category.substr(1);
849 excluded_.push_back(category);
850 } else {
851 included_.push_back(category);
852 }
853 }
854 }
855
856 void CategoryFilter::WriteString(std::string* out,
857 bool included) const {
858 std::vector<std::string>::const_iterator ci;
859 std::vector<std::string>::const_iterator end;
860 if (included) {
861 ci = included_.begin();
862 end = included_.end();
863 } else {
864 ci = excluded_.begin();
865 end = excluded_.end();
866 }
867
868 // Prepend commas for all excluded categories IF we have included categories.
869 bool prepend_comma_for_first_excluded = !included && !included_.empty();
870 int token_cnt = 0;
871 for (; ci != end; ++ci) {
872 if (token_cnt++ > 0 || prepend_comma_for_first_excluded)
873 StringAppendF(out, ",");
874 StringAppendF(out, "%s%s", (included ? "" : "-"), ci->c_str());
875 }
876 }
877
878 std::string CategoryFilter::ToString() const {
879 std::string filter_string;
880 WriteString(&filter_string, true);
881 WriteString(&filter_string, false);
882
883 return filter_string;
884 }
885
886 bool CategoryFilter::IsCategoryGroupEnabled(
887 const char* category_group_name) const {
888 // TraceLog should call this method only as part of enabling/disabling
889 // categories.
890 std::vector<std::string>::const_iterator ci = included_.begin();
891 for (; ci != included_.end(); ++ci) {
892 if (DoesCategoryGroupContainCategory(category_group_name, ci->c_str()))
893 return true;
894 }
895 ci = excluded_.begin();
896 for (; ci != excluded_.end(); ++ci) {
897 if (DoesCategoryGroupContainCategory(category_group_name, ci->c_str()))
898 return false;
899 }
900 // If the category group is not excluded, and there are no included patterns
901 // we consider this pattern enabled.
902 return included_.empty();
903 }
904
905 void CategoryFilter::Merge(const CategoryFilter& nested_filter) {
906 included_.insert(included_.end(),
907 nested_filter.included_.begin(),
908 nested_filter.included_.end());
909 excluded_.insert(excluded_.end(),
910 nested_filter.excluded_.begin(),
911 nested_filter.excluded_.end());
912 }
913
914 bool CategoryFilter::HasAllowedPatterns() const {
915 return !included_.empty();
916 }
917
918 void CategoryFilter::Clear() {
919 included_.clear();
920 excluded_.clear();
921 }
922
859 } // namespace debug 923 } // namespace debug
860 } // namespace base 924 } // namespace base
861 925
862 namespace trace_event_internal { 926 namespace trace_event_internal {
863 927
864 ScopedTrace::ScopedTrace( 928 ScopedTrace::ScopedTrace(
865 TRACE_EVENT_API_ATOMIC_WORD* event_uid, const char* name) { 929 TRACE_EVENT_API_ATOMIC_WORD* event_uid, const char* name) {
866 category_enabled_ = 930 category_enabled_ =
867 reinterpret_cast<const unsigned char*>(TRACE_EVENT_API_ATOMIC_LOAD( 931 reinterpret_cast<const unsigned char*>(TRACE_EVENT_API_ATOMIC_LOAD(
868 *event_uid)); 932 *event_uid));
869 if (!category_enabled_) { 933 if (!category_enabled_) {
870 category_enabled_ = TRACE_EVENT_API_GET_CATEGORY_ENABLED("gpu"); 934 category_enabled_ = TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED("gpu");
871 TRACE_EVENT_API_ATOMIC_STORE( 935 TRACE_EVENT_API_ATOMIC_STORE(
872 *event_uid, 936 *event_uid,
873 reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>(category_enabled_)); 937 reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>(category_enabled_));
874 } 938 }
875 if (*category_enabled_) { 939 if (*category_enabled_) {
876 name_ = name; 940 name_ = name;
877 TRACE_EVENT_API_ADD_TRACE_EVENT( 941 TRACE_EVENT_API_ADD_TRACE_EVENT(
878 TRACE_EVENT_PHASE_BEGIN, // phase 942 TRACE_EVENT_PHASE_BEGIN, // phase
879 category_enabled_, // category enabled 943 category_enabled_, // category enabled
880 name, // name 944 name, // name
(...skipping 18 matching lines...) Expand all
899 0, // num_args 963 0, // num_args
900 NULL, // arg_names 964 NULL, // arg_names
901 NULL, // arg_types 965 NULL, // arg_types
902 NULL, // arg_values 966 NULL, // arg_values
903 TRACE_EVENT_FLAG_NONE); // flags 967 TRACE_EVENT_FLAG_NONE); // flags
904 } 968 }
905 } 969 }
906 970
907 } // namespace trace_event_internal 971 } // namespace trace_event_internal
908 972
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698