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/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 |