OLD | NEW |
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2015 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_config.h" | 5 #include "base/trace_event/trace_config.h" |
6 | 6 |
7 #include "base/json/json_reader.h" | 7 #include "base/json/json_reader.h" |
8 #include "base/json/json_writer.h" | 8 #include "base/json/json_writer.h" |
9 #include "base/strings/pattern.h" | 9 #include "base/strings/pattern.h" |
10 #include "base/strings/string_split.h" | 10 #include "base/strings/string_split.h" |
11 #include "base/strings/string_tokenizer.h" | 11 #include "base/strings/string_tokenizer.h" |
12 #include "base/strings/stringprintf.h" | 12 #include "base/strings/stringprintf.h" |
| 13 #include "base/trace_event/memory_dump_manager.h" |
13 #include "base/trace_event/trace_event.h" | 14 #include "base/trace_event/trace_event.h" |
14 | 15 |
15 namespace base { | 16 namespace base { |
16 namespace trace_event { | 17 namespace trace_event { |
17 | 18 |
18 namespace { | 19 namespace { |
19 | 20 |
20 // String options that can be used to initialize TraceOptions. | 21 // String options that can be used to initialize TraceOptions. |
21 const char kRecordUntilFull[] = "record-until-full"; | 22 const char kRecordUntilFull[] = "record-until-full"; |
22 const char kRecordContinuously[] = "record-continuously"; | 23 const char kRecordContinuously[] = "record-continuously"; |
23 const char kRecordAsMuchAsPossible[] = "record-as-much-as-possible"; | 24 const char kRecordAsMuchAsPossible[] = "record-as-much-as-possible"; |
24 const char kTraceToConsole[] = "trace-to-console"; | 25 const char kTraceToConsole[] = "trace-to-console"; |
25 const char kEnableSampling[] = "enable-sampling"; | 26 const char kEnableSampling[] = "enable-sampling"; |
26 const char kEnableSystrace[] = "enable-systrace"; | 27 const char kEnableSystrace[] = "enable-systrace"; |
27 const char kEnableArgumentFilter[] = "enable-argument-filter"; | 28 const char kEnableArgumentFilter[] = "enable-argument-filter"; |
28 | 29 |
29 // String parameters that can be used to parse the trace config string. | 30 // String parameters that can be used to parse the trace config string. |
30 const char kRecordModeParam[] = "record_mode"; | 31 const char kRecordModeParam[] = "record_mode"; |
31 const char kEnableSamplingParam[] = "enable_sampling"; | 32 const char kEnableSamplingParam[] = "enable_sampling"; |
32 const char kEnableSystraceParam[] = "enable_systrace"; | 33 const char kEnableSystraceParam[] = "enable_systrace"; |
33 const char kEnableArgumentFilterParam[] = "enable_argument_filter"; | 34 const char kEnableArgumentFilterParam[] = "enable_argument_filter"; |
34 const char kIncludedCategoriesParam[] = "included_categories"; | 35 const char kIncludedCategoriesParam[] = "included_categories"; |
35 const char kExcludedCategoriesParam[] = "excluded_categories"; | 36 const char kExcludedCategoriesParam[] = "excluded_categories"; |
36 const char kSyntheticDelaysParam[] = "synthetic_delays"; | 37 const char kSyntheticDelaysParam[] = "synthetic_delays"; |
37 | 38 |
38 const char kSyntheticDelayCategoryFilterPrefix[] = "DELAY("; | 39 const char kSyntheticDelayCategoryFilterPrefix[] = "DELAY("; |
39 | 40 |
| 41 // String parameters that is used to parse memory dump config in trace config |
| 42 // string. |
| 43 const char kMemoryDumpConfigParam[] = "memory_dump_config"; |
| 44 const char kTriggersParam[] = "triggers"; |
| 45 const char kPeriodicIntervalParam[] = "periodic_interval_ms"; |
| 46 const char kModeParam[] = "mode"; |
| 47 const char kDetailedParam[] = "detailed"; |
| 48 const char kLightParam[] = "light"; |
| 49 |
| 50 // Default configuration of memory dumps. |
| 51 const TraceConfig::MemoryDumpTriggerConfig kDefaultHeavyMemoryDumpTrigger = { |
| 52 2000, // periodic_interval_ms |
| 53 MemoryDumpArgs::LevelOfDetail::HIGH}; |
| 54 const TraceConfig::MemoryDumpTriggerConfig kDefaultLightMemoryDumpTrigger = { |
| 55 250, // periodic_interval_ms |
| 56 MemoryDumpArgs::LevelOfDetail::LOW}; |
| 57 |
40 } // namespace | 58 } // namespace |
41 | 59 |
42 TraceConfig::TraceConfig() { | 60 TraceConfig::TraceConfig() { |
43 InitializeDefault(); | 61 InitializeDefault(); |
44 } | 62 } |
45 | 63 |
46 TraceConfig::TraceConfig(const std::string& category_filter_string, | 64 TraceConfig::TraceConfig(const std::string& category_filter_string, |
47 const std::string& trace_options_string) { | 65 const std::string& trace_options_string) { |
48 InitializeFromStrings(category_filter_string, trace_options_string); | 66 InitializeFromStrings(category_filter_string, trace_options_string); |
49 } | 67 } |
(...skipping 25 matching lines...) Expand all Loading... |
75 InitializeFromConfigString(config_string); | 93 InitializeFromConfigString(config_string); |
76 else | 94 else |
77 InitializeDefault(); | 95 InitializeDefault(); |
78 } | 96 } |
79 | 97 |
80 TraceConfig::TraceConfig(const TraceConfig& tc) | 98 TraceConfig::TraceConfig(const TraceConfig& tc) |
81 : record_mode_(tc.record_mode_), | 99 : record_mode_(tc.record_mode_), |
82 enable_sampling_(tc.enable_sampling_), | 100 enable_sampling_(tc.enable_sampling_), |
83 enable_systrace_(tc.enable_systrace_), | 101 enable_systrace_(tc.enable_systrace_), |
84 enable_argument_filter_(tc.enable_argument_filter_), | 102 enable_argument_filter_(tc.enable_argument_filter_), |
| 103 memory_dump_config_(tc.memory_dump_config_), |
85 included_categories_(tc.included_categories_), | 104 included_categories_(tc.included_categories_), |
86 disabled_categories_(tc.disabled_categories_), | 105 disabled_categories_(tc.disabled_categories_), |
87 excluded_categories_(tc.excluded_categories_), | 106 excluded_categories_(tc.excluded_categories_), |
88 synthetic_delays_(tc.synthetic_delays_) { | 107 synthetic_delays_(tc.synthetic_delays_) {} |
89 } | |
90 | 108 |
91 TraceConfig::~TraceConfig() { | 109 TraceConfig::~TraceConfig() { |
92 } | 110 } |
93 | 111 |
94 TraceConfig& TraceConfig::operator=(const TraceConfig& rhs) { | 112 TraceConfig& TraceConfig::operator=(const TraceConfig& rhs) { |
95 if (this == &rhs) | 113 if (this == &rhs) |
96 return *this; | 114 return *this; |
97 | 115 |
98 record_mode_ = rhs.record_mode_; | 116 record_mode_ = rhs.record_mode_; |
99 enable_sampling_ = rhs.enable_sampling_; | 117 enable_sampling_ = rhs.enable_sampling_; |
100 enable_systrace_ = rhs.enable_systrace_; | 118 enable_systrace_ = rhs.enable_systrace_; |
101 enable_argument_filter_ = rhs.enable_argument_filter_; | 119 enable_argument_filter_ = rhs.enable_argument_filter_; |
| 120 memory_dump_config_ = rhs.memory_dump_config_; |
102 included_categories_ = rhs.included_categories_; | 121 included_categories_ = rhs.included_categories_; |
103 disabled_categories_ = rhs.disabled_categories_; | 122 disabled_categories_ = rhs.disabled_categories_; |
104 excluded_categories_ = rhs.excluded_categories_; | 123 excluded_categories_ = rhs.excluded_categories_; |
105 synthetic_delays_ = rhs.synthetic_delays_; | 124 synthetic_delays_ = rhs.synthetic_delays_; |
106 return *this; | 125 return *this; |
107 } | 126 } |
108 | 127 |
109 const TraceConfig::StringList& TraceConfig::GetSyntheticDelayValues() const { | 128 const TraceConfig::StringList& TraceConfig::GetSyntheticDelayValues() const { |
110 return synthetic_delays_; | 129 return synthetic_delays_; |
111 } | 130 } |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
200 // Otherwise, one of the filter was specifying "*" and we want to honor the | 219 // Otherwise, one of the filter was specifying "*" and we want to honor the |
201 // broadest filter. | 220 // broadest filter. |
202 if (HasIncludedPatterns() && config.HasIncludedPatterns()) { | 221 if (HasIncludedPatterns() && config.HasIncludedPatterns()) { |
203 included_categories_.insert(included_categories_.end(), | 222 included_categories_.insert(included_categories_.end(), |
204 config.included_categories_.begin(), | 223 config.included_categories_.begin(), |
205 config.included_categories_.end()); | 224 config.included_categories_.end()); |
206 } else { | 225 } else { |
207 included_categories_.clear(); | 226 included_categories_.clear(); |
208 } | 227 } |
209 | 228 |
| 229 memory_dump_config_.insert(memory_dump_config_.end(), |
| 230 config.memory_dump_config_.begin(), |
| 231 config.memory_dump_config_.end()); |
| 232 |
210 disabled_categories_.insert(disabled_categories_.end(), | 233 disabled_categories_.insert(disabled_categories_.end(), |
211 config.disabled_categories_.begin(), | 234 config.disabled_categories_.begin(), |
212 config.disabled_categories_.end()); | 235 config.disabled_categories_.end()); |
213 excluded_categories_.insert(excluded_categories_.end(), | 236 excluded_categories_.insert(excluded_categories_.end(), |
214 config.excluded_categories_.begin(), | 237 config.excluded_categories_.begin(), |
215 config.excluded_categories_.end()); | 238 config.excluded_categories_.end()); |
216 synthetic_delays_.insert(synthetic_delays_.end(), | 239 synthetic_delays_.insert(synthetic_delays_.end(), |
217 config.synthetic_delays_.begin(), | 240 config.synthetic_delays_.begin(), |
218 config.synthetic_delays_.end()); | 241 config.synthetic_delays_.end()); |
219 } | 242 } |
220 | 243 |
221 void TraceConfig::Clear() { | 244 void TraceConfig::Clear() { |
222 record_mode_ = RECORD_UNTIL_FULL; | 245 record_mode_ = RECORD_UNTIL_FULL; |
223 enable_sampling_ = false; | 246 enable_sampling_ = false; |
224 enable_systrace_ = false; | 247 enable_systrace_ = false; |
225 enable_argument_filter_ = false; | 248 enable_argument_filter_ = false; |
226 included_categories_.clear(); | 249 included_categories_.clear(); |
227 disabled_categories_.clear(); | 250 disabled_categories_.clear(); |
228 excluded_categories_.clear(); | 251 excluded_categories_.clear(); |
229 synthetic_delays_.clear(); | 252 synthetic_delays_.clear(); |
| 253 memory_dump_config_.clear(); |
230 } | 254 } |
231 | 255 |
232 void TraceConfig::InitializeDefault() { | 256 void TraceConfig::InitializeDefault() { |
233 record_mode_ = RECORD_UNTIL_FULL; | 257 record_mode_ = RECORD_UNTIL_FULL; |
234 enable_sampling_ = false; | 258 enable_sampling_ = false; |
235 enable_systrace_ = false; | 259 enable_systrace_ = false; |
236 enable_argument_filter_ = false; | 260 enable_argument_filter_ = false; |
237 excluded_categories_.push_back("*Debug"); | 261 excluded_categories_.push_back("*Debug"); |
238 excluded_categories_.push_back("*Test"); | 262 excluded_categories_.push_back("*Test"); |
239 } | 263 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 enable_systrace_ = false; | 296 enable_systrace_ = false; |
273 else | 297 else |
274 enable_systrace_ = enable_systrace; | 298 enable_systrace_ = enable_systrace; |
275 | 299 |
276 bool enable_argument_filter; | 300 bool enable_argument_filter; |
277 if (!dict->GetBoolean(kEnableArgumentFilterParam, &enable_argument_filter)) | 301 if (!dict->GetBoolean(kEnableArgumentFilterParam, &enable_argument_filter)) |
278 enable_argument_filter_ = false; | 302 enable_argument_filter_ = false; |
279 else | 303 else |
280 enable_argument_filter_ = enable_argument_filter; | 304 enable_argument_filter_ = enable_argument_filter; |
281 | 305 |
282 | 306 base::ListValue* category_list = nullptr; |
283 base::ListValue* category_list = NULL; | |
284 if (dict->GetList(kIncludedCategoriesParam, &category_list)) | 307 if (dict->GetList(kIncludedCategoriesParam, &category_list)) |
285 SetCategoriesFromIncludedList(*category_list); | 308 SetCategoriesFromIncludedList(*category_list); |
286 if (dict->GetList(kExcludedCategoriesParam, &category_list)) | 309 if (dict->GetList(kExcludedCategoriesParam, &category_list)) |
287 SetCategoriesFromExcludedList(*category_list); | 310 SetCategoriesFromExcludedList(*category_list); |
288 if (dict->GetList(kSyntheticDelaysParam, &category_list)) | 311 if (dict->GetList(kSyntheticDelaysParam, &category_list)) |
289 SetSyntheticDelaysFromList(*category_list); | 312 SetSyntheticDelaysFromList(*category_list); |
| 313 |
| 314 if (IsCategoryEnabled(MemoryDumpManager::kTraceCategory)) { |
| 315 // If dump triggers not set, the client is using the legacy with just |
| 316 // category enabled. So, use the default periodic dump config. |
| 317 base::DictionaryValue* memory_dump_config = nullptr; |
| 318 if (dict->GetDictionary(kMemoryDumpConfigParam, &memory_dump_config)) |
| 319 SetMemoryDumpConfig(*memory_dump_config); |
| 320 else |
| 321 SetDefaultMemoryDumpConfig(); |
| 322 } |
290 } | 323 } |
291 | 324 |
292 void TraceConfig::InitializeFromStrings( | 325 void TraceConfig::InitializeFromStrings( |
293 const std::string& category_filter_string, | 326 const std::string& category_filter_string, |
294 const std::string& trace_options_string) { | 327 const std::string& trace_options_string) { |
295 if (!category_filter_string.empty()) { | 328 if (!category_filter_string.empty()) { |
296 std::vector<std::string> split = | 329 std::vector<std::string> split = |
297 base::SplitString(category_filter_string, ",", base::TRIM_WHITESPACE, | 330 base::SplitString(category_filter_string, ",", base::TRIM_WHITESPACE, |
298 base::SPLIT_WANT_ALL); | 331 base::SPLIT_WANT_ALL); |
299 std::vector<std::string>::iterator iter; | 332 std::vector<std::string>::iterator iter; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
346 record_mode_ = RECORD_AS_MUCH_AS_POSSIBLE; | 379 record_mode_ = RECORD_AS_MUCH_AS_POSSIBLE; |
347 } else if (*iter == kEnableSampling) { | 380 } else if (*iter == kEnableSampling) { |
348 enable_sampling_ = true; | 381 enable_sampling_ = true; |
349 } else if (*iter == kEnableSystrace) { | 382 } else if (*iter == kEnableSystrace) { |
350 enable_systrace_ = true; | 383 enable_systrace_ = true; |
351 } else if (*iter == kEnableArgumentFilter) { | 384 } else if (*iter == kEnableArgumentFilter) { |
352 enable_argument_filter_ = true; | 385 enable_argument_filter_ = true; |
353 } | 386 } |
354 } | 387 } |
355 } | 388 } |
| 389 |
| 390 if (IsCategoryEnabled(MemoryDumpManager::kTraceCategory)) { |
| 391 SetDefaultMemoryDumpConfig(); |
| 392 } |
356 } | 393 } |
357 | 394 |
358 void TraceConfig::SetCategoriesFromIncludedList( | 395 void TraceConfig::SetCategoriesFromIncludedList( |
359 const base::ListValue& included_list) { | 396 const base::ListValue& included_list) { |
360 included_categories_.clear(); | 397 included_categories_.clear(); |
361 for (size_t i = 0; i < included_list.GetSize(); ++i) { | 398 for (size_t i = 0; i < included_list.GetSize(); ++i) { |
362 std::string category; | 399 std::string category; |
363 if (!included_list.GetString(i, &category)) | 400 if (!included_list.GetString(i, &category)) |
364 continue; | 401 continue; |
365 if (category.compare(0, strlen(TRACE_DISABLED_BY_DEFAULT("")), | 402 if (category.compare(0, strlen(TRACE_DISABLED_BY_DEFAULT("")), |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
405 scoped_ptr<base::ListValue> list(new base::ListValue()); | 442 scoped_ptr<base::ListValue> list(new base::ListValue()); |
406 for (StringList::const_iterator ci = categories.begin(); | 443 for (StringList::const_iterator ci = categories.begin(); |
407 ci != categories.end(); | 444 ci != categories.end(); |
408 ++ci) { | 445 ++ci) { |
409 list->AppendString(*ci); | 446 list->AppendString(*ci); |
410 } | 447 } |
411 | 448 |
412 dict.Set(param, list.Pass()); | 449 dict.Set(param, list.Pass()); |
413 } | 450 } |
414 | 451 |
| 452 void TraceConfig::SetMemoryDumpConfig( |
| 453 const base::DictionaryValue& memory_dump_config) { |
| 454 memory_dump_config_.clear(); |
| 455 |
| 456 const base::ListValue* trigger_list = nullptr; |
| 457 if (!memory_dump_config.GetList(kTriggersParam, &trigger_list) || |
| 458 trigger_list->GetSize() == 0) { |
| 459 return; |
| 460 } |
| 461 |
| 462 for (size_t i = 0; i < trigger_list->GetSize(); ++i) { |
| 463 const base::DictionaryValue* trigger = nullptr; |
| 464 if (!trigger_list->GetDictionary(i, &trigger)) |
| 465 continue; |
| 466 |
| 467 MemoryDumpTriggerConfig dump_config; |
| 468 std::string dump_type; |
| 469 int interval = 0; |
| 470 |
| 471 if (!trigger->GetInteger(kPeriodicIntervalParam, &interval)) { |
| 472 continue; |
| 473 } |
| 474 DCHECK_GT(interval, 0); |
| 475 dump_config.periodic_interval_ms = static_cast<uint32>(interval); |
| 476 dump_config.level_of_detail = MemoryDumpArgs::LevelOfDetail::LOW; |
| 477 |
| 478 if (trigger->GetString(kModeParam, &dump_type)) { |
| 479 if (dump_type == kDetailedParam) { |
| 480 dump_config.level_of_detail = MemoryDumpArgs::LevelOfDetail::HIGH; |
| 481 } |
| 482 } |
| 483 |
| 484 memory_dump_config_.push_back(dump_config); |
| 485 } |
| 486 } |
| 487 |
| 488 void TraceConfig::SetDefaultMemoryDumpConfig() { |
| 489 memory_dump_config_.clear(); |
| 490 memory_dump_config_.push_back(kDefaultHeavyMemoryDumpTrigger); |
| 491 memory_dump_config_.push_back(kDefaultLightMemoryDumpTrigger); |
| 492 } |
| 493 |
415 void TraceConfig::ToDict(base::DictionaryValue& dict) const { | 494 void TraceConfig::ToDict(base::DictionaryValue& dict) const { |
416 switch (record_mode_) { | 495 switch (record_mode_) { |
417 case RECORD_UNTIL_FULL: | 496 case RECORD_UNTIL_FULL: |
418 dict.SetString(kRecordModeParam, kRecordUntilFull); | 497 dict.SetString(kRecordModeParam, kRecordUntilFull); |
419 break; | 498 break; |
420 case RECORD_CONTINUOUSLY: | 499 case RECORD_CONTINUOUSLY: |
421 dict.SetString(kRecordModeParam, kRecordContinuously); | 500 dict.SetString(kRecordModeParam, kRecordContinuously); |
422 break; | 501 break; |
423 case RECORD_AS_MUCH_AS_POSSIBLE: | 502 case RECORD_AS_MUCH_AS_POSSIBLE: |
424 dict.SetString(kRecordModeParam, kRecordAsMuchAsPossible); | 503 dict.SetString(kRecordModeParam, kRecordAsMuchAsPossible); |
(...skipping 20 matching lines...) Expand all Loading... |
445 else | 524 else |
446 dict.SetBoolean(kEnableArgumentFilterParam, false); | 525 dict.SetBoolean(kEnableArgumentFilterParam, false); |
447 | 526 |
448 StringList categories(included_categories_); | 527 StringList categories(included_categories_); |
449 categories.insert(categories.end(), | 528 categories.insert(categories.end(), |
450 disabled_categories_.begin(), | 529 disabled_categories_.begin(), |
451 disabled_categories_.end()); | 530 disabled_categories_.end()); |
452 AddCategoryToDict(dict, kIncludedCategoriesParam, categories); | 531 AddCategoryToDict(dict, kIncludedCategoriesParam, categories); |
453 AddCategoryToDict(dict, kExcludedCategoriesParam, excluded_categories_); | 532 AddCategoryToDict(dict, kExcludedCategoriesParam, excluded_categories_); |
454 AddCategoryToDict(dict, kSyntheticDelaysParam, synthetic_delays_); | 533 AddCategoryToDict(dict, kSyntheticDelaysParam, synthetic_delays_); |
| 534 |
| 535 if (IsCategoryEnabled(MemoryDumpManager::kTraceCategory)) { |
| 536 scoped_ptr<base::DictionaryValue> memory_dump_config( |
| 537 new base::DictionaryValue()); |
| 538 scoped_ptr<base::ListValue> triggers_list(new base::ListValue()); |
| 539 for (const MemoryDumpTriggerConfig& config : memory_dump_config_) { |
| 540 scoped_ptr<base::DictionaryValue> trigger_dict( |
| 541 new base::DictionaryValue()); |
| 542 trigger_dict->SetInteger(kPeriodicIntervalParam, |
| 543 static_cast<int>(config.periodic_interval_ms)); |
| 544 |
| 545 switch (config.level_of_detail) { |
| 546 case MemoryDumpArgs::LevelOfDetail::LOW: |
| 547 trigger_dict->SetString(kModeParam, kLightParam); |
| 548 break; |
| 549 case MemoryDumpArgs::LevelOfDetail::HIGH: |
| 550 trigger_dict->SetString(kModeParam, kDetailedParam); |
| 551 break; |
| 552 default: |
| 553 NOTREACHED(); |
| 554 } |
| 555 triggers_list->Append(trigger_dict.Pass()); |
| 556 } |
| 557 |
| 558 // Empty triggers will still be specified explicitly since it means that |
| 559 // the periodic dumps are not enabled. |
| 560 memory_dump_config->Set(kTriggersParam, triggers_list.Pass()); |
| 561 dict.Set(kMemoryDumpConfigParam, memory_dump_config.Pass()); |
| 562 } |
455 } | 563 } |
456 | 564 |
457 std::string TraceConfig::ToTraceOptionsString() const { | 565 std::string TraceConfig::ToTraceOptionsString() const { |
458 std::string ret; | 566 std::string ret; |
459 switch (record_mode_) { | 567 switch (record_mode_) { |
460 case RECORD_UNTIL_FULL: | 568 case RECORD_UNTIL_FULL: |
461 ret = kRecordUntilFull; | 569 ret = kRecordUntilFull; |
462 break; | 570 break; |
463 case RECORD_CONTINUOUSLY: | 571 case RECORD_CONTINUOUSLY: |
464 ret = kRecordContinuously; | 572 ret = kRecordContinuously; |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
540 str.at(0) == ' ' || | 648 str.at(0) == ' ' || |
541 str.at(str.length() - 1) == ' '; | 649 str.at(str.length() - 1) == ' '; |
542 } | 650 } |
543 | 651 |
544 bool TraceConfig::HasIncludedPatterns() const { | 652 bool TraceConfig::HasIncludedPatterns() const { |
545 return !included_categories_.empty(); | 653 return !included_categories_.empty(); |
546 } | 654 } |
547 | 655 |
548 } // namespace trace_event | 656 } // namespace trace_event |
549 } // namespace base | 657 } // namespace base |
OLD | NEW |