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 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 389 uintptr_t category_ptr = reinterpret_cast<uintptr_t>(category_enabled); | 389 uintptr_t category_ptr = reinterpret_cast<uintptr_t>(category_enabled); |
| 390 DCHECK(category_ptr >= category_begin && | 390 DCHECK(category_ptr >= category_begin && |
| 391 category_ptr < reinterpret_cast<uintptr_t>(g_category_enabled + | 391 category_ptr < reinterpret_cast<uintptr_t>(g_category_enabled + |
| 392 TRACE_EVENT_MAX_CATEGORIES)) << | 392 TRACE_EVENT_MAX_CATEGORIES)) << |
| 393 "out of bounds category pointer"; | 393 "out of bounds category pointer"; |
| 394 uintptr_t category_index = | 394 uintptr_t category_index = |
| 395 (category_ptr - category_begin) / sizeof(g_category_enabled[0]); | 395 (category_ptr - category_begin) / sizeof(g_category_enabled[0]); |
| 396 return g_categories[category_index]; | 396 return g_categories[category_index]; |
| 397 } | 397 } |
| 398 | 398 |
| 399 static void EnableMatchingCategory(int category_index, | 399 void TraceLog::EnableIncludedCategoryGroup(int category_index, |
| 400 const std::vector<std::string>& patterns, | 400 const CategoryFilter& category_filter) { |
| 401 unsigned char matched_value, | 401 bool is_enabled = |
| 402 unsigned char unmatched_value) { | 402 category_filter.IsCategoryGroupEnabled(g_categories[category_index]); |
| 403 std::vector<std::string>::const_iterator ci = patterns.begin(); | 403 g_category_enabled[category_index] = is_enabled ? |
| 404 bool is_match = false; | 404 TraceLog::CATEGORY_ENABLED : 0; |
| 405 for (; ci != patterns.end(); ++ci) { | |
| 406 is_match = MatchPattern(g_categories[category_index], ci->c_str()); | |
| 407 if (is_match) | |
| 408 break; | |
| 409 } | |
| 410 g_category_enabled[category_index] = is_match ? | |
| 411 matched_value : unmatched_value; | |
| 412 } | 405 } |
| 413 | 406 |
| 414 // Enable/disable each category based on the category filters in |patterns|. | 407 void TraceLog::EnableIncludedCategoryGroups( |
| 415 // If the category name matches one of the patterns, its enabled status is set | 408 const CategoryFilter& category_filter) { |
| 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++) | 409 for (int i = 0; i < g_category_index; i++) |
| 421 EnableMatchingCategory(i, patterns, matched_value, unmatched_value); | 410 EnableIncludedCategoryGroup(i, category_filter); |
| 422 } | 411 } |
| 423 | 412 |
| 424 const unsigned char* TraceLog::GetCategoryEnabledInternal(const char* name) { | 413 const unsigned char* TraceLog::GetCategoryEnabledInternal(const char* name) { |
| 425 AutoLock lock(lock_); | 414 AutoLock lock(lock_); |
| 426 DCHECK(!strchr(name, '"')) << "Category names may not contain double quote"; | 415 DCHECK(!strchr(name, '"')) << "Category names may not contain double quote"; |
| 427 | 416 |
| 428 unsigned char* category_enabled = NULL; | 417 unsigned char* category_enabled = NULL; |
| 429 // Search for pre-existing category matching this name | 418 // Search for pre-existing category matching this name |
| 430 for (int i = 0; i < g_category_index; i++) { | 419 for (int i = 0; i < g_category_index; i++) { |
| 431 if (strcmp(g_categories[i], name) == 0) { | 420 if (strcmp(g_categories[i], name) == 0) { |
| 432 category_enabled = &g_category_enabled[i]; | 421 category_enabled = &g_category_enabled[i]; |
| 433 break; | 422 break; |
| 434 } | 423 } |
| 435 } | 424 } |
| 436 | 425 |
| 437 if (!category_enabled) { | 426 if (!category_enabled) { |
| 438 // Create a new category | 427 // Create a new category |
| 439 DCHECK(g_category_index < TRACE_EVENT_MAX_CATEGORIES) << | 428 DCHECK(g_category_index < TRACE_EVENT_MAX_CATEGORIES) << |
| 440 "must increase TRACE_EVENT_MAX_CATEGORIES"; | 429 "must increase TRACE_EVENT_MAX_CATEGORIES"; |
| 441 if (g_category_index < TRACE_EVENT_MAX_CATEGORIES) { | 430 if (g_category_index < TRACE_EVENT_MAX_CATEGORIES) { |
| 442 int new_index = g_category_index++; | 431 int new_index = g_category_index++; |
| 443 // Don't hold on to the name pointer, so that we can create categories | 432 // Don't hold on to the name pointer, so that we can create categories |
| 444 // with strings not known at compile time (this is required by | 433 // with strings not known at compile time (this is required by |
| 445 // SetWatchEvent). | 434 // SetWatchEvent). |
| 446 const char* new_name = strdup(name); | 435 const char* new_name = strdup(name); |
| 447 ANNOTATE_LEAKING_OBJECT_PTR(new_name); | 436 ANNOTATE_LEAKING_OBJECT_PTR(new_name); |
| 448 g_categories[new_index] = new_name; | 437 g_categories[new_index] = new_name; |
| 449 DCHECK(!g_category_enabled[new_index]); | 438 DCHECK(!g_category_enabled[new_index]); |
| 450 if (enable_count_) { | 439 if (enable_count_) { |
| 451 // Note that if both included and excluded_categories are empty, the | 440 // Note that if both included and excluded patterns in the |
| 452 // else clause below excludes nothing, thereby enabling this category. | 441 // CategoryFilter are empty, we exclude nothing, |
| 453 if (!included_categories_.empty()) { | 442 // thereby enabling this category group. |
| 454 EnableMatchingCategory(new_index, included_categories_, | 443 EnableIncludedCategoryGroup(new_index, category_filter_); |
| 455 CATEGORY_ENABLED, 0); | |
| 456 } else { | |
| 457 EnableMatchingCategory(new_index, excluded_categories_, | |
| 458 0, CATEGORY_ENABLED); | |
| 459 } | |
| 460 } else { | 444 } else { |
| 461 g_category_enabled[new_index] = 0; | 445 g_category_enabled[new_index] = 0; |
| 462 } | 446 } |
| 463 category_enabled = &g_category_enabled[new_index]; | 447 category_enabled = &g_category_enabled[new_index]; |
| 464 } else { | 448 } else { |
| 465 category_enabled = &g_category_enabled[g_category_categories_exhausted]; | 449 category_enabled = &g_category_enabled[g_category_categories_exhausted]; |
| 466 } | 450 } |
| 467 } | 451 } |
| 468 #if defined(OS_ANDROID) | 452 #if defined(OS_ANDROID) |
| 469 ApplyATraceEnabledFlag(category_enabled); | 453 ApplyATraceEnabledFlag(category_enabled); |
| 470 #endif | 454 #endif |
| 471 return category_enabled; | 455 return category_enabled; |
| 472 } | 456 } |
| 473 | 457 |
| 474 void TraceLog::GetKnownCategories(std::vector<std::string>* categories) { | 458 void TraceLog::GetKnownCategories(std::vector<std::string>* categories) { |
| 475 AutoLock lock(lock_); | 459 AutoLock lock(lock_); |
| 476 for (int i = 0; i < g_category_index; i++) | 460 for (int i = 0; i < g_category_index; i++) |
| 477 categories->push_back(g_categories[i]); | 461 categories->push_back(g_categories[i]); |
| 478 } | 462 } |
| 479 | 463 |
| 480 void TraceLog::SetEnabled(const std::vector<std::string>& included_categories, | 464 static bool DoesCategoryGroupContainCategory(const char* category_group, |
| 481 const std::vector<std::string>& excluded_categories) { | 465 const char* category) { |
|
rterrazas
2013/02/21 04:08:05
So...I was thinking, I'd like to change this to so
nduca
2013/02/22 19:55:19
This sounds like a metho don the CategoryFilter ob
| |
| 466 DCHECK(category); | |
| 467 CStringTokenizer category_group_tokens(category_group, | |
| 468 category_group + strlen(category_group), ","); | |
| 469 while (category_group_tokens.GetNext()) { | |
| 470 std::string category_group_token = category_group_tokens.token(); | |
| 471 // Don't allow empty tokens, nor tokens with leading or trailing space. | |
| 472 DCHECK(!category_group_token.empty() && | |
| 473 category_group_token.at(0) != ' '&& | |
| 474 category_group_token.at(category_group_token.length() - 1) != ' ') | |
| 475 << "Disallowed category string"; | |
| 476 if (MatchPattern(category_group_token.c_str(), category)) | |
| 477 return true; | |
| 478 } | |
| 479 return false; | |
| 480 } | |
| 481 | |
| 482 const char* CategoryFilter::kDefaultCategoryFilterString = "-*Debug,-*Test"; | |
| 483 | |
| 484 CategoryFilter::CategoryFilter() { | |
| 485 Initialize(CategoryFilter::kDefaultCategoryFilterString); | |
| 486 } | |
| 487 | |
| 488 CategoryFilter::CategoryFilter(const std::string& filter_string) { | |
| 489 Initialize(filter_string); | |
| 490 } | |
| 491 | |
| 492 void CategoryFilter::Initialize(const std::string& filter_string) { | |
| 493 // Pass 1: Tokenize list of categories, delimited by ','. | |
| 494 StringTokenizer tokens(filter_string, ","); | |
| 495 while (tokens.GetNext()) { | |
| 496 bool is_included = true; | |
| 497 std::string category = tokens.token(); | |
| 498 // Ignore empty categories. | |
| 499 if(category.empty()) | |
| 500 continue; | |
| 501 // Excluded categories start with '-'. | |
| 502 if (category.at(0) == '-') { | |
| 503 // Remove '-' from category string. | |
| 504 category = category.substr(1); | |
| 505 is_included = false; | |
| 506 } | |
| 507 if (is_included) | |
| 508 included_.push_back(category); | |
| 509 else | |
| 510 excluded_.push_back(category); | |
| 511 } | |
| 512 } | |
| 513 | |
| 514 void CategoryFilter::WriteString(std::string* out, | |
| 515 bool included) const { | |
| 516 std::vector<std::string>::const_iterator ci; | |
| 517 std::vector<std::string>::const_iterator end; | |
| 518 if (included) { | |
| 519 ci = included_.begin(); | |
| 520 end = included_.end(); | |
| 521 } else { | |
| 522 ci = excluded_.begin(); | |
| 523 end = excluded_.end(); | |
| 524 } | |
| 525 | |
| 526 for (; ci != end; ++ci) { | |
| 527 if (included) | |
| 528 StringAppendF(out, "%s,", ci->c_str()); | |
| 529 else | |
| 530 StringAppendF(out, "-%s,", ci->c_str()); | |
| 531 } | |
| 532 } | |
| 533 | |
| 534 void CategoryFilter::ToString(std::string* filter_string) const { | |
| 535 WriteString(filter_string, true); | |
| 536 WriteString(filter_string, false); | |
| 537 } | |
| 538 | |
| 539 bool CategoryFilter::IsCategoryGroupEnabled(const char* category_group_name) | |
|
rterrazas
2013/02/20 02:40:06
This does a lot of the work that was done through
| |
| 540 const { | |
| 541 // TraceLog should call this method only as part of enabling/disabling | |
| 542 // categories. | |
| 543 std::vector<std::string>::const_iterator ci = included_.begin(); | |
| 544 for (; ci != included_.end(); ++ci) { | |
| 545 if (DoesCategoryGroupContainCategory(category_group_name, ci->c_str())) | |
| 546 return true; | |
| 547 } | |
| 548 ci = excluded_.begin(); | |
| 549 for (; ci != excluded_.end(); ++ci) { | |
| 550 if (DoesCategoryGroupContainCategory(category_group_name, ci->c_str())) | |
| 551 return false; | |
| 552 } | |
| 553 // If the category group is not excluded, and there are no included patterns | |
| 554 // we consider this pattern enabled. | |
| 555 return included_.empty(); | |
| 556 } | |
| 557 | |
| 558 void CategoryFilter::Merge(const CategoryFilter& nested_filter) { | |
| 559 included_.insert(included_.end(), | |
| 560 nested_filter.included_.begin(), | |
| 561 nested_filter.included_.end()); | |
| 562 excluded_.insert(excluded_.end(), | |
| 563 nested_filter.excluded_.begin(), | |
| 564 nested_filter.excluded_.end()); | |
| 565 } | |
| 566 | |
| 567 bool CategoryFilter::HasIncludedCategories() const { | |
| 568 return !included_.empty(); | |
| 569 } | |
| 570 | |
| 571 void CategoryFilter::Clear() { | |
| 572 included_.clear(); | |
| 573 excluded_.clear(); | |
| 574 } | |
| 575 | |
| 576 void TraceLog::SetEnabled(const CategoryFilter& category_filter) { | |
| 577 | |
| 578 // Actually enable/disable the categories. | |
| 482 AutoLock lock(lock_); | 579 AutoLock lock(lock_); |
| 483 | 580 |
| 484 if (enable_count_++ > 0) { | 581 if (enable_count_++ > 0) { |
| 485 // Tracing is already enabled, so just merge in enabled categories. | 582 // Tracing is already enabled, so just merge in enabled categories. |
| 486 // We only expand the set of enabled categories upon nested SetEnable(). | 583 // We only expand the set of enabled categories upon nested SetEnable(). |
| 487 if (!included_categories_.empty() && !included_categories.empty()) { | 584 if (category_filter_.HasIncludedCategories() && |
| 488 included_categories_.insert(included_categories_.end(), | 585 category_filter.HasIncludedCategories()) { |
| 489 included_categories.begin(), | 586 category_filter_.Merge(category_filter); |
| 490 included_categories.end()); | |
| 491 EnableMatchingCategories(included_categories_, CATEGORY_ENABLED, 0); | |
| 492 } else { | 587 } else { |
| 493 // If either old or new included categories are empty, allow all events. | 588 // If either old or new included categories are empty, allow all not |
| 494 included_categories_.clear(); | 589 // excluded events. |
| 495 excluded_categories_.clear(); | 590 category_filter_.Clear(); |
| 496 EnableMatchingCategories(excluded_categories_, 0, CATEGORY_ENABLED); | |
| 497 } | 591 } |
| 592 EnableIncludedCategoryGroups(category_filter_); | |
| 498 return; | 593 return; |
| 499 } | 594 } |
| 500 | 595 |
| 501 if (dispatching_to_observer_list_) { | 596 if (dispatching_to_observer_list_) { |
| 502 DLOG(ERROR) << | 597 DLOG(ERROR) << |
| 503 "Cannot manipulate TraceLog::Enabled state from an observer."; | 598 "Cannot manipulate TraceLog::Enabled state from an observer."; |
| 504 return; | 599 return; |
| 505 } | 600 } |
| 506 | 601 |
| 507 dispatching_to_observer_list_ = true; | 602 dispatching_to_observer_list_ = true; |
| 508 FOR_EACH_OBSERVER(EnabledStateChangedObserver, enabled_state_observer_list_, | 603 FOR_EACH_OBSERVER(EnabledStateChangedObserver, enabled_state_observer_list_, |
| 509 OnTraceLogWillEnable()); | 604 OnTraceLogWillEnable()); |
| 510 dispatching_to_observer_list_ = false; | 605 dispatching_to_observer_list_ = false; |
| 511 | 606 |
| 512 logged_events_.reserve(1024); | 607 logged_events_.reserve(1024); |
| 513 included_categories_ = included_categories; | 608 category_filter_ = CategoryFilter(category_filter); |
| 514 excluded_categories_ = excluded_categories; | 609 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 } | 610 } |
| 522 | 611 |
| 523 void TraceLog::SetEnabled(const std::string& categories) { | 612 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_); | 613 AutoLock lock(lock_); |
| 548 if (enable_count_) { | 614 DCHECK(enable_count_ > 0); |
| 549 *included_out = included_categories_; | 615 return category_filter_; |
| 550 *excluded_out = excluded_categories_; | |
| 551 } | |
| 552 } | 616 } |
| 553 | 617 |
| 554 void TraceLog::SetDisabled() { | 618 void TraceLog::SetDisabled() { |
| 555 AutoLock lock(lock_); | 619 AutoLock lock(lock_); |
| 556 DCHECK(enable_count_ > 0); | 620 DCHECK(enable_count_ > 0); |
| 557 if (--enable_count_ != 0) | 621 if (--enable_count_ != 0) |
| 558 return; | 622 return; |
| 559 | 623 |
| 560 if (dispatching_to_observer_list_) { | 624 if (dispatching_to_observer_list_) { |
| 561 DLOG(ERROR) | 625 DLOG(ERROR) |
| 562 << "Cannot manipulate TraceLog::Enabled state from an observer."; | 626 << "Cannot manipulate TraceLog::Enabled state from an observer."; |
| 563 return; | 627 return; |
| 564 } | 628 } |
| 565 | 629 |
| 566 dispatching_to_observer_list_ = true; | 630 dispatching_to_observer_list_ = true; |
| 567 FOR_EACH_OBSERVER(EnabledStateChangedObserver, enabled_state_observer_list_, | 631 FOR_EACH_OBSERVER(EnabledStateChangedObserver, enabled_state_observer_list_, |
| 568 OnTraceLogWillDisable()); | 632 OnTraceLogWillDisable()); |
| 569 dispatching_to_observer_list_ = false; | 633 dispatching_to_observer_list_ = false; |
| 570 | 634 |
| 571 included_categories_.clear(); | 635 category_filter_.Clear(); |
| 572 excluded_categories_.clear(); | |
| 573 watch_category_ = NULL; | 636 watch_category_ = NULL; |
| 574 watch_event_name_ = ""; | 637 watch_event_name_ = ""; |
| 575 for (int i = 0; i < g_category_index; i++) | 638 for (int i = 0; i < g_category_index; i++) |
| 576 g_category_enabled[i] = 0; | 639 g_category_enabled[i] = 0; |
| 577 AddThreadNameMetadataEvents(); | 640 AddThreadNameMetadataEvents(); |
| 578 } | 641 } |
| 579 | 642 |
| 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) { | 643 void TraceLog::AddEnabledStateObserver(EnabledStateChangedObserver* listener) { |
| 588 enabled_state_observer_list_.AddObserver(listener); | 644 enabled_state_observer_list_.AddObserver(listener); |
| 589 } | 645 } |
| 590 | 646 |
| 591 void TraceLog::RemoveEnabledStateObserver( | 647 void TraceLog::RemoveEnabledStateObserver( |
| 592 EnabledStateChangedObserver* listener) { | 648 EnabledStateChangedObserver* listener) { |
| 593 enabled_state_observer_list_.RemoveObserver(listener); | 649 enabled_state_observer_list_.RemoveObserver(listener); |
| 594 } | 650 } |
| 595 | 651 |
| 596 float TraceLog::GetBufferPercentFull() const { | 652 float TraceLog::GetBufferPercentFull() const { |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 862 0, // num_args | 918 0, // num_args |
| 863 NULL, // arg_names | 919 NULL, // arg_names |
| 864 NULL, // arg_types | 920 NULL, // arg_types |
| 865 NULL, // arg_values | 921 NULL, // arg_values |
| 866 TRACE_EVENT_FLAG_NONE); // flags | 922 TRACE_EVENT_FLAG_NONE); // flags |
| 867 } | 923 } |
| 868 } | 924 } |
| 869 | 925 |
| 870 } // namespace trace_event_internal | 926 } // namespace trace_event_internal |
| 871 | 927 |
| OLD | NEW |