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/trace_event/trace_event_impl.h" | 5 #include "base/trace_event/trace_event_impl.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cmath> | 8 #include <cmath> |
9 | 9 |
10 #include "base/base_switches.h" | 10 #include "base/base_switches.h" |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
13 #include "base/debug/leak_annotations.h" | 13 #include "base/debug/leak_annotations.h" |
14 #include "base/format_macros.h" | 14 #include "base/format_macros.h" |
15 #include "base/json/json_reader.h" | |
16 #include "base/json/json_writer.h" | |
15 #include "base/json/string_escape.h" | 17 #include "base/json/string_escape.h" |
16 #include "base/lazy_instance.h" | 18 #include "base/lazy_instance.h" |
17 #include "base/location.h" | 19 #include "base/location.h" |
18 #include "base/memory/singleton.h" | 20 #include "base/memory/singleton.h" |
19 #include "base/process/process_metrics.h" | 21 #include "base/process/process_metrics.h" |
20 #include "base/stl_util.h" | 22 #include "base/stl_util.h" |
21 #include "base/strings/string_number_conversions.h" | 23 #include "base/strings/string_number_conversions.h" |
22 #include "base/strings/string_split.h" | 24 #include "base/strings/string_split.h" |
23 #include "base/strings/string_tokenizer.h" | 25 #include "base/strings/string_tokenizer.h" |
24 #include "base/strings/string_util.h" | 26 #include "base/strings/string_util.h" |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
62 const int kOverheadReportThresholdInMicroseconds = 50; | 64 const int kOverheadReportThresholdInMicroseconds = 50; |
63 | 65 |
64 // String options that can be used to initialize TraceOptions. | 66 // String options that can be used to initialize TraceOptions. |
65 const char kRecordUntilFull[] = "record-until-full"; | 67 const char kRecordUntilFull[] = "record-until-full"; |
66 const char kRecordContinuously[] = "record-continuously"; | 68 const char kRecordContinuously[] = "record-continuously"; |
67 const char kRecordAsMuchAsPossible[] = "record-as-much-as-possible"; | 69 const char kRecordAsMuchAsPossible[] = "record-as-much-as-possible"; |
68 const char kTraceToConsole[] = "trace-to-console"; | 70 const char kTraceToConsole[] = "trace-to-console"; |
69 const char kEnableSampling[] = "enable-sampling"; | 71 const char kEnableSampling[] = "enable-sampling"; |
70 const char kEnableSystrace[] = "enable-systrace"; | 72 const char kEnableSystrace[] = "enable-systrace"; |
71 | 73 |
74 // String parameters that can be used to parse the trace config string. | |
75 const char kRecordModeParam[] = "record_mode"; | |
76 const char kEnableSamplingParam[] = "enable_sampling"; | |
77 const char kEnableSystraceParam[] = "enable_systrace"; | |
78 const char kIncludedCategoriesParam[] = "included_categories"; | |
79 const char kDisabledCategoriesParam[] = "disabled_categories"; | |
80 const char kExcludedCategoriesParam[] = "excluded_categories"; | |
81 const char kSyntheticDelaysParam[] = "synthetic_delays"; | |
82 | |
72 // Controls the number of trace events we will buffer in-memory | 83 // Controls the number of trace events we will buffer in-memory |
73 // before throwing them away. | 84 // before throwing them away. |
74 const size_t kTraceBufferChunkSize = TraceBufferChunk::kTraceBufferChunkSize; | 85 const size_t kTraceBufferChunkSize = TraceBufferChunk::kTraceBufferChunkSize; |
75 const size_t kTraceEventVectorBigBufferChunks = | 86 const size_t kTraceEventVectorBigBufferChunks = |
76 512000000 / kTraceBufferChunkSize; | 87 512000000 / kTraceBufferChunkSize; |
77 const size_t kTraceEventVectorBufferChunks = 256000 / kTraceBufferChunkSize; | 88 const size_t kTraceEventVectorBufferChunks = 256000 / kTraceBufferChunkSize; |
78 const size_t kTraceEventRingBufferChunks = kTraceEventVectorBufferChunks / 4; | 89 const size_t kTraceEventRingBufferChunks = kTraceEventVectorBufferChunks / 4; |
79 const size_t kTraceEventBufferSizeInBytes = 100 * 1024; | 90 const size_t kTraceEventBufferSizeInBytes = 100 * 1024; |
80 // Can store results for 30 seconds with 1 ms sampling interval. | 91 // Can store results for 30 seconds with 1 ms sampling interval. |
81 const size_t kMonitorTraceEventBufferChunks = 30000 / kTraceBufferChunkSize; | 92 const size_t kMonitorTraceEventBufferChunks = 30000 / kTraceBufferChunkSize; |
(...skipping 2298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2380 void TraceLog::SetCurrentThreadBlocksMessageLoop() { | 2391 void TraceLog::SetCurrentThreadBlocksMessageLoop() { |
2381 thread_blocks_message_loop_.Set(true); | 2392 thread_blocks_message_loop_.Set(true); |
2382 if (thread_local_event_buffer_.Get()) { | 2393 if (thread_local_event_buffer_.Get()) { |
2383 // This will flush the thread local buffer. | 2394 // This will flush the thread local buffer. |
2384 delete thread_local_event_buffer_.Get(); | 2395 delete thread_local_event_buffer_.Get(); |
2385 } | 2396 } |
2386 } | 2397 } |
2387 | 2398 |
2388 bool CategoryFilter::IsEmptyOrContainsLeadingOrTrailingWhitespace( | 2399 bool CategoryFilter::IsEmptyOrContainsLeadingOrTrailingWhitespace( |
2389 const std::string& str) { | 2400 const std::string& str) { |
2390 return str.empty() || | 2401 return TraceConfig::IsEmptyOrContainsLeadingOrTrailingWhitespace(str); |
2391 str.at(0) == ' ' || | |
2392 str.at(str.length() - 1) == ' '; | |
2393 } | 2402 } |
2394 | 2403 |
2395 CategoryFilter::CategoryFilter(const std::string& filter_string) { | 2404 CategoryFilter::CategoryFilter(const std::string& filter_string) |
2396 if (!filter_string.empty()) | 2405 : config_(new TraceConfig(filter_string, "")) { |
2397 Initialize(filter_string); | |
2398 else | |
2399 Initialize(CategoryFilter::kDefaultCategoryFilterString); | |
2400 } | 2406 } |
2401 | 2407 |
2402 CategoryFilter::CategoryFilter() { | 2408 CategoryFilter::CategoryFilter() |
2403 Initialize(CategoryFilter::kDefaultCategoryFilterString); | 2409 : config_(new TraceConfig()) { |
2404 } | 2410 } |
2405 | 2411 |
2406 CategoryFilter::CategoryFilter(const CategoryFilter& cf) | 2412 CategoryFilter::CategoryFilter(const CategoryFilter& cf) |
2407 : included_(cf.included_), | 2413 : config_(new TraceConfig(*(cf.config_))) { |
2408 disabled_(cf.disabled_), | |
2409 excluded_(cf.excluded_), | |
2410 delays_(cf.delays_) { | |
2411 } | 2414 } |
2412 | 2415 |
2413 CategoryFilter::~CategoryFilter() { | 2416 CategoryFilter::~CategoryFilter() { |
2414 } | 2417 } |
2415 | 2418 |
2416 CategoryFilter& CategoryFilter::operator=(const CategoryFilter& rhs) { | 2419 CategoryFilter& CategoryFilter::operator=(const CategoryFilter& rhs) { |
2417 if (this == &rhs) | 2420 if (this == &rhs) |
2418 return *this; | 2421 return *this; |
2419 | 2422 |
2420 included_ = rhs.included_; | 2423 config_.reset(new TraceConfig(*(rhs.config_))); |
2421 disabled_ = rhs.disabled_; | |
2422 excluded_ = rhs.excluded_; | |
2423 delays_ = rhs.delays_; | |
2424 return *this; | 2424 return *this; |
2425 } | 2425 } |
2426 | 2426 |
2427 void CategoryFilter::Initialize(const std::string& filter_string) { | |
2428 // Tokenize list of categories, delimited by ','. | |
2429 StringTokenizer tokens(filter_string, ","); | |
2430 // Add each token to the appropriate list (included_,excluded_). | |
2431 while (tokens.GetNext()) { | |
2432 std::string category = tokens.token(); | |
2433 // Ignore empty categories. | |
2434 if (category.empty()) | |
2435 continue; | |
2436 // Synthetic delays are of the form 'DELAY(delay;option;option;...)'. | |
2437 if (category.find(kSyntheticDelayCategoryFilterPrefix) == 0 && | |
2438 category.at(category.size() - 1) == ')') { | |
2439 category = category.substr( | |
2440 strlen(kSyntheticDelayCategoryFilterPrefix), | |
2441 category.size() - strlen(kSyntheticDelayCategoryFilterPrefix) - 1); | |
2442 size_t name_length = category.find(';'); | |
2443 if (name_length != std::string::npos && name_length > 0 && | |
2444 name_length != category.size() - 1) { | |
2445 delays_.push_back(category); | |
2446 } | |
2447 } else if (category.at(0) == '-') { | |
2448 // Excluded categories start with '-'. | |
2449 // Remove '-' from category string. | |
2450 category = category.substr(1); | |
2451 excluded_.push_back(category); | |
2452 } else if (category.compare(0, strlen(TRACE_DISABLED_BY_DEFAULT("")), | |
2453 TRACE_DISABLED_BY_DEFAULT("")) == 0) { | |
2454 disabled_.push_back(category); | |
2455 } else { | |
2456 included_.push_back(category); | |
2457 } | |
2458 } | |
2459 } | |
2460 | |
2461 void CategoryFilter::WriteString(const StringList& values, | 2427 void CategoryFilter::WriteString(const StringList& values, |
2462 std::string* out, | 2428 std::string* out, |
2463 bool included) const { | 2429 bool included) const { |
2464 bool prepend_comma = !out->empty(); | 2430 bool prepend_comma = !out->empty(); |
2465 int token_cnt = 0; | 2431 int token_cnt = 0; |
2466 for (StringList::const_iterator ci = values.begin(); | 2432 for (StringList::const_iterator ci = values.begin(); |
2467 ci != values.end(); ++ci) { | 2433 ci != values.end(); ++ci) { |
2468 if (token_cnt > 0 || prepend_comma) | 2434 if (token_cnt > 0 || prepend_comma) |
2469 StringAppendF(out, ","); | 2435 StringAppendF(out, ","); |
2470 StringAppendF(out, "%s%s", (included ? "" : "-"), ci->c_str()); | 2436 StringAppendF(out, "%s%s", (included ? "" : "-"), ci->c_str()); |
(...skipping 10 matching lines...) Expand all Loading... | |
2481 if (token_cnt > 0 || prepend_comma) | 2447 if (token_cnt > 0 || prepend_comma) |
2482 StringAppendF(out, ","); | 2448 StringAppendF(out, ","); |
2483 StringAppendF(out, "%s%s)", kSyntheticDelayCategoryFilterPrefix, | 2449 StringAppendF(out, "%s%s)", kSyntheticDelayCategoryFilterPrefix, |
2484 ci->c_str()); | 2450 ci->c_str()); |
2485 ++token_cnt; | 2451 ++token_cnt; |
2486 } | 2452 } |
2487 } | 2453 } |
2488 | 2454 |
2489 std::string CategoryFilter::ToString() const { | 2455 std::string CategoryFilter::ToString() const { |
2490 std::string filter_string; | 2456 std::string filter_string; |
2491 WriteString(included_, &filter_string, true); | 2457 WriteString(config_->included_categories_, &filter_string, true); |
2492 WriteString(disabled_, &filter_string, true); | 2458 WriteString(config_->disabled_categories_, &filter_string, true); |
2493 WriteString(excluded_, &filter_string, false); | 2459 WriteString(config_->excluded_categories_, &filter_string, false); |
2494 WriteString(delays_, &filter_string); | 2460 WriteString(config_->synthetic_delays_, &filter_string); |
2495 return filter_string; | 2461 return filter_string; |
2496 } | 2462 } |
2497 | 2463 |
2498 bool CategoryFilter::IsCategoryGroupEnabled( | 2464 bool CategoryFilter::IsCategoryGroupEnabled( |
2499 const char* category_group_name) const { | 2465 const char* category_group_name) const { |
2466 return config_->IsCategoryGroupEnabled(category_group_name); | |
2467 } | |
2468 | |
2469 bool CategoryFilter::IsCategoryEnabled(const char* category_name) const { | |
2470 return config_->IsCategoryEnabled(category_name); | |
2471 } | |
2472 | |
2473 bool CategoryFilter::HasIncludedPatterns() const { | |
2474 return config_->HasIncludedPatterns(); | |
2475 } | |
2476 | |
2477 void CategoryFilter::Merge(const CategoryFilter& nested_filter) { | |
2478 config_->Merge(*(nested_filter.config_)); | |
2479 } | |
2480 | |
2481 void CategoryFilter::Clear() { | |
2482 config_->included_categories_.clear(); | |
2483 config_->disabled_categories_.clear(); | |
2484 config_->excluded_categories_.clear(); | |
2485 } | |
2486 | |
2487 const CategoryFilter::StringList& | |
2488 CategoryFilter::GetSyntheticDelayValues() const { | |
2489 return config_->GetSyntheticDelayValues(); | |
2490 } | |
2491 | |
2492 //////////////////////////////////////////////////////////////////////////////// | |
2493 // | |
2494 // TraceConfig | |
2495 // | |
2496 //////////////////////////////////////////////////////////////////////////////// | |
2497 | |
2498 TraceConfig::TraceConfig() { | |
2499 Initialize(TraceConfig::kDefaultTraceConfigString); | |
2500 } | |
2501 | |
2502 TraceConfig::TraceConfig(const CategoryFilter& cf, | |
2503 const TraceOptions& options) { | |
2504 record_mode_ = options.record_mode; | |
2505 enable_sampling_ = options.enable_sampling; | |
2506 enable_systrace_ = options.enable_systrace; | |
2507 | |
2508 included_categories_ = cf.config_->included_categories_; | |
2509 disabled_categories_ = cf.config_->disabled_categories_; | |
2510 excluded_categories_ = cf.config_->excluded_categories_; | |
2511 synthetic_delays_ = cf.config_->synthetic_delays_; | |
2512 } | |
2513 | |
2514 TraceConfig::TraceConfig(const std::string& category_filter_string, | |
2515 const std::string& trace_options_string) { | |
2516 if (!category_filter_string.empty()) { | |
2517 // Tokenize list of categories, delimited by ','. | |
2518 StringTokenizer tokens(category_filter_string, ","); | |
nednguyen
2015/05/11 17:59:28
nits: you want to be consistent about using single
Zhen Wang
2015/05/13 00:01:10
Use SplitString now.
| |
2519 // Add each token to the appropriate list (included_,excluded_). | |
2520 while (tokens.GetNext()) { | |
2521 std::string category = tokens.token(); | |
2522 // Ignore empty categories. | |
2523 if (category.empty()) | |
2524 continue; | |
2525 // Synthetic delays are of the form 'DELAY(delay;option;option;...)'. | |
nednguyen
2015/05/11 17:59:28
What about cases like ' Delay(delay; option; opt
Zhen Wang
2015/05/13 00:01:10
Use SplitString now to get leading-and-trailing-sp
| |
2526 if (category.find(kSyntheticDelayCategoryFilterPrefix) == 0 && | |
2527 category.at(category.size() - 1) == ')') { | |
2528 category = category.substr( | |
2529 strlen(kSyntheticDelayCategoryFilterPrefix), | |
2530 category.size() - strlen(kSyntheticDelayCategoryFilterPrefix) - 1); | |
2531 size_t name_length = category.find(';'); | |
2532 if (name_length != std::string::npos && name_length > 0 && | |
2533 name_length != category.size() - 1) { | |
2534 synthetic_delays_.push_back(category); | |
2535 } | |
2536 } else if (category.at(0) == '-') { | |
2537 // Excluded categories start with '-'. | |
2538 // Remove '-' from category string. | |
2539 category = category.substr(1); | |
2540 excluded_categories_.push_back(category); | |
2541 } else if (category.compare(0, strlen(TRACE_DISABLED_BY_DEFAULT("")), | |
2542 TRACE_DISABLED_BY_DEFAULT("")) == 0) { | |
2543 disabled_categories_.push_back(category); | |
2544 } else { | |
2545 included_categories_.push_back(category); | |
2546 } | |
2547 } | |
2548 } else { | |
2549 Initialize(TraceConfig::kDefaultTraceConfigString); | |
2550 } | |
2551 | |
2552 record_mode_ = RECORD_UNTIL_FULL; | |
2553 enable_sampling_ = false; | |
2554 enable_systrace_ = false; | |
2555 if(!trace_options_string.empty()) { | |
2556 std::vector<std::string> split; | |
2557 std::vector<std::string>::iterator iter; | |
2558 base::SplitString(trace_options_string, ',', &split); | |
nednguyen
2015/05/11 17:59:28
while use StringTokenizer above but use SplitStrin
Zhen Wang
2015/05/13 00:01:10
Updated above with SplitString, so that leading an
| |
2559 for (iter = split.begin(); iter != split.end(); ++iter) { | |
2560 if (*iter == kRecordUntilFull) { | |
2561 record_mode_ = RECORD_UNTIL_FULL; | |
2562 } else if (*iter == kRecordContinuously) { | |
2563 record_mode_ = RECORD_CONTINUOUSLY; | |
2564 } else if (*iter == kTraceToConsole) { | |
2565 record_mode_ = ECHO_TO_CONSOLE; | |
2566 } else if (*iter == kRecordAsMuchAsPossible) { | |
2567 record_mode_ = RECORD_AS_MUCH_AS_POSSIBLE; | |
2568 } else if (*iter == kEnableSampling) { | |
2569 enable_sampling_ = true; | |
2570 } else if (*iter == kEnableSystrace) { | |
2571 enable_systrace_ = true; | |
2572 } | |
2573 } | |
2574 } | |
2575 } | |
2576 | |
2577 TraceConfig::TraceConfig(const std::string& config_string) { | |
2578 if (!config_string.empty()) | |
2579 Initialize(config_string); | |
2580 else | |
2581 Initialize(TraceConfig::kDefaultTraceConfigString); | |
2582 } | |
2583 | |
2584 TraceConfig::TraceConfig(const TraceConfig& tc) | |
2585 : record_mode_(tc.record_mode_), | |
2586 enable_sampling_(tc.enable_sampling_), | |
2587 enable_systrace_(tc.enable_systrace_), | |
2588 included_categories_(tc.included_categories_), | |
2589 disabled_categories_(tc.disabled_categories_), | |
2590 excluded_categories_(tc.excluded_categories_), | |
2591 synthetic_delays_(tc.synthetic_delays_) { | |
2592 } | |
2593 | |
2594 TraceConfig::~TraceConfig() { | |
2595 } | |
2596 | |
2597 TraceConfig& TraceConfig::operator=(const TraceConfig& rhs) { | |
2598 if (this == &rhs) | |
2599 return *this; | |
2600 | |
2601 record_mode_ = rhs.record_mode_; | |
2602 enable_sampling_ = rhs.enable_sampling_; | |
2603 enable_systrace_ = rhs.enable_systrace_; | |
2604 included_categories_ = rhs.included_categories_; | |
2605 disabled_categories_ = rhs.disabled_categories_; | |
2606 excluded_categories_ = rhs.excluded_categories_; | |
2607 synthetic_delays_ = rhs.synthetic_delays_; | |
2608 return *this; | |
2609 } | |
2610 | |
2611 const TraceConfig::StringList& TraceConfig::GetSyntheticDelayValues() const { | |
2612 return synthetic_delays_; | |
2613 } | |
2614 | |
2615 void TraceConfig::ToCategoryFilter(CategoryFilter& cf) const { | |
2616 cf.config_.reset(new TraceConfig(*this)); | |
2617 } | |
2618 | |
2619 void TraceConfig::ToTraceOptions(TraceOptions& options) const { | |
2620 options.record_mode = record_mode_; | |
2621 options.enable_sampling = enable_sampling_; | |
2622 options.enable_systrace = enable_systrace_; | |
2623 } | |
2624 | |
2625 void TraceConfig::ToDict(base::DictionaryValue& dict) const { | |
2626 switch (record_mode_) { | |
2627 case RECORD_UNTIL_FULL: | |
2628 dict.SetString(kRecordModeParam, kRecordUntilFull); | |
2629 break; | |
2630 case RECORD_CONTINUOUSLY: | |
2631 dict.SetString(kRecordModeParam, kRecordContinuously); | |
2632 break; | |
2633 case ECHO_TO_CONSOLE: | |
2634 dict.SetString(kRecordModeParam, kTraceToConsole); | |
2635 break; | |
2636 case RECORD_AS_MUCH_AS_POSSIBLE: | |
2637 dict.SetString(kRecordModeParam, kRecordAsMuchAsPossible); | |
2638 break; | |
2639 default: | |
2640 NOTREACHED(); | |
2641 } | |
2642 | |
2643 if (enable_sampling_) | |
2644 dict.SetBoolean(kEnableSamplingParam, true); | |
2645 else | |
2646 dict.SetBoolean(kEnableSamplingParam, false); | |
2647 | |
2648 if (enable_systrace_) | |
2649 dict.SetBoolean(kEnableSystraceParam, true); | |
2650 else | |
2651 dict.SetBoolean(kEnableSystraceParam, false); | |
2652 | |
2653 AddCategoryToDict(dict, kIncludedCategoriesParam, included_categories_); | |
2654 AddCategoryToDict(dict, kDisabledCategoriesParam, disabled_categories_); | |
2655 AddCategoryToDict(dict, kExcludedCategoriesParam, excluded_categories_); | |
2656 AddCategoryToDict(dict, kSyntheticDelaysParam, synthetic_delays_); | |
2657 } | |
2658 | |
2659 std::string TraceConfig::ToString() const { | |
2660 base::DictionaryValue dict; | |
2661 ToDict(dict); | |
2662 | |
2663 std::string json; | |
2664 base::JSONWriter::Write(&dict, &json); | |
2665 | |
2666 return json; | |
2667 } | |
2668 | |
2669 std::string TraceConfig::ToCategoryFilterString() const { | |
2670 CategoryFilter cf; | |
2671 ToCategoryFilter(cf); | |
2672 return cf.ToString(); | |
2673 } | |
2674 | |
2675 std::string TraceConfig::ToTraceOptionsString() const { | |
2676 TraceOptions to; | |
2677 ToTraceOptions(to); | |
2678 return to.ToString(); | |
2679 } | |
2680 | |
2681 void TraceConfig::AddCategoryToDict(base::DictionaryValue& dict, | |
2682 const char* param, | |
2683 const StringList& categories) const { | |
2684 if (categories.empty()) | |
2685 return; | |
2686 | |
2687 scoped_ptr<base::ListValue> list(new base::ListValue()); | |
2688 for (StringList::const_iterator ci = categories.begin(); | |
2689 ci != categories.end(); | |
2690 ++ci) { | |
2691 list->AppendString(*ci); | |
2692 } | |
2693 | |
2694 dict.Set(param, list.Pass()); | |
2695 } | |
2696 | |
2697 void TraceConfig::Merge(const TraceConfig& config) { | |
2698 if (record_mode_ != config.record_mode_ | |
2699 || enable_sampling_ != config.enable_sampling_ | |
2700 || enable_systrace_ != config.enable_systrace_) { | |
2701 DLOG(ERROR) << "Attempting to merge trace config with a different " | |
2702 << "set of options."; | |
2703 } | |
2704 | |
2705 // Keep included patterns only if both filters have an included entry. | |
2706 // Otherwise, one of the filter was specifying "*" and we want to honor the | |
2707 // broadest filter. | |
2708 if (HasIncludedPatterns() && config.HasIncludedPatterns()) { | |
2709 included_categories_.insert(included_categories_.end(), | |
2710 config.included_categories_.begin(), | |
2711 config.included_categories_.end()); | |
2712 } else { | |
2713 included_categories_.clear(); | |
2714 } | |
2715 | |
2716 disabled_categories_.insert(disabled_categories_.end(), | |
2717 config.disabled_categories_.begin(), | |
2718 config.disabled_categories_.end()); | |
2719 excluded_categories_.insert(excluded_categories_.end(), | |
2720 config.excluded_categories_.begin(), | |
2721 config.excluded_categories_.end()); | |
2722 synthetic_delays_.insert(synthetic_delays_.end(), | |
2723 config.synthetic_delays_.begin(), | |
2724 config.synthetic_delays_.end()); | |
2725 } | |
2726 | |
2727 void TraceConfig::Clear() { | |
2728 record_mode_ = RECORD_UNTIL_FULL; | |
2729 enable_sampling_ = false; | |
2730 enable_systrace_ = false; | |
2731 included_categories_.clear(); | |
2732 disabled_categories_.clear(); | |
2733 excluded_categories_.clear(); | |
2734 synthetic_delays_.clear(); | |
2735 } | |
2736 | |
2737 | |
2738 void TraceConfig::Initialize(const std::string& config_string) { | |
dsinclair
2015/05/08 17:44:49
Can you move this up to just below the constructor
Zhen Wang
2015/05/13 00:01:10
Done.
| |
2739 scoped_ptr<base::Value> value(base::JSONReader::Read(config_string)); | |
2740 if (!value || !value->IsType(base::Value::TYPE_DICTIONARY)) | |
2741 return; | |
2742 scoped_ptr<base::DictionaryValue> dict( | |
2743 static_cast<base::DictionaryValue*>(value.release())); | |
2744 | |
2745 std::string record_mode; | |
2746 if (dict->GetString(kRecordModeParam, &record_mode)) { | |
2747 if (record_mode == kRecordUntilFull) { | |
2748 record_mode_ = RECORD_UNTIL_FULL; | |
2749 } else if (record_mode == kRecordContinuously) { | |
2750 record_mode_ = RECORD_CONTINUOUSLY; | |
2751 } else if (record_mode == kTraceToConsole) { | |
2752 record_mode_ = ECHO_TO_CONSOLE; | |
2753 } else if (record_mode == kRecordAsMuchAsPossible) { | |
2754 record_mode_ = RECORD_AS_MUCH_AS_POSSIBLE; | |
2755 } | |
2756 } else { | |
2757 record_mode_ = RECORD_UNTIL_FULL; | |
2758 } | |
2759 | |
2760 if (!dict->GetBoolean(kEnableSamplingParam, &enable_sampling_)) | |
2761 enable_sampling_ = false; | |
2762 if (!dict->GetBoolean(kEnableSystraceParam, &enable_systrace_)) | |
2763 enable_systrace_ = false; | |
2764 | |
2765 base::ListValue* category_list = NULL; | |
2766 if (dict->GetList(kIncludedCategoriesParam, &category_list)) | |
2767 SetCategoriesFromList(included_categories_, *category_list); | |
2768 if (dict->GetList(kDisabledCategoriesParam, &category_list)) | |
2769 SetCategoriesFromList(disabled_categories_, *category_list); | |
2770 if (dict->GetList(kExcludedCategoriesParam, &category_list)) | |
2771 SetCategoriesFromList(excluded_categories_, *category_list); | |
2772 if (dict->GetList(kSyntheticDelaysParam, &category_list)) | |
2773 SetCategoriesFromList(synthetic_delays_, *category_list); | |
2774 } | |
2775 | |
2776 void TraceConfig::SetCategoriesFromList(StringList& categories, | |
2777 const base::ListValue& list) { | |
2778 categories.clear(); | |
2779 for (size_t i = 0; i < list.GetSize(); ++i) { | |
2780 std::string category; | |
2781 if (list.GetString(i, &category)) | |
2782 categories.push_back(category); | |
2783 } | |
2784 } | |
2785 | |
2786 bool TraceConfig::IsCategoryGroupEnabled( | |
2787 const char* category_group_name) const { | |
2500 // TraceLog should call this method only as part of enabling/disabling | 2788 // TraceLog should call this method only as part of enabling/disabling |
2501 // categories. | 2789 // categories. |
2502 | 2790 |
2503 bool had_enabled_by_default = false; | 2791 bool had_enabled_by_default = false; |
2504 DCHECK(category_group_name); | 2792 DCHECK(category_group_name); |
2505 CStringTokenizer category_group_tokens( | 2793 CStringTokenizer category_group_tokens( |
2506 category_group_name, category_group_name + strlen(category_group_name), | 2794 category_group_name, category_group_name + strlen(category_group_name), |
2507 ","); | 2795 ","); |
2508 while (category_group_tokens.GetNext()) { | 2796 while (category_group_tokens.GetNext()) { |
2509 std::string category_group_token = category_group_tokens.token(); | 2797 std::string category_group_token = category_group_tokens.token(); |
2510 // Don't allow empty tokens, nor tokens with leading or trailing space. | 2798 // Don't allow empty tokens, nor tokens with leading or trailing space. |
2511 DCHECK(!CategoryFilter::IsEmptyOrContainsLeadingOrTrailingWhitespace( | 2799 DCHECK(!TraceConfig::IsEmptyOrContainsLeadingOrTrailingWhitespace( |
2512 category_group_token)) | 2800 category_group_token)) |
2513 << "Disallowed category string"; | 2801 << "Disallowed category string"; |
2514 if (IsCategoryEnabled(category_group_token.c_str())) { | 2802 if (IsCategoryEnabled(category_group_token.c_str())) { |
2515 return true; | 2803 return true; |
2516 } | 2804 } |
2517 if (!MatchPattern(category_group_token.c_str(), | 2805 if (!MatchPattern(category_group_token.c_str(), |
2518 TRACE_DISABLED_BY_DEFAULT("*"))) | 2806 TRACE_DISABLED_BY_DEFAULT("*"))) |
2519 had_enabled_by_default = true; | 2807 had_enabled_by_default = true; |
2520 } | 2808 } |
2521 // Do a second pass to check for explicitly disabled categories | 2809 // Do a second pass to check for explicitly disabled categories |
2522 // (those explicitly enabled have priority due to first pass). | 2810 // (those explicitly enabled have priority due to first pass). |
2523 category_group_tokens.Reset(); | 2811 category_group_tokens.Reset(); |
2524 bool category_group_disabled = false; | 2812 bool category_group_disabled = false; |
2525 while (category_group_tokens.GetNext()) { | 2813 while (category_group_tokens.GetNext()) { |
2526 std::string category_group_token = category_group_tokens.token(); | 2814 std::string category_group_token = category_group_tokens.token(); |
2527 for (StringList::const_iterator ci = excluded_.begin(); | 2815 for (StringList::const_iterator ci = excluded_categories_.begin(); |
2528 ci != excluded_.end(); ++ci) { | 2816 ci != excluded_categories_.end(); |
2817 ++ci) { | |
2529 if (MatchPattern(category_group_token.c_str(), ci->c_str())) { | 2818 if (MatchPattern(category_group_token.c_str(), ci->c_str())) { |
2530 // Current token of category_group_name is present in excluded_list. | 2819 // Current token of category_group_name is present in excluded_list. |
2531 // Flag the exclusion and proceed further to check if any of the | 2820 // Flag the exclusion and proceed further to check if any of the |
2532 // remaining categories of category_group_name is not present in the | 2821 // remaining categories of category_group_name is not present in the |
2533 // excluded_ list. | 2822 // excluded_ list. |
2534 category_group_disabled = true; | 2823 category_group_disabled = true; |
2535 break; | 2824 break; |
2536 } | 2825 } |
2537 // One of the category of category_group_name is not present in | 2826 // One of the category of category_group_name is not present in |
2538 // excluded_ list. So, it has to be included_ list. Enable the | 2827 // excluded_ list. So, it has to be included_ list. Enable the |
2539 // category_group_name for recording. | 2828 // category_group_name for recording. |
2540 category_group_disabled = false; | 2829 category_group_disabled = false; |
2541 } | 2830 } |
2542 // One of the categories present in category_group_name is not present in | 2831 // One of the categories present in category_group_name is not present in |
2543 // excluded_ list. Implies this category_group_name group can be enabled | 2832 // excluded_ list. Implies this category_group_name group can be enabled |
2544 // for recording, since one of its groups is enabled for recording. | 2833 // for recording, since one of its groups is enabled for recording. |
2545 if (!category_group_disabled) | 2834 if (!category_group_disabled) |
2546 break; | 2835 break; |
2547 } | 2836 } |
2548 // If the category group is not excluded, and there are no included patterns | 2837 // If the category group is not excluded, and there are no included patterns |
2549 // we consider this category group enabled, as long as it had categories | 2838 // we consider this category group enabled, as long as it had categories |
2550 // other than disabled-by-default. | 2839 // other than disabled-by-default. |
2551 return !category_group_disabled && | 2840 return !category_group_disabled && |
2552 included_.empty() && had_enabled_by_default; | 2841 included_categories_.empty() && had_enabled_by_default; |
2553 } | 2842 } |
2554 | 2843 |
2555 bool CategoryFilter::IsCategoryEnabled(const char* category_name) const { | 2844 bool TraceConfig::IsCategoryEnabled(const char* category_name) const { |
2556 StringList::const_iterator ci; | 2845 StringList::const_iterator ci; |
2557 | 2846 |
2558 // Check the disabled- filters and the disabled-* wildcard first so that a | 2847 // Check the disabled- filters and the disabled-* wildcard first so that a |
2559 // "*" filter does not include the disabled. | 2848 // "*" filter does not include the disabled. |
2560 for (ci = disabled_.begin(); ci != disabled_.end(); ++ci) { | 2849 for (ci = disabled_categories_.begin(); |
2850 ci != disabled_categories_.end(); | |
2851 ++ci) { | |
2561 if (MatchPattern(category_name, ci->c_str())) | 2852 if (MatchPattern(category_name, ci->c_str())) |
2562 return true; | 2853 return true; |
2563 } | 2854 } |
2564 | 2855 |
2565 if (MatchPattern(category_name, TRACE_DISABLED_BY_DEFAULT("*"))) | 2856 if (MatchPattern(category_name, TRACE_DISABLED_BY_DEFAULT("*"))) |
2566 return false; | 2857 return false; |
2567 | 2858 |
2568 for (ci = included_.begin(); ci != included_.end(); ++ci) { | 2859 for (ci = included_categories_.begin(); |
2860 ci != included_categories_.end(); | |
2861 ++ci) { | |
2569 if (MatchPattern(category_name, ci->c_str())) | 2862 if (MatchPattern(category_name, ci->c_str())) |
2570 return true; | 2863 return true; |
2571 } | 2864 } |
2572 | 2865 |
2573 return false; | 2866 return false; |
2574 } | 2867 } |
2575 | 2868 |
2576 bool CategoryFilter::HasIncludedPatterns() const { | 2869 bool TraceConfig::IsEmptyOrContainsLeadingOrTrailingWhitespace( |
2577 return !included_.empty(); | 2870 const std::string& str) { |
2871 return str.empty() || | |
2872 str.at(0) == ' ' || | |
2873 str.at(str.length() - 1) == ' '; | |
2578 } | 2874 } |
2579 | 2875 |
2580 void CategoryFilter::Merge(const CategoryFilter& nested_filter) { | 2876 bool TraceConfig::HasIncludedPatterns() const { |
2581 // Keep included patterns only if both filters have an included entry. | 2877 return !included_categories_.empty(); |
2582 // Otherwise, one of the filter was specifying "*" and we want to honour the | |
2583 // broadest filter. | |
2584 if (HasIncludedPatterns() && nested_filter.HasIncludedPatterns()) { | |
2585 included_.insert(included_.end(), | |
2586 nested_filter.included_.begin(), | |
2587 nested_filter.included_.end()); | |
2588 } else { | |
2589 included_.clear(); | |
2590 } | |
2591 | |
2592 disabled_.insert(disabled_.end(), | |
2593 nested_filter.disabled_.begin(), | |
2594 nested_filter.disabled_.end()); | |
2595 excluded_.insert(excluded_.end(), | |
2596 nested_filter.excluded_.begin(), | |
2597 nested_filter.excluded_.end()); | |
2598 delays_.insert(delays_.end(), | |
2599 nested_filter.delays_.begin(), | |
2600 nested_filter.delays_.end()); | |
2601 } | |
2602 | |
2603 void CategoryFilter::Clear() { | |
2604 included_.clear(); | |
2605 disabled_.clear(); | |
2606 excluded_.clear(); | |
2607 } | |
2608 | |
2609 const CategoryFilter::StringList& | |
2610 CategoryFilter::GetSyntheticDelayValues() const { | |
2611 return delays_; | |
2612 } | 2878 } |
2613 | 2879 |
2614 } // namespace trace_event | 2880 } // namespace trace_event |
2615 } // namespace base | 2881 } // namespace base |
2616 | 2882 |
2617 namespace trace_event_internal { | 2883 namespace trace_event_internal { |
2618 | 2884 |
2619 ScopedTraceBinaryEfficient::ScopedTraceBinaryEfficient( | 2885 ScopedTraceBinaryEfficient::ScopedTraceBinaryEfficient( |
2620 const char* category_group, const char* name) { | 2886 const char* category_group, const char* name) { |
2621 // The single atom works because for now the category_group can only be "gpu". | 2887 // The single atom works because for now the category_group can only be "gpu". |
(...skipping 14 matching lines...) Expand all Loading... | |
2636 } | 2902 } |
2637 | 2903 |
2638 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() { | 2904 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() { |
2639 if (*category_group_enabled_) { | 2905 if (*category_group_enabled_) { |
2640 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, | 2906 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, |
2641 name_, event_handle_); | 2907 name_, event_handle_); |
2642 } | 2908 } |
2643 } | 2909 } |
2644 | 2910 |
2645 } // namespace trace_event_internal | 2911 } // namespace trace_event_internal |
OLD | NEW |