| 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 <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| 11 #include "base/json/json_reader.h" | 11 #include "base/json/json_reader.h" |
| 12 #include "base/json/json_writer.h" | 12 #include "base/json/json_writer.h" |
| 13 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 14 #include "base/strings/pattern.h" | |
| 15 #include "base/strings/string_split.h" | 14 #include "base/strings/string_split.h" |
| 16 #include "base/strings/string_tokenizer.h" | |
| 17 #include "base/strings/string_util.h" | |
| 18 #include "base/strings/stringprintf.h" | |
| 19 #include "base/trace_event/memory_dump_manager.h" | 15 #include "base/trace_event/memory_dump_manager.h" |
| 20 #include "base/trace_event/memory_dump_request_args.h" | 16 #include "base/trace_event/memory_dump_request_args.h" |
| 21 #include "base/trace_event/trace_event.h" | 17 #include "base/trace_event/trace_event.h" |
| 22 | 18 |
| 23 namespace base { | 19 namespace base { |
| 24 namespace trace_event { | 20 namespace trace_event { |
| 25 | 21 |
| 26 namespace { | 22 namespace { |
| 27 | 23 |
| 28 // String options that can be used to initialize TraceOptions. | 24 // String options that can be used to initialize TraceOptions. |
| 29 const char kRecordUntilFull[] = "record-until-full"; | 25 const char kRecordUntilFull[] = "record-until-full"; |
| 30 const char kRecordContinuously[] = "record-continuously"; | 26 const char kRecordContinuously[] = "record-continuously"; |
| 31 const char kRecordAsMuchAsPossible[] = "record-as-much-as-possible"; | 27 const char kRecordAsMuchAsPossible[] = "record-as-much-as-possible"; |
| 32 const char kTraceToConsole[] = "trace-to-console"; | 28 const char kTraceToConsole[] = "trace-to-console"; |
| 33 const char kEnableSystrace[] = "enable-systrace"; | 29 const char kEnableSystrace[] = "enable-systrace"; |
| 34 const char kEnableArgumentFilter[] = "enable-argument-filter"; | 30 const char kEnableArgumentFilter[] = "enable-argument-filter"; |
| 35 | 31 |
| 36 // String parameters that can be used to parse the trace config string. | 32 // String parameters that can be used to parse the trace config string. |
| 37 const char kRecordModeParam[] = "record_mode"; | 33 const char kRecordModeParam[] = "record_mode"; |
| 38 const char kEnableSystraceParam[] = "enable_systrace"; | 34 const char kEnableSystraceParam[] = "enable_systrace"; |
| 39 const char kEnableArgumentFilterParam[] = "enable_argument_filter"; | 35 const char kEnableArgumentFilterParam[] = "enable_argument_filter"; |
| 40 const char kIncludedCategoriesParam[] = "included_categories"; | |
| 41 const char kExcludedCategoriesParam[] = "excluded_categories"; | |
| 42 const char kSyntheticDelaysParam[] = "synthetic_delays"; | |
| 43 | |
| 44 const char kSyntheticDelayCategoryFilterPrefix[] = "DELAY("; | |
| 45 | 36 |
| 46 // String parameters that is used to parse memory dump config in trace config | 37 // String parameters that is used to parse memory dump config in trace config |
| 47 // string. | 38 // string. |
| 48 const char kMemoryDumpConfigParam[] = "memory_dump_config"; | 39 const char kMemoryDumpConfigParam[] = "memory_dump_config"; |
| 49 const char kAllowedDumpModesParam[] = "allowed_dump_modes"; | 40 const char kAllowedDumpModesParam[] = "allowed_dump_modes"; |
| 50 const char kTriggersParam[] = "triggers"; | 41 const char kTriggersParam[] = "triggers"; |
| 51 const char kTriggerModeParam[] = "mode"; | 42 const char kTriggerModeParam[] = "mode"; |
| 52 const char kMinTimeBetweenDumps[] = "min_time_between_dumps_ms"; | 43 const char kMinTimeBetweenDumps[] = "min_time_between_dumps_ms"; |
| 53 const char kTriggerTypeParam[] = "type"; | 44 const char kTriggerTypeParam[] = "type"; |
| 54 const char kPeriodicIntervalLegacyParam[] = "periodic_interval_ms"; | 45 const char kPeriodicIntervalLegacyParam[] = "periodic_interval_ms"; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 141 TraceConfig::EventFilterConfig::EventFilterConfig(const EventFilterConfig& tc) { | 132 TraceConfig::EventFilterConfig::EventFilterConfig(const EventFilterConfig& tc) { |
| 142 *this = tc; | 133 *this = tc; |
| 143 } | 134 } |
| 144 | 135 |
| 145 TraceConfig::EventFilterConfig& TraceConfig::EventFilterConfig::operator=( | 136 TraceConfig::EventFilterConfig& TraceConfig::EventFilterConfig::operator=( |
| 146 const TraceConfig::EventFilterConfig& rhs) { | 137 const TraceConfig::EventFilterConfig& rhs) { |
| 147 if (this == &rhs) | 138 if (this == &rhs) |
| 148 return *this; | 139 return *this; |
| 149 | 140 |
| 150 predicate_name_ = rhs.predicate_name_; | 141 predicate_name_ = rhs.predicate_name_; |
| 151 included_categories_ = rhs.included_categories_; | 142 category_filter_ = rhs.category_filter_; |
| 152 excluded_categories_ = rhs.excluded_categories_; | 143 |
| 153 if (rhs.args_) | 144 if (rhs.args_) |
| 154 args_ = rhs.args_->CreateDeepCopy(); | 145 args_ = rhs.args_->CreateDeepCopy(); |
| 155 | 146 |
| 156 return *this; | 147 return *this; |
| 157 } | 148 } |
| 158 | 149 |
| 159 void TraceConfig::EventFilterConfig::AddIncludedCategory( | 150 void TraceConfig::EventFilterConfig::InitializeFromConfigDict( |
| 160 const std::string& category) { | 151 const base::DictionaryValue* event_filter) { |
| 161 included_categories_.push_back(category); | 152 category_filter_.InitializeFromConfigDict(*event_filter); |
| 153 |
| 154 const base::DictionaryValue* args_dict = nullptr; |
| 155 if (event_filter->GetDictionary(kFilterArgsParam, &args_dict)) |
| 156 args_ = args_dict->CreateDeepCopy(); |
| 162 } | 157 } |
| 163 | 158 |
| 164 void TraceConfig::EventFilterConfig::AddExcludedCategory( | 159 void TraceConfig::EventFilterConfig::SetCategoryFilter( |
| 165 const std::string& category) { | 160 const TraceConfigCategoryFilter& category_filter) { |
| 166 excluded_categories_.push_back(category); | 161 category_filter_ = category_filter; |
| 167 } | 162 } |
| 168 | 163 |
| 169 void TraceConfig::EventFilterConfig::SetArgs( | 164 void TraceConfig::EventFilterConfig::ToDict( |
| 170 std::unique_ptr<base::DictionaryValue> args) { | 165 DictionaryValue* filter_dict) const { |
| 171 args_ = std::move(args); | 166 filter_dict->SetString(kFilterPredicateParam, predicate_name()); |
| 167 |
| 168 category_filter_.ToDict(filter_dict); |
| 169 |
| 170 if (args_) |
| 171 filter_dict->Set(kFilterArgsParam, args_->CreateDeepCopy()); |
| 172 } | 172 } |
| 173 | 173 |
| 174 bool TraceConfig::EventFilterConfig::GetArgAsSet( | 174 bool TraceConfig::EventFilterConfig::GetArgAsSet( |
| 175 const char* key, | 175 const char* key, |
| 176 std::unordered_set<std::string>* out_set) const { | 176 std::unordered_set<std::string>* out_set) const { |
| 177 const ListValue* list = nullptr; | 177 const ListValue* list = nullptr; |
| 178 if (!args_->GetList(key, &list)) | 178 if (!args_->GetList(key, &list)) |
| 179 return false; | 179 return false; |
| 180 for (size_t i = 0; i < list->GetSize(); ++i) { | 180 for (size_t i = 0; i < list->GetSize(); ++i) { |
| 181 std::string value; | 181 std::string value; |
| 182 if (list->GetString(i, &value)) | 182 if (list->GetString(i, &value)) |
| 183 out_set->insert(value); | 183 out_set->insert(value); |
| 184 } | 184 } |
| 185 return true; | 185 return true; |
| 186 } | 186 } |
| 187 | 187 |
| 188 bool TraceConfig::EventFilterConfig::IsCategoryGroupEnabled( | 188 bool TraceConfig::EventFilterConfig::IsCategoryGroupEnabled( |
| 189 const char* category_group_name) const { | 189 const char* category_group_name) const { |
| 190 CStringTokenizer category_group_tokens( | 190 return category_filter_.IsCategoryGroupEnabled(category_group_name); |
| 191 category_group_name, category_group_name + strlen(category_group_name), | |
| 192 ","); | |
| 193 while (category_group_tokens.GetNext()) { | |
| 194 std::string category_group_token = category_group_tokens.token(); | |
| 195 | |
| 196 for (const auto& excluded_category : excluded_categories_) { | |
| 197 if (base::MatchPattern(category_group_token, excluded_category)) { | |
| 198 return false; | |
| 199 } | |
| 200 } | |
| 201 | |
| 202 for (const auto& included_category : included_categories_) { | |
| 203 if (base::MatchPattern(category_group_token, included_category)) { | |
| 204 return true; | |
| 205 } | |
| 206 } | |
| 207 } | |
| 208 | |
| 209 return false; | |
| 210 } | 191 } |
| 211 | 192 |
| 212 TraceConfig::TraceConfig() { | 193 TraceConfig::TraceConfig() { |
| 213 InitializeDefault(); | 194 InitializeDefault(); |
| 214 } | 195 } |
| 215 | 196 |
| 216 TraceConfig::TraceConfig(StringPiece category_filter_string, | 197 TraceConfig::TraceConfig(StringPiece category_filter_string, |
| 217 StringPiece trace_options_string) { | 198 StringPiece trace_options_string) { |
| 218 InitializeFromStrings(category_filter_string, trace_options_string); | 199 InitializeFromStrings(category_filter_string, trace_options_string); |
| 219 } | 200 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 248 if (!config_string.empty()) | 229 if (!config_string.empty()) |
| 249 InitializeFromConfigString(config_string); | 230 InitializeFromConfigString(config_string); |
| 250 else | 231 else |
| 251 InitializeDefault(); | 232 InitializeDefault(); |
| 252 } | 233 } |
| 253 | 234 |
| 254 TraceConfig::TraceConfig(const TraceConfig& tc) | 235 TraceConfig::TraceConfig(const TraceConfig& tc) |
| 255 : record_mode_(tc.record_mode_), | 236 : record_mode_(tc.record_mode_), |
| 256 enable_systrace_(tc.enable_systrace_), | 237 enable_systrace_(tc.enable_systrace_), |
| 257 enable_argument_filter_(tc.enable_argument_filter_), | 238 enable_argument_filter_(tc.enable_argument_filter_), |
| 239 category_filter_(tc.category_filter_), |
| 258 memory_dump_config_(tc.memory_dump_config_), | 240 memory_dump_config_(tc.memory_dump_config_), |
| 259 included_categories_(tc.included_categories_), | |
| 260 disabled_categories_(tc.disabled_categories_), | |
| 261 excluded_categories_(tc.excluded_categories_), | |
| 262 synthetic_delays_(tc.synthetic_delays_), | |
| 263 event_filters_(tc.event_filters_) {} | 241 event_filters_(tc.event_filters_) {} |
| 264 | 242 |
| 265 TraceConfig::~TraceConfig() { | 243 TraceConfig::~TraceConfig() { |
| 266 } | 244 } |
| 267 | 245 |
| 268 TraceConfig& TraceConfig::operator=(const TraceConfig& rhs) { | 246 TraceConfig& TraceConfig::operator=(const TraceConfig& rhs) { |
| 269 if (this == &rhs) | 247 if (this == &rhs) |
| 270 return *this; | 248 return *this; |
| 271 | 249 |
| 272 record_mode_ = rhs.record_mode_; | 250 record_mode_ = rhs.record_mode_; |
| 273 enable_systrace_ = rhs.enable_systrace_; | 251 enable_systrace_ = rhs.enable_systrace_; |
| 274 enable_argument_filter_ = rhs.enable_argument_filter_; | 252 enable_argument_filter_ = rhs.enable_argument_filter_; |
| 253 category_filter_ = rhs.category_filter_; |
| 275 memory_dump_config_ = rhs.memory_dump_config_; | 254 memory_dump_config_ = rhs.memory_dump_config_; |
| 276 included_categories_ = rhs.included_categories_; | |
| 277 disabled_categories_ = rhs.disabled_categories_; | |
| 278 excluded_categories_ = rhs.excluded_categories_; | |
| 279 synthetic_delays_ = rhs.synthetic_delays_; | |
| 280 event_filters_ = rhs.event_filters_; | 255 event_filters_ = rhs.event_filters_; |
| 281 return *this; | 256 return *this; |
| 282 } | 257 } |
| 283 | 258 |
| 284 const TraceConfig::StringList& TraceConfig::GetSyntheticDelayValues() const { | 259 const TraceConfig::StringList& TraceConfig::GetSyntheticDelayValues() const { |
| 285 return synthetic_delays_; | 260 return category_filter_.synthetic_delays(); |
| 286 } | 261 } |
| 287 | 262 |
| 288 std::string TraceConfig::ToString() const { | 263 std::string TraceConfig::ToString() const { |
| 289 std::unique_ptr<DictionaryValue> dict = ToDict(); | 264 std::unique_ptr<DictionaryValue> dict = ToDict(); |
| 290 std::string json; | 265 std::string json; |
| 291 JSONWriter::Write(*dict, &json); | 266 JSONWriter::Write(*dict, &json); |
| 292 return json; | 267 return json; |
| 293 } | 268 } |
| 294 | 269 |
| 295 std::unique_ptr<ConvertableToTraceFormat> | 270 std::unique_ptr<ConvertableToTraceFormat> |
| 296 TraceConfig::AsConvertableToTraceFormat() const { | 271 TraceConfig::AsConvertableToTraceFormat() const { |
| 297 return MakeUnique<ConvertableTraceConfigToTraceFormat>(*this); | 272 return MakeUnique<ConvertableTraceConfigToTraceFormat>(*this); |
| 298 } | 273 } |
| 299 | 274 |
| 300 std::string TraceConfig::ToCategoryFilterString() const { | 275 std::string TraceConfig::ToCategoryFilterString() const { |
| 301 std::string filter_string; | 276 return category_filter_.ToFilterString(); |
| 302 WriteCategoryFilterString(included_categories_, &filter_string, true); | |
| 303 WriteCategoryFilterString(disabled_categories_, &filter_string, true); | |
| 304 WriteCategoryFilterString(excluded_categories_, &filter_string, false); | |
| 305 WriteCategoryFilterString(synthetic_delays_, &filter_string); | |
| 306 return filter_string; | |
| 307 } | 277 } |
| 308 | 278 |
| 309 bool TraceConfig::IsCategoryGroupEnabled( | 279 bool TraceConfig::IsCategoryGroupEnabled( |
| 310 const char* category_group_name) const { | 280 const char* category_group_name) const { |
| 311 // TraceLog should call this method only as part of enabling/disabling | 281 // TraceLog should call this method only as part of enabling/disabling |
| 312 // categories. | 282 // categories. |
| 313 | 283 return category_filter_.IsCategoryGroupEnabled(category_group_name); |
| 314 bool had_enabled_by_default = false; | |
| 315 DCHECK(category_group_name); | |
| 316 std::string category_group_name_str = category_group_name; | |
| 317 StringTokenizer category_group_tokens(category_group_name_str, ","); | |
| 318 while (category_group_tokens.GetNext()) { | |
| 319 std::string category_group_token = category_group_tokens.token(); | |
| 320 // Don't allow empty tokens, nor tokens with leading or trailing space. | |
| 321 DCHECK(!TraceConfig::IsEmptyOrContainsLeadingOrTrailingWhitespace( | |
| 322 category_group_token)) | |
| 323 << "Disallowed category string"; | |
| 324 if (IsCategoryEnabled(category_group_token.c_str())) | |
| 325 return true; | |
| 326 | |
| 327 if (!MatchPattern(category_group_token, TRACE_DISABLED_BY_DEFAULT("*"))) | |
| 328 had_enabled_by_default = true; | |
| 329 } | |
| 330 // Do a second pass to check for explicitly disabled categories | |
| 331 // (those explicitly enabled have priority due to first pass). | |
| 332 category_group_tokens.Reset(); | |
| 333 bool category_group_disabled = false; | |
| 334 while (category_group_tokens.GetNext()) { | |
| 335 std::string category_group_token = category_group_tokens.token(); | |
| 336 for (const std::string& category : excluded_categories_) { | |
| 337 if (MatchPattern(category_group_token, category)) { | |
| 338 // Current token of category_group_name is present in excluded_list. | |
| 339 // Flag the exclusion and proceed further to check if any of the | |
| 340 // remaining categories of category_group_name is not present in the | |
| 341 // excluded_ list. | |
| 342 category_group_disabled = true; | |
| 343 break; | |
| 344 } | |
| 345 // One of the category of category_group_name is not present in | |
| 346 // excluded_ list. So, if it's not a disabled-by-default category, | |
| 347 // it has to be included_ list. Enable the category_group_name | |
| 348 // for recording. | |
| 349 if (!MatchPattern(category_group_token, TRACE_DISABLED_BY_DEFAULT("*"))) { | |
| 350 category_group_disabled = false; | |
| 351 } | |
| 352 } | |
| 353 // One of the categories present in category_group_name is not present in | |
| 354 // excluded_ list. Implies this category_group_name group can be enabled | |
| 355 // for recording, since one of its groups is enabled for recording. | |
| 356 if (!category_group_disabled) | |
| 357 break; | |
| 358 } | |
| 359 // If the category group is not excluded, and there are no included patterns | |
| 360 // we consider this category group enabled, as long as it had categories | |
| 361 // other than disabled-by-default. | |
| 362 return !category_group_disabled && had_enabled_by_default && | |
| 363 included_categories_.empty(); | |
| 364 } | 284 } |
| 365 | 285 |
| 366 void TraceConfig::Merge(const TraceConfig& config) { | 286 void TraceConfig::Merge(const TraceConfig& config) { |
| 367 if (record_mode_ != config.record_mode_ | 287 if (record_mode_ != config.record_mode_ |
| 368 || enable_systrace_ != config.enable_systrace_ | 288 || enable_systrace_ != config.enable_systrace_ |
| 369 || enable_argument_filter_ != config.enable_argument_filter_) { | 289 || enable_argument_filter_ != config.enable_argument_filter_) { |
| 370 DLOG(ERROR) << "Attempting to merge trace config with a different " | 290 DLOG(ERROR) << "Attempting to merge trace config with a different " |
| 371 << "set of options."; | 291 << "set of options."; |
| 372 } | 292 } |
| 373 | 293 |
| 374 // Keep included patterns only if both filters have an included entry. | 294 category_filter_.Merge(config.category_filter_); |
| 375 // Otherwise, one of the filter was specifying "*" and we want to honor the | |
| 376 // broadest filter. | |
| 377 if (HasIncludedPatterns() && config.HasIncludedPatterns()) { | |
| 378 included_categories_.insert(included_categories_.end(), | |
| 379 config.included_categories_.begin(), | |
| 380 config.included_categories_.end()); | |
| 381 } else { | |
| 382 included_categories_.clear(); | |
| 383 } | |
| 384 | 295 |
| 385 memory_dump_config_.Merge(config.memory_dump_config_); | 296 memory_dump_config_.Merge(config.memory_dump_config_); |
| 386 | 297 |
| 387 disabled_categories_.insert(disabled_categories_.end(), | |
| 388 config.disabled_categories_.begin(), | |
| 389 config.disabled_categories_.end()); | |
| 390 excluded_categories_.insert(excluded_categories_.end(), | |
| 391 config.excluded_categories_.begin(), | |
| 392 config.excluded_categories_.end()); | |
| 393 synthetic_delays_.insert(synthetic_delays_.end(), | |
| 394 config.synthetic_delays_.begin(), | |
| 395 config.synthetic_delays_.end()); | |
| 396 event_filters_.insert(event_filters_.end(), config.event_filters().begin(), | 298 event_filters_.insert(event_filters_.end(), config.event_filters().begin(), |
| 397 config.event_filters().end()); | 299 config.event_filters().end()); |
| 398 } | 300 } |
| 399 | 301 |
| 400 void TraceConfig::Clear() { | 302 void TraceConfig::Clear() { |
| 401 record_mode_ = RECORD_UNTIL_FULL; | 303 record_mode_ = RECORD_UNTIL_FULL; |
| 402 enable_systrace_ = false; | 304 enable_systrace_ = false; |
| 403 enable_argument_filter_ = false; | 305 enable_argument_filter_ = false; |
| 404 included_categories_.clear(); | 306 category_filter_.Clear(); |
| 405 disabled_categories_.clear(); | |
| 406 excluded_categories_.clear(); | |
| 407 synthetic_delays_.clear(); | |
| 408 memory_dump_config_.Clear(); | 307 memory_dump_config_.Clear(); |
| 409 event_filters_.clear(); | 308 event_filters_.clear(); |
| 410 } | 309 } |
| 411 | 310 |
| 412 void TraceConfig::InitializeDefault() { | 311 void TraceConfig::InitializeDefault() { |
| 413 record_mode_ = RECORD_UNTIL_FULL; | 312 record_mode_ = RECORD_UNTIL_FULL; |
| 414 enable_systrace_ = false; | 313 enable_systrace_ = false; |
| 415 enable_argument_filter_ = false; | 314 enable_argument_filter_ = false; |
| 416 } | 315 } |
| 417 | 316 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 428 } else if (record_mode == kRecordAsMuchAsPossible) { | 327 } else if (record_mode == kRecordAsMuchAsPossible) { |
| 429 record_mode_ = RECORD_AS_MUCH_AS_POSSIBLE; | 328 record_mode_ = RECORD_AS_MUCH_AS_POSSIBLE; |
| 430 } | 329 } |
| 431 } | 330 } |
| 432 | 331 |
| 433 bool val; | 332 bool val; |
| 434 enable_systrace_ = dict.GetBoolean(kEnableSystraceParam, &val) ? val : false; | 333 enable_systrace_ = dict.GetBoolean(kEnableSystraceParam, &val) ? val : false; |
| 435 enable_argument_filter_ = | 334 enable_argument_filter_ = |
| 436 dict.GetBoolean(kEnableArgumentFilterParam, &val) ? val : false; | 335 dict.GetBoolean(kEnableArgumentFilterParam, &val) ? val : false; |
| 437 | 336 |
| 438 const ListValue* category_list = nullptr; | 337 category_filter_.InitializeFromConfigDict(dict); |
| 439 if (dict.GetList(kIncludedCategoriesParam, &category_list)) | |
| 440 SetCategoriesFromIncludedList(*category_list); | |
| 441 if (dict.GetList(kExcludedCategoriesParam, &category_list)) | |
| 442 SetCategoriesFromExcludedList(*category_list); | |
| 443 if (dict.GetList(kSyntheticDelaysParam, &category_list)) | |
| 444 SetSyntheticDelaysFromList(*category_list); | |
| 445 | 338 |
| 446 const base::ListValue* category_event_filters = nullptr; | 339 const base::ListValue* category_event_filters = nullptr; |
| 447 if (dict.GetList(kEventFiltersParam, &category_event_filters)) | 340 if (dict.GetList(kEventFiltersParam, &category_event_filters)) |
| 448 SetEventFiltersFromConfigList(*category_event_filters); | 341 SetEventFiltersFromConfigList(*category_event_filters); |
| 449 | 342 |
| 450 if (IsCategoryEnabled(MemoryDumpManager::kTraceCategory)) { | 343 if (category_filter_.IsCategoryEnabled(MemoryDumpManager::kTraceCategory)) { |
| 451 // If dump triggers not set, the client is using the legacy with just | 344 // If dump triggers not set, the client is using the legacy with just |
| 452 // category enabled. So, use the default periodic dump config. | 345 // category enabled. So, use the default periodic dump config. |
| 453 const DictionaryValue* memory_dump_config = nullptr; | 346 const DictionaryValue* memory_dump_config = nullptr; |
| 454 if (dict.GetDictionary(kMemoryDumpConfigParam, &memory_dump_config)) | 347 if (dict.GetDictionary(kMemoryDumpConfigParam, &memory_dump_config)) |
| 455 SetMemoryDumpConfigFromConfigDict(*memory_dump_config); | 348 SetMemoryDumpConfigFromConfigDict(*memory_dump_config); |
| 456 else | 349 else |
| 457 SetDefaultMemoryDumpConfig(); | 350 SetDefaultMemoryDumpConfig(); |
| 458 } | 351 } |
| 459 } | 352 } |
| 460 | 353 |
| 461 void TraceConfig::InitializeFromConfigString(StringPiece config_string) { | 354 void TraceConfig::InitializeFromConfigString(StringPiece config_string) { |
| 462 auto dict = DictionaryValue::From(JSONReader::Read(config_string)); | 355 auto dict = DictionaryValue::From(JSONReader::Read(config_string)); |
| 463 if (dict) | 356 if (dict) |
| 464 InitializeFromConfigDict(*dict); | 357 InitializeFromConfigDict(*dict); |
| 465 else | 358 else |
| 466 InitializeDefault(); | 359 InitializeDefault(); |
| 467 } | 360 } |
| 468 | 361 |
| 469 void TraceConfig::InitializeFromStrings(StringPiece category_filter_string, | 362 void TraceConfig::InitializeFromStrings(StringPiece category_filter_string, |
| 470 StringPiece trace_options_string) { | 363 StringPiece trace_options_string) { |
| 471 if (!category_filter_string.empty()) { | 364 if (!category_filter_string.empty()) |
| 472 std::vector<std::string> split = SplitString( | 365 category_filter_.InitializeFromString(category_filter_string); |
| 473 category_filter_string, ",", TRIM_WHITESPACE, SPLIT_WANT_ALL); | |
| 474 for (const std::string& category : split) { | |
| 475 // Ignore empty categories. | |
| 476 if (category.empty()) | |
| 477 continue; | |
| 478 // Synthetic delays are of the form 'DELAY(delay;option;option;...)'. | |
| 479 if (StartsWith(category, kSyntheticDelayCategoryFilterPrefix, | |
| 480 CompareCase::SENSITIVE) && | |
| 481 category.back() == ')') { | |
| 482 std::string synthetic_category = category.substr( | |
| 483 strlen(kSyntheticDelayCategoryFilterPrefix), | |
| 484 category.size() - strlen(kSyntheticDelayCategoryFilterPrefix) - 1); | |
| 485 size_t name_length = synthetic_category.find(';'); | |
| 486 if (name_length != std::string::npos && name_length > 0 && | |
| 487 name_length != synthetic_category.size() - 1) { | |
| 488 synthetic_delays_.push_back(synthetic_category); | |
| 489 } | |
| 490 } else if (category.front() == '-') { | |
| 491 // Excluded categories start with '-'. | |
| 492 // Remove '-' from category string. | |
| 493 excluded_categories_.push_back(category.substr(1)); | |
| 494 } else if (category.compare(0, strlen(TRACE_DISABLED_BY_DEFAULT("")), | |
| 495 TRACE_DISABLED_BY_DEFAULT("")) == 0) { | |
| 496 disabled_categories_.push_back(category); | |
| 497 } else { | |
| 498 included_categories_.push_back(category); | |
| 499 } | |
| 500 } | |
| 501 } | |
| 502 | 366 |
| 503 record_mode_ = RECORD_UNTIL_FULL; | 367 record_mode_ = RECORD_UNTIL_FULL; |
| 504 enable_systrace_ = false; | 368 enable_systrace_ = false; |
| 505 enable_argument_filter_ = false; | 369 enable_argument_filter_ = false; |
| 506 if (!trace_options_string.empty()) { | 370 if (!trace_options_string.empty()) { |
| 507 std::vector<std::string> split = | 371 std::vector<std::string> split = |
| 508 SplitString(trace_options_string, ",", TRIM_WHITESPACE, SPLIT_WANT_ALL); | 372 SplitString(trace_options_string, ",", TRIM_WHITESPACE, SPLIT_WANT_ALL); |
| 509 for (const std::string& token : split) { | 373 for (const std::string& token : split) { |
| 510 if (token == kRecordUntilFull) { | 374 if (token == kRecordUntilFull) { |
| 511 record_mode_ = RECORD_UNTIL_FULL; | 375 record_mode_ = RECORD_UNTIL_FULL; |
| 512 } else if (token == kRecordContinuously) { | 376 } else if (token == kRecordContinuously) { |
| 513 record_mode_ = RECORD_CONTINUOUSLY; | 377 record_mode_ = RECORD_CONTINUOUSLY; |
| 514 } else if (token == kTraceToConsole) { | 378 } else if (token == kTraceToConsole) { |
| 515 record_mode_ = ECHO_TO_CONSOLE; | 379 record_mode_ = ECHO_TO_CONSOLE; |
| 516 } else if (token == kRecordAsMuchAsPossible) { | 380 } else if (token == kRecordAsMuchAsPossible) { |
| 517 record_mode_ = RECORD_AS_MUCH_AS_POSSIBLE; | 381 record_mode_ = RECORD_AS_MUCH_AS_POSSIBLE; |
| 518 } else if (token == kEnableSystrace) { | 382 } else if (token == kEnableSystrace) { |
| 519 enable_systrace_ = true; | 383 enable_systrace_ = true; |
| 520 } else if (token == kEnableArgumentFilter) { | 384 } else if (token == kEnableArgumentFilter) { |
| 521 enable_argument_filter_ = true; | 385 enable_argument_filter_ = true; |
| 522 } | 386 } |
| 523 } | 387 } |
| 524 } | 388 } |
| 525 | 389 |
| 526 if (IsCategoryEnabled(MemoryDumpManager::kTraceCategory)) { | 390 if (category_filter_.IsCategoryEnabled(MemoryDumpManager::kTraceCategory)) { |
| 527 SetDefaultMemoryDumpConfig(); | 391 SetDefaultMemoryDumpConfig(); |
| 528 } | 392 } |
| 529 } | 393 } |
| 530 | 394 |
| 531 void TraceConfig::SetCategoriesFromIncludedList( | |
| 532 const ListValue& included_list) { | |
| 533 included_categories_.clear(); | |
| 534 for (size_t i = 0; i < included_list.GetSize(); ++i) { | |
| 535 std::string category; | |
| 536 if (!included_list.GetString(i, &category)) | |
| 537 continue; | |
| 538 if (category.compare(0, strlen(TRACE_DISABLED_BY_DEFAULT("")), | |
| 539 TRACE_DISABLED_BY_DEFAULT("")) == 0) { | |
| 540 disabled_categories_.push_back(category); | |
| 541 } else { | |
| 542 included_categories_.push_back(category); | |
| 543 } | |
| 544 } | |
| 545 } | |
| 546 | |
| 547 void TraceConfig::SetCategoriesFromExcludedList( | |
| 548 const ListValue& excluded_list) { | |
| 549 excluded_categories_.clear(); | |
| 550 for (size_t i = 0; i < excluded_list.GetSize(); ++i) { | |
| 551 std::string category; | |
| 552 if (excluded_list.GetString(i, &category)) | |
| 553 excluded_categories_.push_back(category); | |
| 554 } | |
| 555 } | |
| 556 | |
| 557 void TraceConfig::SetSyntheticDelaysFromList(const ListValue& list) { | |
| 558 synthetic_delays_.clear(); | |
| 559 for (size_t i = 0; i < list.GetSize(); ++i) { | |
| 560 std::string delay; | |
| 561 if (!list.GetString(i, &delay)) | |
| 562 continue; | |
| 563 // Synthetic delays are of the form "delay;option;option;...". | |
| 564 size_t name_length = delay.find(';'); | |
| 565 if (name_length != std::string::npos && name_length > 0 && | |
| 566 name_length != delay.size() - 1) { | |
| 567 synthetic_delays_.push_back(delay); | |
| 568 } | |
| 569 } | |
| 570 } | |
| 571 | |
| 572 void TraceConfig::AddCategoryToDict(DictionaryValue* dict, | |
| 573 const char* param, | |
| 574 const StringList& categories) const { | |
| 575 if (categories.empty()) | |
| 576 return; | |
| 577 | |
| 578 auto list = MakeUnique<ListValue>(); | |
| 579 for (const std::string& category : categories) | |
| 580 list->AppendString(category); | |
| 581 dict->Set(param, std::move(list)); | |
| 582 } | |
| 583 | |
| 584 void TraceConfig::SetMemoryDumpConfigFromConfigDict( | 395 void TraceConfig::SetMemoryDumpConfigFromConfigDict( |
| 585 const DictionaryValue& memory_dump_config) { | 396 const DictionaryValue& memory_dump_config) { |
| 586 // Set allowed dump modes. | 397 // Set allowed dump modes. |
| 587 memory_dump_config_.allowed_dump_modes.clear(); | 398 memory_dump_config_.allowed_dump_modes.clear(); |
| 588 const ListValue* allowed_modes_list; | 399 const ListValue* allowed_modes_list; |
| 589 if (memory_dump_config.GetList(kAllowedDumpModesParam, &allowed_modes_list)) { | 400 if (memory_dump_config.GetList(kAllowedDumpModesParam, &allowed_modes_list)) { |
| 590 for (size_t i = 0; i < allowed_modes_list->GetSize(); ++i) { | 401 for (size_t i = 0; i < allowed_modes_list->GetSize(); ++i) { |
| 591 std::string level_of_detail_str; | 402 std::string level_of_detail_str; |
| 592 allowed_modes_list->GetString(i, &level_of_detail_str); | 403 allowed_modes_list->GetString(i, &level_of_detail_str); |
| 593 memory_dump_config_.allowed_dump_modes.insert( | 404 memory_dump_config_.allowed_dump_modes.insert( |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 666 const base::DictionaryValue* event_filter = nullptr; | 477 const base::DictionaryValue* event_filter = nullptr; |
| 667 if (!category_event_filters.GetDictionary(event_filter_index, | 478 if (!category_event_filters.GetDictionary(event_filter_index, |
| 668 &event_filter)) | 479 &event_filter)) |
| 669 continue; | 480 continue; |
| 670 | 481 |
| 671 std::string predicate_name; | 482 std::string predicate_name; |
| 672 CHECK(event_filter->GetString(kFilterPredicateParam, &predicate_name)) | 483 CHECK(event_filter->GetString(kFilterPredicateParam, &predicate_name)) |
| 673 << "Invalid predicate name in category event filter."; | 484 << "Invalid predicate name in category event filter."; |
| 674 | 485 |
| 675 EventFilterConfig new_config(predicate_name); | 486 EventFilterConfig new_config(predicate_name); |
| 676 const base::ListValue* included_list = nullptr; | 487 new_config.InitializeFromConfigDict(event_filter); |
| 677 CHECK(event_filter->GetList(kIncludedCategoriesParam, &included_list)) | |
| 678 << "Missing included_categories in category event filter."; | |
| 679 | |
| 680 for (size_t i = 0; i < included_list->GetSize(); ++i) { | |
| 681 std::string category; | |
| 682 if (included_list->GetString(i, &category)) | |
| 683 new_config.AddIncludedCategory(category); | |
| 684 } | |
| 685 | |
| 686 const base::ListValue* excluded_list = nullptr; | |
| 687 if (event_filter->GetList(kExcludedCategoriesParam, &excluded_list)) { | |
| 688 for (size_t i = 0; i < excluded_list->GetSize(); ++i) { | |
| 689 std::string category; | |
| 690 if (excluded_list->GetString(i, &category)) | |
| 691 new_config.AddExcludedCategory(category); | |
| 692 } | |
| 693 } | |
| 694 | |
| 695 const base::DictionaryValue* args_dict = nullptr; | |
| 696 if (event_filter->GetDictionary(kFilterArgsParam, &args_dict)) | |
| 697 new_config.SetArgs(args_dict->CreateDeepCopy()); | |
| 698 | |
| 699 event_filters_.push_back(new_config); | 488 event_filters_.push_back(new_config); |
| 700 } | 489 } |
| 701 } | 490 } |
| 702 | 491 |
| 703 std::unique_ptr<DictionaryValue> TraceConfig::ToDict() const { | 492 std::unique_ptr<DictionaryValue> TraceConfig::ToDict() const { |
| 704 auto dict = MakeUnique<DictionaryValue>(); | 493 auto dict = MakeUnique<DictionaryValue>(); |
| 705 switch (record_mode_) { | 494 switch (record_mode_) { |
| 706 case RECORD_UNTIL_FULL: | 495 case RECORD_UNTIL_FULL: |
| 707 dict->SetString(kRecordModeParam, kRecordUntilFull); | 496 dict->SetString(kRecordModeParam, kRecordUntilFull); |
| 708 break; | 497 break; |
| 709 case RECORD_CONTINUOUSLY: | 498 case RECORD_CONTINUOUSLY: |
| 710 dict->SetString(kRecordModeParam, kRecordContinuously); | 499 dict->SetString(kRecordModeParam, kRecordContinuously); |
| 711 break; | 500 break; |
| 712 case RECORD_AS_MUCH_AS_POSSIBLE: | 501 case RECORD_AS_MUCH_AS_POSSIBLE: |
| 713 dict->SetString(kRecordModeParam, kRecordAsMuchAsPossible); | 502 dict->SetString(kRecordModeParam, kRecordAsMuchAsPossible); |
| 714 break; | 503 break; |
| 715 case ECHO_TO_CONSOLE: | 504 case ECHO_TO_CONSOLE: |
| 716 dict->SetString(kRecordModeParam, kTraceToConsole); | 505 dict->SetString(kRecordModeParam, kTraceToConsole); |
| 717 break; | 506 break; |
| 718 default: | 507 default: |
| 719 NOTREACHED(); | 508 NOTREACHED(); |
| 720 } | 509 } |
| 721 | 510 |
| 722 dict->SetBoolean(kEnableSystraceParam, enable_systrace_); | 511 dict->SetBoolean(kEnableSystraceParam, enable_systrace_); |
| 723 dict->SetBoolean(kEnableArgumentFilterParam, enable_argument_filter_); | 512 dict->SetBoolean(kEnableArgumentFilterParam, enable_argument_filter_); |
| 724 | 513 |
| 725 StringList categories(included_categories_); | 514 category_filter_.ToDict(dict.get()); |
| 726 categories.insert(categories.end(), | |
| 727 disabled_categories_.begin(), | |
| 728 disabled_categories_.end()); | |
| 729 AddCategoryToDict(dict.get(), kIncludedCategoriesParam, categories); | |
| 730 AddCategoryToDict(dict.get(), kExcludedCategoriesParam, excluded_categories_); | |
| 731 AddCategoryToDict(dict.get(), kSyntheticDelaysParam, synthetic_delays_); | |
| 732 | 515 |
| 733 if (!event_filters_.empty()) { | 516 if (!event_filters_.empty()) { |
| 734 std::unique_ptr<base::ListValue> filter_list(new base::ListValue()); | 517 std::unique_ptr<base::ListValue> filter_list(new base::ListValue()); |
| 735 for (const EventFilterConfig& filter : event_filters_) { | 518 for (const EventFilterConfig& filter : event_filters_) { |
| 736 std::unique_ptr<base::DictionaryValue> filter_dict( | 519 std::unique_ptr<base::DictionaryValue> filter_dict( |
| 737 new base::DictionaryValue()); | 520 new base::DictionaryValue()); |
| 738 filter_dict->SetString(kFilterPredicateParam, filter.predicate_name()); | 521 filter.ToDict(filter_dict.get()); |
| 739 | |
| 740 std::unique_ptr<base::ListValue> included_categories_list( | |
| 741 new base::ListValue()); | |
| 742 for (const std::string& included_category : filter.included_categories()) | |
| 743 included_categories_list->AppendString(included_category); | |
| 744 | |
| 745 filter_dict->Set(kIncludedCategoriesParam, | |
| 746 std::move(included_categories_list)); | |
| 747 | |
| 748 if (!filter.excluded_categories().empty()) { | |
| 749 std::unique_ptr<base::ListValue> excluded_categories_list( | |
| 750 new base::ListValue()); | |
| 751 for (const std::string& excluded_category : | |
| 752 filter.excluded_categories()) | |
| 753 excluded_categories_list->AppendString(excluded_category); | |
| 754 | |
| 755 filter_dict->Set(kExcludedCategoriesParam, | |
| 756 std::move(excluded_categories_list)); | |
| 757 } | |
| 758 | |
| 759 if (filter.filter_args()) | |
| 760 filter_dict->Set(kFilterArgsParam, | |
| 761 filter.filter_args()->CreateDeepCopy()); | |
| 762 | |
| 763 filter_list->Append(std::move(filter_dict)); | 522 filter_list->Append(std::move(filter_dict)); |
| 764 } | 523 } |
| 765 dict->Set(kEventFiltersParam, std::move(filter_list)); | 524 dict->Set(kEventFiltersParam, std::move(filter_list)); |
| 766 } | 525 } |
| 767 | 526 |
| 768 if (IsCategoryEnabled(MemoryDumpManager::kTraceCategory)) { | 527 if (category_filter_.IsCategoryEnabled(MemoryDumpManager::kTraceCategory)) { |
| 769 auto allowed_modes = MakeUnique<ListValue>(); | 528 auto allowed_modes = MakeUnique<ListValue>(); |
| 770 for (auto dump_mode : memory_dump_config_.allowed_dump_modes) | 529 for (auto dump_mode : memory_dump_config_.allowed_dump_modes) |
| 771 allowed_modes->AppendString(MemoryDumpLevelOfDetailToString(dump_mode)); | 530 allowed_modes->AppendString(MemoryDumpLevelOfDetailToString(dump_mode)); |
| 772 | 531 |
| 773 auto memory_dump_config = MakeUnique<DictionaryValue>(); | 532 auto memory_dump_config = MakeUnique<DictionaryValue>(); |
| 774 memory_dump_config->Set(kAllowedDumpModesParam, std::move(allowed_modes)); | 533 memory_dump_config->Set(kAllowedDumpModesParam, std::move(allowed_modes)); |
| 775 | 534 |
| 776 auto triggers_list = MakeUnique<ListValue>(); | 535 auto triggers_list = MakeUnique<ListValue>(); |
| 777 for (const auto& config : memory_dump_config_.triggers) { | 536 for (const auto& config : memory_dump_config_.triggers) { |
| 778 auto trigger_dict = MakeUnique<DictionaryValue>(); | 537 auto trigger_dict = MakeUnique<DictionaryValue>(); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 822 default: | 581 default: |
| 823 NOTREACHED(); | 582 NOTREACHED(); |
| 824 } | 583 } |
| 825 if (enable_systrace_) | 584 if (enable_systrace_) |
| 826 ret = ret + "," + kEnableSystrace; | 585 ret = ret + "," + kEnableSystrace; |
| 827 if (enable_argument_filter_) | 586 if (enable_argument_filter_) |
| 828 ret = ret + "," + kEnableArgumentFilter; | 587 ret = ret + "," + kEnableArgumentFilter; |
| 829 return ret; | 588 return ret; |
| 830 } | 589 } |
| 831 | 590 |
| 832 void TraceConfig::WriteCategoryFilterString(const StringList& values, | |
| 833 std::string* out, | |
| 834 bool included) const { | |
| 835 bool prepend_comma = !out->empty(); | |
| 836 int token_cnt = 0; | |
| 837 for (const std::string& category : values) { | |
| 838 if (token_cnt > 0 || prepend_comma) | |
| 839 StringAppendF(out, ","); | |
| 840 StringAppendF(out, "%s%s", (included ? "" : "-"), category.c_str()); | |
| 841 ++token_cnt; | |
| 842 } | |
| 843 } | |
| 844 | |
| 845 void TraceConfig::WriteCategoryFilterString(const StringList& delays, | |
| 846 std::string* out) const { | |
| 847 bool prepend_comma = !out->empty(); | |
| 848 int token_cnt = 0; | |
| 849 for (const std::string& category : delays) { | |
| 850 if (token_cnt > 0 || prepend_comma) | |
| 851 StringAppendF(out, ","); | |
| 852 StringAppendF(out, "%s%s)", kSyntheticDelayCategoryFilterPrefix, | |
| 853 category.c_str()); | |
| 854 ++token_cnt; | |
| 855 } | |
| 856 } | |
| 857 | |
| 858 bool TraceConfig::IsCategoryEnabled(const char* category_name) const { | |
| 859 // Check the disabled- filters and the disabled-* wildcard first so that a | |
| 860 // "*" filter does not include the disabled. | |
| 861 for (const std::string& category : disabled_categories_) { | |
| 862 if (MatchPattern(category_name, category)) | |
| 863 return true; | |
| 864 } | |
| 865 | |
| 866 if (MatchPattern(category_name, TRACE_DISABLED_BY_DEFAULT("*"))) | |
| 867 return false; | |
| 868 | |
| 869 for (const std::string& category : included_categories_) { | |
| 870 if (MatchPattern(category_name, category)) | |
| 871 return true; | |
| 872 } | |
| 873 | |
| 874 return false; | |
| 875 } | |
| 876 | |
| 877 bool TraceConfig::IsEmptyOrContainsLeadingOrTrailingWhitespace( | |
| 878 StringPiece str) { | |
| 879 return str.empty() || str.front() == ' ' || str.back() == ' '; | |
| 880 } | |
| 881 | |
| 882 bool TraceConfig::HasIncludedPatterns() const { | |
| 883 return !included_categories_.empty(); | |
| 884 } | |
| 885 | |
| 886 } // namespace trace_event | 591 } // namespace trace_event |
| 887 } // namespace base | 592 } // namespace base |
| OLD | NEW |