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

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: More renamings and category filter cleanups. 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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 42
43 // Controls the number of trace events we will buffer in-memory 43 // Controls the number of trace events we will buffer in-memory
44 // before throwing them away. 44 // before throwing them away.
45 const size_t kTraceEventBufferSize = 500000; 45 const size_t kTraceEventBufferSize = 500000;
46 const size_t kTraceEventBatchSize = 1000; 46 const size_t kTraceEventBatchSize = 1000;
47 47
48 #define TRACE_EVENT_MAX_CATEGORIES 100 48 #define TRACE_EVENT_MAX_CATEGORIES 100
49 49
50 namespace { 50 namespace {
51 51
52 // Parallel arrays g_categories and g_category_enabled are separate so that 52 // Parallel arrays g_category_groups and g_category_group_enabled are separate
53 // a pointer to a member of g_category_enabled can be easily converted to an 53 // so that a pointer to a member of g_category_group_enabled can be easily
54 // index into g_categories. This allows macros to deal only with char enabled 54 // converted to an index into g_category_groups. This allows macros to deal
55 // pointers from g_category_enabled, and we can convert internally to determine 55 // only with char enabled pointers from g_category_group_enabled, and we can
56 // the category name from the char enabled pointer. 56 // convert internally to determine the category name from the char enabled
57 const char* g_categories[TRACE_EVENT_MAX_CATEGORIES] = { 57 // pointer.
58 const char* g_category_groups[TRACE_EVENT_MAX_CATEGORIES] = {
nduca 2013/02/21 06:02:36 MAX_CATEGORY_GROUPS
rterrazas 2013/02/25 05:55:02 Done.
58 "tracing already shutdown", 59 "tracing already shutdown",
59 "tracing categories exhausted; must increase TRACE_EVENT_MAX_CATEGORIES", 60 "tracing categories exhausted; must increase TRACE_EVENT_MAX_CATEGORIES",
60 "__metadata", 61 "__metadata",
61 }; 62 };
62 // The enabled flag is char instead of bool so that the API can be used from C. 63 // The enabled flag is char instead of bool so that the API can be used from C.
63 unsigned char g_category_enabled[TRACE_EVENT_MAX_CATEGORIES] = { 0 }; 64 unsigned char g_category_group_enabled[TRACE_EVENT_MAX_CATEGORIES] = { 0 };
64 const int g_category_already_shutdown = 0; 65 const int g_category_already_shutdown = 0;
65 const int g_category_categories_exhausted = 1; 66 const int g_category_categories_exhausted = 1;
66 const int g_category_metadata = 2; 67 const int g_category_metadata = 2;
67 int g_category_index = 3; // skip initial 3 categories 68 int g_category_index = 3; // skip initial 3 categories
68 69
69 // The name of the current thread. This is used to decide if the current 70 // The name of the current thread. This is used to decide if the current
70 // thread name has changed. We combine all the seen thread names into the 71 // thread name has changed. We combine all the seen thread names into the
71 // output name for the thread. 72 // output name for the thread.
72 LazyInstance<ThreadLocalPointer<const char> >::Leaky 73 LazyInstance<ThreadLocalPointer<const char> >::Leaky
73 g_current_thread_name = LAZY_INSTANCE_INITIALIZER; 74 g_current_thread_name = LAZY_INSTANCE_INITIALIZER;
(...skipping 20 matching lines...) Expand all
94 DCHECK_LE(static_cast<int>(written), end - *buffer); 95 DCHECK_LE(static_cast<int>(written), end - *buffer);
95 *member = *buffer; 96 *member = *buffer;
96 *buffer += written; 97 *buffer += written;
97 } 98 }
98 } 99 }
99 100
100 } // namespace 101 } // namespace
101 102
102 TraceEvent::TraceEvent() 103 TraceEvent::TraceEvent()
103 : id_(0u), 104 : id_(0u),
104 category_enabled_(NULL), 105 category_group_enabled_(NULL),
105 name_(NULL), 106 name_(NULL),
106 thread_id_(0), 107 thread_id_(0),
107 phase_(TRACE_EVENT_PHASE_BEGIN), 108 phase_(TRACE_EVENT_PHASE_BEGIN),
108 flags_(0) { 109 flags_(0) {
109 arg_names_[0] = NULL; 110 arg_names_[0] = NULL;
110 arg_names_[1] = NULL; 111 arg_names_[1] = NULL;
111 memset(arg_values_, 0, sizeof(arg_values_)); 112 memset(arg_values_, 0, sizeof(arg_values_));
112 } 113 }
113 114
114 TraceEvent::TraceEvent(int thread_id, 115 TraceEvent::TraceEvent(int thread_id,
115 TimeTicks timestamp, 116 TimeTicks timestamp,
116 char phase, 117 char phase,
117 const unsigned char* category_enabled, 118 const unsigned char* category_group_enabled,
118 const char* name, 119 const char* name,
119 unsigned long long id, 120 unsigned long long id,
120 int num_args, 121 int num_args,
121 const char** arg_names, 122 const char** arg_names,
122 const unsigned char* arg_types, 123 const unsigned char* arg_types,
123 const unsigned long long* arg_values, 124 const unsigned long long* arg_values,
124 unsigned char flags) 125 unsigned char flags)
125 : timestamp_(timestamp), 126 : timestamp_(timestamp),
126 id_(id), 127 id_(id),
127 category_enabled_(category_enabled), 128 category_group_enabled_(category_group_enabled),
128 name_(name), 129 name_(name),
129 thread_id_(thread_id), 130 thread_id_(thread_id),
130 phase_(phase), 131 phase_(phase),
131 flags_(flags) { 132 flags_(flags) {
132 // Clamp num_args since it may have been set by a third_party library. 133 // Clamp num_args since it may have been set by a third_party library.
133 num_args = (num_args > kTraceMaxNumArgs) ? kTraceMaxNumArgs : num_args; 134 num_args = (num_args > kTraceMaxNumArgs) ? kTraceMaxNumArgs : num_args;
134 int i = 0; 135 int i = 0;
135 for (; i < num_args; ++i) { 136 for (; i < num_args; ++i) {
136 arg_names_[i] = arg_names[i]; 137 arg_names_[i] = arg_names[i];
137 arg_values_[i].as_uint = arg_values[i]; 138 arg_values_[i].as_uint = arg_values[i];
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
235 for (size_t i = 0; i < count && start + i < events.size(); ++i) { 236 for (size_t i = 0; i < count && start + i < events.size(); ++i) {
236 if (i > 0) 237 if (i > 0)
237 *out += ","; 238 *out += ",";
238 events[i + start].AppendAsJSON(out); 239 events[i + start].AppendAsJSON(out);
239 } 240 }
240 } 241 }
241 242
242 void TraceEvent::AppendAsJSON(std::string* out) const { 243 void TraceEvent::AppendAsJSON(std::string* out) const {
243 int64 time_int64 = timestamp_.ToInternalValue(); 244 int64 time_int64 = timestamp_.ToInternalValue();
244 int process_id = TraceLog::GetInstance()->process_id(); 245 int process_id = TraceLog::GetInstance()->process_id();
245 // Category name checked at category creation time. 246 // Category group checked at category creation time.
246 DCHECK(!strchr(name_, '"')); 247 DCHECK(!strchr(name_, '"'));
247 StringAppendF(out, 248 StringAppendF(out,
248 "{\"cat\":\"%s\",\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64 "," 249 "{\"cat\":\"%s\",\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64 ","
249 "\"ph\":\"%c\",\"name\":\"%s\",\"args\":{", 250 "\"ph\":\"%c\",\"name\":\"%s\",\"args\":{",
250 TraceLog::GetCategoryName(category_enabled_), 251 TraceLog::GetCategoryGroupName(category_group_enabled_),
251 process_id, 252 process_id,
252 thread_id_, 253 thread_id_,
253 time_int64, 254 time_int64,
254 phase_, 255 phase_,
255 name_); 256 name_);
256 257
257 // Output argument names and values, stop at first NULL argument name. 258 // Output argument names and values, stop at first NULL argument name.
258 for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) { 259 for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) {
259 if (i > 0) 260 if (i > 0)
260 *out += ","; 261 *out += ",";
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
350 351
351 TraceLog::TraceLog() 352 TraceLog::TraceLog()
352 : enable_count_(0), 353 : enable_count_(0),
353 dispatching_to_observer_list_(false), 354 dispatching_to_observer_list_(false),
354 watch_category_(NULL) { 355 watch_category_(NULL) {
355 // Trace is enabled or disabled on one thread while other threads are 356 // Trace is enabled or disabled on one thread while other threads are
356 // accessing the enabled flag. We don't care whether edge-case events are 357 // accessing the enabled flag. We don't care whether edge-case events are
357 // traced or not, so we allow races on the enabled flag to keep the trace 358 // traced or not, so we allow races on the enabled flag to keep the trace
358 // macros fast. 359 // macros fast.
359 // TODO(jbates): ANNOTATE_BENIGN_RACE_SIZED crashes windows TSAN bots: 360 // TODO(jbates): ANNOTATE_BENIGN_RACE_SIZED crashes windows TSAN bots:
360 // ANNOTATE_BENIGN_RACE_SIZED(g_category_enabled, sizeof(g_category_enabled), 361 // ANNOTATE_BENIGN_RACE_SIZED(g_category_group_enabled,
361 // "trace_event category enabled"); 362 // sizeof(g_category_group_enabled),
363 // "trace_event category enabled");
362 for (int i = 0; i < TRACE_EVENT_MAX_CATEGORIES; ++i) { 364 for (int i = 0; i < TRACE_EVENT_MAX_CATEGORIES; ++i) {
363 ANNOTATE_BENIGN_RACE(&g_category_enabled[i], 365 ANNOTATE_BENIGN_RACE(&g_category_group_enabled[i],
364 "trace_event category enabled"); 366 "trace_event category enabled");
365 } 367 }
366 #if defined(OS_NACL) // NaCl shouldn't expose the process id. 368 #if defined(OS_NACL) // NaCl shouldn't expose the process id.
367 SetProcessID(0); 369 SetProcessID(0);
368 #else 370 #else
369 SetProcessID(static_cast<int>(GetCurrentProcId())); 371 SetProcessID(static_cast<int>(GetCurrentProcId()));
370 #endif 372 #endif
371 } 373 }
372 374
373 TraceLog::~TraceLog() { 375 TraceLog::~TraceLog() {
374 } 376 }
375 377
376 const unsigned char* TraceLog::GetCategoryEnabled(const char* name) { 378 const unsigned char* TraceLog::GetCategoryGroupEnabled(
379 const char* category_group) {
377 TraceLog* tracelog = GetInstance(); 380 TraceLog* tracelog = GetInstance();
378 if (!tracelog) { 381 if (!tracelog) {
379 DCHECK(!g_category_enabled[g_category_already_shutdown]); 382 DCHECK(!g_category_group_enabled[g_category_already_shutdown]);
380 return &g_category_enabled[g_category_already_shutdown]; 383 return &g_category_group_enabled[g_category_already_shutdown];
381 } 384 }
382 return tracelog->GetCategoryEnabledInternal(name); 385 return tracelog->GetCategoryGroupEnabledInternal(category_group);
383 } 386 }
384 387
385 const char* TraceLog::GetCategoryName(const unsigned char* category_enabled) { 388 const char* TraceLog::GetCategoryGroupName(
386 // Calculate the index of the category by finding category_enabled in 389 const unsigned char* category_group_enabled) {
387 // g_category_enabled array. 390 // Calculate the index of the category group by finding
388 uintptr_t category_begin = reinterpret_cast<uintptr_t>(g_category_enabled); 391 // category_group_enabled in g_category_group_enabled array.
389 uintptr_t category_ptr = reinterpret_cast<uintptr_t>(category_enabled); 392 uintptr_t category_begin = reinterpret_cast<uintptr_t>(
393 g_category_group_enabled);
nduca 2013/02/21 06:02:36 check your indentation throughout, as noted before
rterrazas 2013/02/25 05:55:02 Done.
rterrazas 2013/02/25 05:55:02 Done.
394 uintptr_t category_ptr = reinterpret_cast<uintptr_t>(category_group_enabled);
390 DCHECK(category_ptr >= category_begin && 395 DCHECK(category_ptr >= category_begin &&
391 category_ptr < reinterpret_cast<uintptr_t>(g_category_enabled + 396 category_ptr < reinterpret_cast<uintptr_t>(g_category_group_enabled +
392 TRACE_EVENT_MAX_CATEGORIES)) << 397 TRACE_EVENT_MAX_CATEGORIES)) <<
393 "out of bounds category pointer"; 398 "out of bounds category pointer";
394 uintptr_t category_index = 399 uintptr_t category_index =
395 (category_ptr - category_begin) / sizeof(g_category_enabled[0]); 400 (category_ptr - category_begin) / sizeof(g_category_group_enabled[0]);
396 return g_categories[category_index]; 401 return g_category_groups[category_index];
397 } 402 }
398 403
399 static void EnableMatchingCategory(int category_index, 404 void TraceLog::EnableIncludedCategoryGroup(int category_index,
nduca 2013/02/21 06:02:36 any reason we're passing the filter when this is a
rterrazas 2013/02/25 05:55:02 It's static function, at the time I liked it bette
400 const std::vector<std::string>& patterns, 405 const CategoryFilter& category_filter) {
401 unsigned char matched_value, 406 bool is_enabled =
402 unsigned char unmatched_value) { 407 category_filter.IsCategoryGroupEnabled(g_category_groups[category_index]);
403 std::vector<std::string>::const_iterator ci = patterns.begin(); 408 g_category_group_enabled[category_index] = is_enabled ?
404 bool is_match = false; 409 TraceLog::CATEGORY_ENABLED : 0;
405 for (; ci != patterns.end(); ++ci) { 410 }
406 is_match = MatchPattern(g_categories[category_index], ci->c_str()); 411
407 if (is_match) 412 void TraceLog::EnableIncludedCategoryGroups(
413 const CategoryFilter& category_filter) {
414 for (int i = 0; i < g_category_index; i++)
415 EnableIncludedCategoryGroup(i, category_filter);
416 }
417
418 const unsigned char* TraceLog::GetCategoryGroupEnabledInternal(
419 const char* category_group) {
420 AutoLock lock(lock_);
421 DCHECK(!strchr(category_group, '"')) <<
dsinclair 2013/02/22 21:13:44 Can we do this before we lock?
rterrazas 2013/02/25 05:55:02 Done.
422 "Category group names may not contain double quote";
dsinclair 2013/02/22 21:13:44 contain a double
dsinclair 2013/02/22 21:13:44 Why can't it contain a quote? Can it contain a , o
rterrazas 2013/02/25 05:55:02 The double quote restriction must be related to th
423
424 unsigned char* category_group_enabled = NULL;
425 // Search for pre-existing category matching this category_group
426 for (int i = 0; i < g_category_index; i++) {
427 if (strcmp(g_category_groups[i], category_group) == 0) {
428 category_group_enabled = &g_category_group_enabled[i];
408 break; 429 break;
409 } 430 }
410 g_category_enabled[category_index] = is_match ? 431 }
411 matched_value : unmatched_value; 432
412 } 433 if (!category_group_enabled) {
413
414 // Enable/disable each category based on the category filters in |patterns|.
415 // If the category name matches one of the patterns, its enabled status is set
416 // to |matched_value|. Otherwise its enabled status is set to |unmatched_value|.
417 static void EnableMatchingCategories(const std::vector<std::string>& patterns,
418 unsigned char matched_value,
419 unsigned char unmatched_value) {
420 for (int i = 0; i < g_category_index; i++)
421 EnableMatchingCategory(i, patterns, matched_value, unmatched_value);
422 }
423
424 const unsigned char* TraceLog::GetCategoryEnabledInternal(const char* name) {
425 AutoLock lock(lock_);
426 DCHECK(!strchr(name, '"')) << "Category names may not contain double quote";
427
428 unsigned char* category_enabled = NULL;
429 // Search for pre-existing category matching this name
430 for (int i = 0; i < g_category_index; i++) {
431 if (strcmp(g_categories[i], name) == 0) {
432 category_enabled = &g_category_enabled[i];
433 break;
434 }
435 }
436
437 if (!category_enabled) {
438 // Create a new category 434 // Create a new category
439 DCHECK(g_category_index < TRACE_EVENT_MAX_CATEGORIES) << 435 DCHECK(g_category_index < TRACE_EVENT_MAX_CATEGORIES) <<
440 "must increase TRACE_EVENT_MAX_CATEGORIES"; 436 "must increase TRACE_EVENT_MAX_CATEGORIES";
441 if (g_category_index < TRACE_EVENT_MAX_CATEGORIES) { 437 if (g_category_index < TRACE_EVENT_MAX_CATEGORIES) {
442 int new_index = g_category_index++; 438 int new_index = g_category_index++;
443 // Don't hold on to the name pointer, so that we can create categories 439 // Don't hold on to the category_group pointer, so that we can create
444 // with strings not known at compile time (this is required by 440 // category groups with strings not known at compile time (this is
445 // SetWatchEvent). 441 // required by SetWatchEvent).
446 const char* new_name = strdup(name); 442 const char* new_group = strdup(category_group);
447 ANNOTATE_LEAKING_OBJECT_PTR(new_name); 443 ANNOTATE_LEAKING_OBJECT_PTR(new_group);
448 g_categories[new_index] = new_name; 444 g_category_groups[new_index] = new_group;
449 DCHECK(!g_category_enabled[new_index]); 445 DCHECK(!g_category_group_enabled[new_index]);
450 if (enable_count_) { 446 if (enable_count_) {
451 // Note that if both included and excluded_categories are empty, the 447 // Note that if both included and excluded patterns in the
452 // else clause below excludes nothing, thereby enabling this category. 448 // CategoryFilter are empty, we exclude nothing,
453 if (!included_categories_.empty()) { 449 // thereby enabling this category group.
454 EnableMatchingCategory(new_index, included_categories_, 450 EnableIncludedCategoryGroup(new_index, category_filter_);
455 CATEGORY_ENABLED, 0);
456 } else {
457 EnableMatchingCategory(new_index, excluded_categories_,
458 0, CATEGORY_ENABLED);
459 }
460 } else { 451 } else {
461 g_category_enabled[new_index] = 0; 452 g_category_group_enabled[new_index] = 0;
462 } 453 }
463 category_enabled = &g_category_enabled[new_index]; 454 category_group_enabled = &g_category_group_enabled[new_index];
464 } else { 455 } else {
465 category_enabled = &g_category_enabled[g_category_categories_exhausted]; 456 category_group_enabled =
457 &g_category_group_enabled[g_category_categories_exhausted];
466 } 458 }
467 } 459 }
468 #if defined(OS_ANDROID) 460 #if defined(OS_ANDROID)
469 ApplyATraceEnabledFlag(category_enabled); 461 ApplyATraceEnabledFlag(category_group_enabled);
470 #endif 462 #endif
471 return category_enabled; 463 return category_group_enabled;
472 } 464 }
473 465
474 void TraceLog::GetKnownCategories(std::vector<std::string>* categories) { 466 void TraceLog::GetKnownCategoryGroups(
467 std::vector<std::string>* category_groups) {
475 AutoLock lock(lock_); 468 AutoLock lock(lock_);
476 for (int i = 0; i < g_category_index; i++) 469 for (int i = 0; i < g_category_index; i++)
477 categories->push_back(g_categories[i]); 470 category_groups->push_back(g_category_groups[i]);
478 } 471 }
479 472
480 void TraceLog::SetEnabled(const std::vector<std::string>& included_categories, 473 static bool DoesCategoryGroupContainCategory(const char* category_group,
481 const std::vector<std::string>& excluded_categories) { 474 const char* category) {
475 DCHECK(category);
476 CStringTokenizer category_group_tokens(category_group,
477 category_group + strlen(category_group), ",");
478 while (category_group_tokens.GetNext()) {
479 std::string category_group_token = category_group_tokens.token();
480 // Don't allow empty tokens, nor tokens with leading or trailing space.
481 DCHECK(!category_group_token.empty() &&
482 category_group_token.at(0) != ' '&&
483 category_group_token.at(category_group_token.length() - 1) != ' ')
484 << "Disallowed category string";
485 if (MatchPattern(category_group_token.c_str(), category))
486 return true;
487 }
488 return false;
489 }
490
491 const char* CategoryFilter::kDefaultCategoryFilterString = "-*Debug,-*Test";
492
493 CategoryFilter::CategoryFilter() {
494 Initialize(CategoryFilter::kDefaultCategoryFilterString);
495 }
496
497 CategoryFilter::CategoryFilter(const std::string& filter_string) {
498 Initialize(filter_string);
499 }
500
501 void CategoryFilter::Initialize(const std::string& filter_string) {
502 // Pass 1: Tokenize list of categories, delimited by ','.
nduca 2013/02/21 06:02:36 There's only one pass....?
rterrazas 2013/02/25 05:55:02 Done.
503 StringTokenizer tokens(filter_string, ",");
504 while (tokens.GetNext()) {
505 bool is_included = true;
506 std::string category = tokens.token();
507 // Ignore empty categories.
508 if(category.empty())
509 continue;
510 // Excluded categories start with '-'.
511 if (category.at(0) == '-') {
512 // Remove '-' from category string.
513 category = category.substr(1);
514 is_included = false;
515 }
516 if (is_included)
dsinclair 2013/02/22 21:13:44 Instead of storing is_included, why not just do th
rterrazas 2013/02/25 05:55:02 Like. Done.
517 included_.push_back(category);
518 else
519 excluded_.push_back(category);
520 }
521 }
522
523 void CategoryFilter::WriteString(std::string* out,
524 bool included) const {
525 std::vector<std::string>::const_iterator ci;
526 std::vector<std::string>::const_iterator end;
527 if (included) {
528 ci = included_.begin();
529 end = included_.end();
530 } else {
531 ci = excluded_.begin();
532 end = excluded_.end();
533 }
534
535 for (; ci != end; ++ci) {
536 if (included)
537 StringAppendF(out, "%s,", ci->c_str());
538 else
539 StringAppendF(out, "-%s,", ci->c_str());
dsinclair 2013/02/22 21:13:44 StringAppendF(out, "%s%s,", (included ? "" : "-"),
rterrazas 2013/02/25 05:55:02 Done.
540 }
541 }
542
543 void CategoryFilter::ToString(std::string* filter_string) const {
nduca 2013/02/21 06:02:36 not sure that this makes sense... or works in all
rterrazas 2013/02/25 05:55:02 In Initialize, I ignored empty category patterns (
544 WriteString(filter_string, true);
545 WriteString(filter_string, false);
546 }
547
548 bool CategoryFilter::IsCategoryGroupEnabled(const char* category_group_name)
549 const {
nduca 2013/02/21 06:02:36 indentation
rterrazas 2013/02/25 05:55:02 Done.
550 // TraceLog should call this method only as part of enabling/disabling
551 // categories.
552 std::vector<std::string>::const_iterator ci = included_.begin();
553 for (; ci != included_.end(); ++ci) {
554 if (DoesCategoryGroupContainCategory(category_group_name, ci->c_str()))
555 return true;
556 }
557 ci = excluded_.begin();
558 for (; ci != excluded_.end(); ++ci) {
559 if (DoesCategoryGroupContainCategory(category_group_name, ci->c_str()))
560 return false;
561 }
562 // If the category group is not excluded, and there are no included patterns
563 // we consider this pattern enabled.
564 return included_.empty();
565 }
566
567 void CategoryFilter::Merge(const CategoryFilter& nested_filter) {
568 included_.insert(included_.end(),
569 nested_filter.included_.begin(),
570 nested_filter.included_.end());
571 excluded_.insert(excluded_.end(),
nduca 2013/02/21 06:02:36 indentation is funky
rterrazas 2013/02/25 05:55:02 Done.
572 nested_filter.excluded_.begin(),
573 nested_filter.excluded_.end());
574 }
575
576 bool CategoryFilter::HasIncludedCategories() const {
577 return !included_.empty();
578 }
579
580 void CategoryFilter::Clear() {
nduca 2013/02/21 06:02:36 what use case necessitated this?
rterrazas 2013/02/25 05:55:02 SetEnabled() // If either old or new included cate
581 included_.clear();
582 excluded_.clear();
583 }
584
585 void TraceLog::SetEnabled(const CategoryFilter& category_filter) {
586
587 // Actually enable/disable the categories.
nduca 2013/02/21 06:02:36 categyr groups
482 AutoLock lock(lock_); 588 AutoLock lock(lock_);
483 589
484 if (enable_count_++ > 0) { 590 if (enable_count_++ > 0) {
485 // Tracing is already enabled, so just merge in enabled categories. 591 // Tracing is already enabled, so just merge in enabled categories.
486 // We only expand the set of enabled categories upon nested SetEnable(). 592 // We only expand the set of enabled categories upon nested SetEnable().
487 if (!included_categories_.empty() && !included_categories.empty()) { 593 if (category_filter_.HasIncludedCategories() &&
nduca 2013/02/21 06:02:36 Can this just be part of merge? E.g. make merge do
rterrazas 2013/02/25 05:55:02 We could do something like MergeIfNeeded and Clear
488 included_categories_.insert(included_categories_.end(), 594 category_filter.HasIncludedCategories()) {
489 included_categories.begin(), 595 category_filter_.Merge(category_filter);
490 included_categories.end());
491 EnableMatchingCategories(included_categories_, CATEGORY_ENABLED, 0);
492 } else { 596 } else {
493 // If either old or new included categories are empty, allow all events. 597 // If either old or new included categories are empty, allow all not
494 included_categories_.clear(); 598 // excluded events.
495 excluded_categories_.clear(); 599 category_filter_.Clear();
496 EnableMatchingCategories(excluded_categories_, 0, CATEGORY_ENABLED); 600 }
497 } 601 EnableIncludedCategoryGroups(category_filter_);
498 return; 602 return;
499 } 603 }
500 604
501 if (dispatching_to_observer_list_) { 605 if (dispatching_to_observer_list_) {
502 DLOG(ERROR) << 606 DLOG(ERROR) <<
503 "Cannot manipulate TraceLog::Enabled state from an observer."; 607 "Cannot manipulate TraceLog::Enabled state from an observer.";
504 return; 608 return;
505 } 609 }
506 610
507 dispatching_to_observer_list_ = true; 611 dispatching_to_observer_list_ = true;
508 FOR_EACH_OBSERVER(EnabledStateChangedObserver, enabled_state_observer_list_, 612 FOR_EACH_OBSERVER(EnabledStateChangedObserver, enabled_state_observer_list_,
509 OnTraceLogWillEnable()); 613 OnTraceLogWillEnable());
510 dispatching_to_observer_list_ = false; 614 dispatching_to_observer_list_ = false;
511 615
512 logged_events_.reserve(1024); 616 logged_events_.reserve(1024);
513 included_categories_ = included_categories; 617 category_filter_ = CategoryFilter(category_filter);
514 excluded_categories_ = excluded_categories; 618 EnableIncludedCategoryGroups(category_filter_);
515 // Note that if both included and excluded_categories are empty, the else
516 // clause below excludes nothing, thereby enabling all categories.
517 if (!included_categories_.empty())
518 EnableMatchingCategories(included_categories_, CATEGORY_ENABLED, 0);
519 else
520 EnableMatchingCategories(excluded_categories_, 0, CATEGORY_ENABLED);
521 } 619 }
522 620
523 void TraceLog::SetEnabled(const std::string& categories) { 621 CategoryFilter& TraceLog::GetCurrentCategoryFilter() {
524 std::vector<std::string> included, excluded;
525 // Tokenize list of categories, delimited by ','.
526 StringTokenizer tokens(categories, ",");
527 while (tokens.GetNext()) {
528 bool is_included = true;
529 std::string category = tokens.token();
530 // Excluded categories start with '-'.
531 if (category.at(0) == '-') {
532 // Remove '-' from category string.
533 category = category.substr(1);
534 is_included = false;
535 }
536 if (is_included)
537 included.push_back(category);
538 else
539 excluded.push_back(category);
540 }
541 SetEnabled(included, excluded);
542 }
543
544 void TraceLog::GetEnabledTraceCategories(
545 std::vector<std::string>* included_out,
546 std::vector<std::string>* excluded_out) {
547 AutoLock lock(lock_); 622 AutoLock lock(lock_);
548 if (enable_count_) { 623 DCHECK(enable_count_ > 0);
549 *included_out = included_categories_; 624 return category_filter_;
550 *excluded_out = excluded_categories_;
551 }
552 } 625 }
553 626
554 void TraceLog::SetDisabled() { 627 void TraceLog::SetDisabled() {
555 AutoLock lock(lock_); 628 AutoLock lock(lock_);
556 DCHECK(enable_count_ > 0); 629 DCHECK(enable_count_ > 0);
557 if (--enable_count_ != 0) 630 if (--enable_count_ != 0)
558 return; 631 return;
559 632
560 if (dispatching_to_observer_list_) { 633 if (dispatching_to_observer_list_) {
561 DLOG(ERROR) 634 DLOG(ERROR)
562 << "Cannot manipulate TraceLog::Enabled state from an observer."; 635 << "Cannot manipulate TraceLog::Enabled state from an observer.";
563 return; 636 return;
564 } 637 }
565 638
566 dispatching_to_observer_list_ = true; 639 dispatching_to_observer_list_ = true;
567 FOR_EACH_OBSERVER(EnabledStateChangedObserver, enabled_state_observer_list_, 640 FOR_EACH_OBSERVER(EnabledStateChangedObserver, enabled_state_observer_list_,
568 OnTraceLogWillDisable()); 641 OnTraceLogWillDisable());
569 dispatching_to_observer_list_ = false; 642 dispatching_to_observer_list_ = false;
570 643
571 included_categories_.clear(); 644 category_filter_.Clear();
572 excluded_categories_.clear();
573 watch_category_ = NULL; 645 watch_category_ = NULL;
574 watch_event_name_ = ""; 646 watch_event_name_ = "";
575 for (int i = 0; i < g_category_index; i++) 647 for (int i = 0; i < g_category_index; i++)
576 g_category_enabled[i] = 0; 648 g_category_group_enabled[i] = 0;
577 AddThreadNameMetadataEvents(); 649 AddThreadNameMetadataEvents();
578 } 650 }
579 651
580 void TraceLog::SetEnabled(bool enabled) {
581 if (enabled)
582 SetEnabled(std::vector<std::string>(), std::vector<std::string>());
583 else
584 SetDisabled();
585 }
586
587 void TraceLog::AddEnabledStateObserver(EnabledStateChangedObserver* listener) { 652 void TraceLog::AddEnabledStateObserver(EnabledStateChangedObserver* listener) {
588 enabled_state_observer_list_.AddObserver(listener); 653 enabled_state_observer_list_.AddObserver(listener);
589 } 654 }
590 655
591 void TraceLog::RemoveEnabledStateObserver( 656 void TraceLog::RemoveEnabledStateObserver(
592 EnabledStateChangedObserver* listener) { 657 EnabledStateChangedObserver* listener) {
593 enabled_state_observer_list_.RemoveObserver(listener); 658 enabled_state_observer_list_.RemoveObserver(listener);
594 } 659 }
595 660
596 float TraceLog::GetBufferPercentFull() const { 661 float TraceLog::GetBufferPercentFull() const {
(...skipping 20 matching lines...) Expand all
617 new RefCountedString(); 682 new RefCountedString();
618 TraceEvent::AppendEventsAsJSON(previous_logged_events, 683 TraceEvent::AppendEventsAsJSON(previous_logged_events,
619 i, 684 i,
620 kTraceEventBatchSize, 685 kTraceEventBatchSize,
621 &(json_events_str_ptr->data())); 686 &(json_events_str_ptr->data()));
622 cb.Run(json_events_str_ptr); 687 cb.Run(json_events_str_ptr);
623 } 688 }
624 } 689 }
625 690
626 void TraceLog::AddTraceEvent(char phase, 691 void TraceLog::AddTraceEvent(char phase,
627 const unsigned char* category_enabled, 692 const unsigned char* category_group_enabled,
628 const char* name, 693 const char* name,
629 unsigned long long id, 694 unsigned long long id,
630 int num_args, 695 int num_args,
631 const char** arg_names, 696 const char** arg_names,
632 const unsigned char* arg_types, 697 const unsigned char* arg_types,
633 const unsigned long long* arg_values, 698 const unsigned long long* arg_values,
634 unsigned char flags) { 699 unsigned char flags) {
635 int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); 700 int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
636 base::TimeTicks now = base::TimeTicks::NowFromSystemTraceTime(); 701 base::TimeTicks now = base::TimeTicks::NowFromSystemTraceTime();
637 AddTraceEventWithThreadIdAndTimestamp(phase, category_enabled, name, id, 702 AddTraceEventWithThreadIdAndTimestamp(phase, category_group_enabled, name, id,
638 thread_id, now, num_args, arg_names, 703 thread_id, now, num_args, arg_names,
639 arg_types, arg_values, flags); 704 arg_types, arg_values, flags);
640 } 705 }
641 706
642 void TraceLog::AddTraceEventWithThreadIdAndTimestamp( 707 void TraceLog::AddTraceEventWithThreadIdAndTimestamp(
643 char phase, 708 char phase,
644 const unsigned char* category_enabled, 709 const unsigned char* category_group_enabled,
645 const char* name, 710 const char* name,
646 unsigned long long id, 711 unsigned long long id,
647 int thread_id, 712 int thread_id,
648 const TimeTicks& timestamp, 713 const TimeTicks& timestamp,
649 int num_args, 714 int num_args,
650 const char** arg_names, 715 const char** arg_names,
651 const unsigned char* arg_types, 716 const unsigned char* arg_types,
652 const unsigned long long* arg_values, 717 const unsigned long long* arg_values,
653 unsigned char flags) { 718 unsigned char flags) {
654 DCHECK(name); 719 DCHECK(name);
655 720
656 #if defined(OS_ANDROID) 721 #if defined(OS_ANDROID)
657 SendToATrace(phase, GetCategoryName(category_enabled), name, 722 SendToATrace(phase, GetCategoryGroupName(category_group_enabled), name,
658 num_args, arg_names, arg_types, arg_values); 723 num_args, arg_names, arg_types, arg_values);
659 #endif 724 #endif
660 725
661 TimeTicks now = timestamp - time_offset_; 726 TimeTicks now = timestamp - time_offset_;
662 NotificationHelper notifier(this); 727 NotificationHelper notifier(this);
663 728
664 { 729 {
665 AutoLock lock(lock_); 730 AutoLock lock(lock_);
666 if (*category_enabled != CATEGORY_ENABLED) 731 if (*category_group_enabled != CATEGORY_ENABLED)
667 return; 732 return;
668 if (logged_events_.size() >= kTraceEventBufferSize) 733 if (logged_events_.size() >= kTraceEventBufferSize)
669 return; 734 return;
670 735
671 const char* new_name = ThreadIdNameManager::GetInstance()-> 736 const char* new_name = ThreadIdNameManager::GetInstance()->
672 GetName(thread_id); 737 GetName(thread_id);
673 // Check if the thread name has been set or changed since the previous 738 // Check if the thread name has been set or changed since the previous
674 // call (if any), but don't bother if the new name is empty. Note this will 739 // call (if any), but don't bother if the new name is empty. Note this will
675 // not detect a thread name change within the same char* buffer address: we 740 // not detect a thread name change within the same char* buffer address: we
676 // favor common case performance over corner case correctness. 741 // favor common case performance over corner case correctness.
(...skipping 19 matching lines...) Expand all
696 existing_name->second.append(new_name); 761 existing_name->second.append(new_name);
697 } 762 }
698 } 763 }
699 } 764 }
700 765
701 if (flags & TRACE_EVENT_FLAG_MANGLE_ID) 766 if (flags & TRACE_EVENT_FLAG_MANGLE_ID)
702 id ^= process_id_hash_; 767 id ^= process_id_hash_;
703 768
704 logged_events_.push_back( 769 logged_events_.push_back(
705 TraceEvent(thread_id, 770 TraceEvent(thread_id,
706 now, phase, category_enabled, name, id, 771 now, phase, category_group_enabled, name, id,
707 num_args, arg_names, arg_types, arg_values, 772 num_args, arg_names, arg_types, arg_values,
708 flags)); 773 flags));
709 774
710 if (logged_events_.size() == kTraceEventBufferSize) 775 if (logged_events_.size() == kTraceEventBufferSize)
711 notifier.AddNotificationWhileLocked(TRACE_BUFFER_FULL); 776 notifier.AddNotificationWhileLocked(TRACE_BUFFER_FULL);
712 777
713 if (watch_category_ == category_enabled && watch_event_name_ == name) 778 if (watch_category_ == category_group_enabled && watch_event_name_ == name)
714 notifier.AddNotificationWhileLocked(EVENT_WATCH_NOTIFICATION); 779 notifier.AddNotificationWhileLocked(EVENT_WATCH_NOTIFICATION);
715 } // release lock 780 } // release lock
716 781
717 notifier.SendNotificationIfAny(); 782 notifier.SendNotificationIfAny();
718 } 783 }
719 784
720 void TraceLog::AddTraceEventEtw(char phase, 785 void TraceLog::AddTraceEventEtw(char phase,
721 const char* name, 786 const char* name,
722 const void* id, 787 const void* id,
723 const char* extra) { 788 const char* extra) {
(...skipping 11 matching lines...) Expand all
735 { 800 {
736 #if defined(OS_WIN) 801 #if defined(OS_WIN)
737 TraceEventETWProvider::Trace(name, phase, id, extra); 802 TraceEventETWProvider::Trace(name, phase, id, extra);
738 #endif 803 #endif
739 INTERNAL_TRACE_EVENT_ADD(phase, "ETW Trace Event", name, 804 INTERNAL_TRACE_EVENT_ADD(phase, "ETW Trace Event", name,
740 TRACE_EVENT_FLAG_COPY, "id", id, "extra", extra); 805 TRACE_EVENT_FLAG_COPY, "id", id, "extra", extra);
741 } 806 }
742 807
743 void TraceLog::SetWatchEvent(const std::string& category_name, 808 void TraceLog::SetWatchEvent(const std::string& category_name,
744 const std::string& event_name) { 809 const std::string& event_name) {
745 const unsigned char* category = GetCategoryEnabled(category_name.c_str()); 810 const unsigned char* category = GetCategoryGroupEnabled(
811 category_name.c_str());
746 int notify_count = 0; 812 int notify_count = 0;
747 { 813 {
748 AutoLock lock(lock_); 814 AutoLock lock(lock_);
749 watch_category_ = category; 815 watch_category_ = category;
750 watch_event_name_ = event_name; 816 watch_event_name_ = event_name;
751 817
752 // First, search existing events for watch event because we want to catch it 818 // First, search existing events for watch event because we want to catch it
753 // even if it has already occurred. 819 // even if it has already occurred.
754 for (size_t i = 0u; i < logged_events_.size(); ++i) { 820 for (size_t i = 0u; i < logged_events_.size(); ++i) {
755 if (category == logged_events_[i].category_enabled() && 821 if (category == logged_events_[i].category_group_enabled() &&
756 strcmp(event_name.c_str(), logged_events_[i].name()) == 0) { 822 strcmp(event_name.c_str(), logged_events_[i].name()) == 0) {
757 ++notify_count; 823 ++notify_count;
758 } 824 }
759 } 825 }
760 } // release lock 826 } // release lock
761 827
762 // Send notification for each event found. 828 // Send notification for each event found.
763 for (int i = 0; i < notify_count; ++i) { 829 for (int i = 0; i < notify_count; ++i) {
764 NotificationHelper notifier(this); 830 NotificationHelper notifier(this);
765 lock_.Acquire(); 831 lock_.Acquire();
(...skipping 16 matching lines...) Expand all
782 it++) { 848 it++) {
783 if (!it->second.empty()) { 849 if (!it->second.empty()) {
784 int num_args = 1; 850 int num_args = 1;
785 const char* arg_name = "name"; 851 const char* arg_name = "name";
786 unsigned char arg_type; 852 unsigned char arg_type;
787 unsigned long long arg_value; 853 unsigned long long arg_value;
788 trace_event_internal::SetTraceValue(it->second, &arg_type, &arg_value); 854 trace_event_internal::SetTraceValue(it->second, &arg_type, &arg_value);
789 logged_events_.push_back( 855 logged_events_.push_back(
790 TraceEvent(it->first, 856 TraceEvent(it->first,
791 TimeTicks(), TRACE_EVENT_PHASE_METADATA, 857 TimeTicks(), TRACE_EVENT_PHASE_METADATA,
792 &g_category_enabled[g_category_metadata], 858 &g_category_group_enabled[g_category_metadata],
793 "thread_name", trace_event_internal::kNoEventId, 859 "thread_name", trace_event_internal::kNoEventId,
794 num_args, &arg_name, &arg_type, &arg_value, 860 num_args, &arg_name, &arg_type, &arg_value,
795 TRACE_EVENT_FLAG_NONE)); 861 TRACE_EVENT_FLAG_NONE));
796 } 862 }
797 } 863 }
798 } 864 }
799 865
800 void TraceLog::DeleteForTesting() { 866 void TraceLog::DeleteForTesting() {
801 DeleteTraceLogForTesting::Delete(); 867 DeleteTraceLogForTesting::Delete();
802 } 868 }
(...skipping 20 matching lines...) Expand all
823 } // namespace base 889 } // namespace base
824 890
825 namespace trace_event_internal { 891 namespace trace_event_internal {
826 892
827 ScopedTrace::ScopedTrace( 893 ScopedTrace::ScopedTrace(
828 TRACE_EVENT_API_ATOMIC_WORD* event_uid, const char* name) { 894 TRACE_EVENT_API_ATOMIC_WORD* event_uid, const char* name) {
829 category_enabled_ = 895 category_enabled_ =
830 reinterpret_cast<const unsigned char*>(TRACE_EVENT_API_ATOMIC_LOAD( 896 reinterpret_cast<const unsigned char*>(TRACE_EVENT_API_ATOMIC_LOAD(
831 *event_uid)); 897 *event_uid));
832 if (!category_enabled_) { 898 if (!category_enabled_) {
833 category_enabled_ = TRACE_EVENT_API_GET_CATEGORY_ENABLED("gpu"); 899 category_enabled_ = TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED("gpu");
834 TRACE_EVENT_API_ATOMIC_STORE( 900 TRACE_EVENT_API_ATOMIC_STORE(
835 *event_uid, 901 *event_uid,
836 reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>(category_enabled_)); 902 reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>(category_enabled_));
837 } 903 }
838 if (*category_enabled_) { 904 if (*category_enabled_) {
839 name_ = name; 905 name_ = name;
840 TRACE_EVENT_API_ADD_TRACE_EVENT( 906 TRACE_EVENT_API_ADD_TRACE_EVENT(
841 TRACE_EVENT_PHASE_BEGIN, // phase 907 TRACE_EVENT_PHASE_BEGIN, // phase
842 category_enabled_, // category enabled 908 category_enabled_, // category enabled
843 name, // name 909 name, // name
(...skipping 18 matching lines...) Expand all
862 0, // num_args 928 0, // num_args
863 NULL, // arg_names 929 NULL, // arg_names
864 NULL, // arg_types 930 NULL, // arg_types
865 NULL, // arg_values 931 NULL, // arg_values
866 TRACE_EVENT_FLAG_NONE); // flags 932 TRACE_EVENT_FLAG_NONE); // flags
867 } 933 }
868 } 934 }
869 935
870 } // namespace trace_event_internal 936 } // namespace trace_event_internal
871 937
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698