trace_config.cc 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740
  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
  3. // found in the LICENSE file.
  4. #include "base/trace_event/trace_config.h"
  5. #include <stddef.h>
  6. #include <algorithm>
  7. #include <utility>
  8. #include "base/json/json_reader.h"
  9. #include "base/json/json_writer.h"
  10. #include "base/logging.h"
  11. #include "base/memory/ptr_util.h"
  12. #include "base/notreached.h"
  13. #include "base/strings/string_split.h"
  14. #include "base/trace_event/memory_dump_manager.h"
  15. #include "base/trace_event/memory_dump_request_args.h"
  16. #include "base/trace_event/trace_event.h"
  17. #include "third_party/abseil-cpp/absl/types/optional.h"
  18. namespace base {
  19. namespace trace_event {
  20. namespace {
  21. // String options that can be used to initialize TraceOptions.
  22. const char kRecordUntilFull[] = "record-until-full";
  23. const char kRecordContinuously[] = "record-continuously";
  24. const char kRecordAsMuchAsPossible[] = "record-as-much-as-possible";
  25. const char kTraceToConsole[] = "trace-to-console";
  26. const char kEnableSystrace[] = "enable-systrace";
  27. constexpr int kEnableSystraceLength = sizeof(kEnableSystrace) - 1;
  28. const char kEnableArgumentFilter[] = "enable-argument-filter";
  29. // String parameters that can be used to parse the trace config string.
  30. const char kRecordModeParam[] = "record_mode";
  31. const char kTraceBufferSizeInEvents[] = "trace_buffer_size_in_events";
  32. const char kTraceBufferSizeInKb[] = "trace_buffer_size_in_kb";
  33. const char kEnableSystraceParam[] = "enable_systrace";
  34. const char kSystraceEventsParam[] = "enable_systrace_events";
  35. const char kEnableArgumentFilterParam[] = "enable_argument_filter";
  36. const char kEnableEventPackageNameFilterParam[] = "enable_package_name_filter";
  37. // String parameters that is used to parse memory dump config in trace config
  38. // string.
  39. const char kMemoryDumpConfigParam[] = "memory_dump_config";
  40. const char kAllowedDumpModesParam[] = "allowed_dump_modes";
  41. const char kTriggersParam[] = "triggers";
  42. const char kTriggerModeParam[] = "mode";
  43. const char kMinTimeBetweenDumps[] = "min_time_between_dumps_ms";
  44. const char kTriggerTypeParam[] = "type";
  45. const char kPeriodicIntervalLegacyParam[] = "periodic_interval_ms";
  46. const char kHeapProfilerOptions[] = "heap_profiler_options";
  47. const char kBreakdownThresholdBytes[] = "breakdown_threshold_bytes";
  48. // String parameters used to parse category event filters.
  49. const char kEventFiltersParam[] = "event_filters";
  50. const char kFilterPredicateParam[] = "filter_predicate";
  51. const char kFilterArgsParam[] = "filter_args";
  52. // String parameter used to parse process filter.
  53. const char kIncludedProcessesParam[] = "included_process_ids";
  54. const char kHistogramNamesParam[] = "histogram_names";
  55. class ConvertableTraceConfigToTraceFormat
  56. : public base::trace_event::ConvertableToTraceFormat {
  57. public:
  58. explicit ConvertableTraceConfigToTraceFormat(const TraceConfig& trace_config)
  59. : trace_config_(trace_config) {}
  60. ~ConvertableTraceConfigToTraceFormat() override = default;
  61. void AppendAsTraceFormat(std::string* out) const override {
  62. out->append(trace_config_.ToString());
  63. }
  64. private:
  65. const TraceConfig trace_config_;
  66. };
  67. std::set<MemoryDumpLevelOfDetail> GetDefaultAllowedMemoryDumpModes() {
  68. std::set<MemoryDumpLevelOfDetail> all_modes;
  69. for (uint32_t mode = static_cast<uint32_t>(MemoryDumpLevelOfDetail::FIRST);
  70. mode <= static_cast<uint32_t>(MemoryDumpLevelOfDetail::LAST); mode++) {
  71. all_modes.insert(static_cast<MemoryDumpLevelOfDetail>(mode));
  72. }
  73. return all_modes;
  74. }
  75. } // namespace
  76. TraceConfig::MemoryDumpConfig::HeapProfiler::HeapProfiler()
  77. : breakdown_threshold_bytes(kDefaultBreakdownThresholdBytes) {}
  78. void TraceConfig::MemoryDumpConfig::HeapProfiler::Clear() {
  79. breakdown_threshold_bytes = kDefaultBreakdownThresholdBytes;
  80. }
  81. void TraceConfig::ResetMemoryDumpConfig(
  82. const TraceConfig::MemoryDumpConfig& memory_dump_config) {
  83. memory_dump_config_.Clear();
  84. memory_dump_config_ = memory_dump_config;
  85. }
  86. TraceConfig::MemoryDumpConfig::MemoryDumpConfig() = default;
  87. TraceConfig::MemoryDumpConfig::MemoryDumpConfig(
  88. const MemoryDumpConfig& other) = default;
  89. TraceConfig::MemoryDumpConfig::~MemoryDumpConfig() = default;
  90. void TraceConfig::MemoryDumpConfig::Clear() {
  91. allowed_dump_modes.clear();
  92. triggers.clear();
  93. heap_profiler_options.Clear();
  94. }
  95. void TraceConfig::MemoryDumpConfig::Merge(
  96. const TraceConfig::MemoryDumpConfig& config) {
  97. triggers.insert(triggers.end(), config.triggers.begin(),
  98. config.triggers.end());
  99. allowed_dump_modes.insert(config.allowed_dump_modes.begin(),
  100. config.allowed_dump_modes.end());
  101. heap_profiler_options.breakdown_threshold_bytes =
  102. std::min(heap_profiler_options.breakdown_threshold_bytes,
  103. config.heap_profiler_options.breakdown_threshold_bytes);
  104. }
  105. TraceConfig::ProcessFilterConfig::ProcessFilterConfig() = default;
  106. TraceConfig::ProcessFilterConfig::ProcessFilterConfig(
  107. const ProcessFilterConfig& other) = default;
  108. TraceConfig::ProcessFilterConfig::ProcessFilterConfig(
  109. const std::unordered_set<base::ProcessId>& included_process_ids)
  110. : included_process_ids_(included_process_ids) {}
  111. TraceConfig::ProcessFilterConfig::~ProcessFilterConfig() = default;
  112. void TraceConfig::ProcessFilterConfig::Clear() {
  113. included_process_ids_.clear();
  114. }
  115. void TraceConfig::ProcessFilterConfig::Merge(
  116. const ProcessFilterConfig& config) {
  117. included_process_ids_.insert(config.included_process_ids_.begin(),
  118. config.included_process_ids_.end());
  119. }
  120. void TraceConfig::ProcessFilterConfig::InitializeFromConfigDict(
  121. const Value& dict) {
  122. included_process_ids_.clear();
  123. const Value* value = dict.FindListKey(kIncludedProcessesParam);
  124. if (!value)
  125. return;
  126. for (auto& pid_value : value->GetListDeprecated()) {
  127. if (pid_value.is_int()) {
  128. included_process_ids_.insert(
  129. static_cast<base::ProcessId>(pid_value.GetInt()));
  130. }
  131. }
  132. }
  133. void TraceConfig::ProcessFilterConfig::ToDict(Value::Dict& dict) const {
  134. if (included_process_ids_.empty())
  135. return;
  136. base::Value::List list;
  137. std::set<base::ProcessId> ordered_set(included_process_ids_.begin(),
  138. included_process_ids_.end());
  139. for (auto process_id : ordered_set)
  140. list.Append(static_cast<int>(process_id));
  141. dict.Set(kIncludedProcessesParam, std::move(list));
  142. }
  143. bool TraceConfig::ProcessFilterConfig::IsEnabled(
  144. base::ProcessId process_id) const {
  145. return included_process_ids_.empty() ||
  146. included_process_ids_.count(process_id);
  147. }
  148. TraceConfig::EventFilterConfig::EventFilterConfig(
  149. const std::string& predicate_name)
  150. : predicate_name_(predicate_name) {}
  151. TraceConfig::EventFilterConfig::~EventFilterConfig() = default;
  152. TraceConfig::EventFilterConfig::EventFilterConfig(const EventFilterConfig& tc) {
  153. *this = tc;
  154. }
  155. TraceConfig::EventFilterConfig& TraceConfig::EventFilterConfig::operator=(
  156. const TraceConfig::EventFilterConfig& rhs) {
  157. if (this == &rhs)
  158. return *this;
  159. predicate_name_ = rhs.predicate_name_;
  160. category_filter_ = rhs.category_filter_;
  161. if (!rhs.args_.is_none())
  162. args_ = rhs.args_.Clone();
  163. return *this;
  164. }
  165. void TraceConfig::EventFilterConfig::InitializeFromConfigDict(
  166. const Value& event_filter) {
  167. category_filter_.InitializeFromConfigDict(event_filter);
  168. const Value* args_dict = event_filter.FindDictKey(kFilterArgsParam);
  169. if (args_dict)
  170. args_ = args_dict->Clone();
  171. }
  172. void TraceConfig::EventFilterConfig::SetCategoryFilter(
  173. const TraceConfigCategoryFilter& category_filter) {
  174. category_filter_ = category_filter;
  175. }
  176. void TraceConfig::EventFilterConfig::ToDict(Value::Dict& filter_dict) const {
  177. filter_dict.Set(kFilterPredicateParam, predicate_name());
  178. category_filter_.ToDict(filter_dict);
  179. if (!args_.is_none())
  180. filter_dict.Set(kFilterArgsParam, args_.Clone());
  181. }
  182. bool TraceConfig::EventFilterConfig::GetArgAsSet(
  183. const char* key,
  184. std::unordered_set<std::string>* out_set) const {
  185. const Value* list = args_.FindListPath(key);
  186. if (!list)
  187. return false;
  188. for (const Value& item : list->GetListDeprecated()) {
  189. if (item.is_string())
  190. out_set->insert(item.GetString());
  191. }
  192. return true;
  193. }
  194. bool TraceConfig::EventFilterConfig::IsCategoryGroupEnabled(
  195. const StringPiece& category_group_name) const {
  196. return category_filter_.IsCategoryGroupEnabled(category_group_name);
  197. }
  198. // static
  199. std::string TraceConfig::TraceRecordModeToStr(TraceRecordMode record_mode) {
  200. switch (record_mode) {
  201. case RECORD_UNTIL_FULL:
  202. return kRecordUntilFull;
  203. case RECORD_CONTINUOUSLY:
  204. return kRecordContinuously;
  205. case RECORD_AS_MUCH_AS_POSSIBLE:
  206. return kRecordAsMuchAsPossible;
  207. case ECHO_TO_CONSOLE:
  208. return kTraceToConsole;
  209. default:
  210. NOTREACHED();
  211. }
  212. return kRecordUntilFull;
  213. }
  214. TraceConfig::TraceConfig() {
  215. InitializeDefault();
  216. }
  217. TraceConfig::TraceConfig(StringPiece category_filter_string,
  218. StringPiece trace_options_string) {
  219. InitializeFromStrings(category_filter_string, trace_options_string);
  220. }
  221. TraceConfig::TraceConfig(StringPiece category_filter_string,
  222. TraceRecordMode record_mode) {
  223. InitializeFromStrings(category_filter_string,
  224. TraceConfig::TraceRecordModeToStr(record_mode));
  225. }
  226. TraceConfig::TraceConfig(const Value& config) {
  227. InitializeFromConfigDict(config);
  228. }
  229. TraceConfig::TraceConfig(StringPiece config_string) {
  230. if (!config_string.empty())
  231. InitializeFromConfigString(config_string);
  232. else
  233. InitializeDefault();
  234. }
  235. TraceConfig::TraceConfig(const TraceConfig& tc) = default;
  236. TraceConfig::~TraceConfig() = default;
  237. TraceConfig& TraceConfig::operator=(const TraceConfig& rhs) {
  238. if (this == &rhs)
  239. return *this;
  240. record_mode_ = rhs.record_mode_;
  241. trace_buffer_size_in_events_ = rhs.trace_buffer_size_in_events_;
  242. trace_buffer_size_in_kb_ = rhs.trace_buffer_size_in_kb_;
  243. enable_systrace_ = rhs.enable_systrace_;
  244. enable_argument_filter_ = rhs.enable_argument_filter_;
  245. category_filter_ = rhs.category_filter_;
  246. process_filter_config_ = rhs.process_filter_config_;
  247. enable_event_package_name_filter_ = rhs.enable_event_package_name_filter_;
  248. memory_dump_config_ = rhs.memory_dump_config_;
  249. event_filters_ = rhs.event_filters_;
  250. histogram_names_ = rhs.histogram_names_;
  251. systrace_events_ = rhs.systrace_events_;
  252. return *this;
  253. }
  254. std::string TraceConfig::ToString() const {
  255. Value dict = ToValue();
  256. std::string json;
  257. JSONWriter::Write(dict, &json);
  258. return json;
  259. }
  260. std::unique_ptr<ConvertableToTraceFormat>
  261. TraceConfig::AsConvertableToTraceFormat() const {
  262. return std::make_unique<ConvertableTraceConfigToTraceFormat>(*this);
  263. }
  264. std::string TraceConfig::ToCategoryFilterString() const {
  265. return category_filter_.ToFilterString();
  266. }
  267. bool TraceConfig::IsCategoryGroupEnabled(
  268. const StringPiece& category_group_name) const {
  269. // TraceLog should call this method only as part of enabling/disabling
  270. // categories.
  271. return category_filter_.IsCategoryGroupEnabled(category_group_name);
  272. }
  273. void TraceConfig::Merge(const TraceConfig& config) {
  274. if (record_mode_ != config.record_mode_ ||
  275. enable_systrace_ != config.enable_systrace_ ||
  276. enable_argument_filter_ != config.enable_argument_filter_ ||
  277. enable_event_package_name_filter_ !=
  278. config.enable_event_package_name_filter_) {
  279. DLOG(ERROR) << "Attempting to merge trace config with a different "
  280. << "set of options.";
  281. }
  282. DCHECK_EQ(trace_buffer_size_in_events_, config.trace_buffer_size_in_events_)
  283. << "Cannot change trace buffer size";
  284. category_filter_.Merge(config.category_filter_);
  285. memory_dump_config_.Merge(config.memory_dump_config_);
  286. process_filter_config_.Merge(config.process_filter_config_);
  287. event_filters_.insert(event_filters_.end(), config.event_filters().begin(),
  288. config.event_filters().end());
  289. histogram_names_.insert(config.histogram_names().begin(),
  290. config.histogram_names().end());
  291. }
  292. void TraceConfig::Clear() {
  293. record_mode_ = RECORD_UNTIL_FULL;
  294. trace_buffer_size_in_events_ = 0;
  295. trace_buffer_size_in_kb_ = 0;
  296. enable_systrace_ = false;
  297. enable_argument_filter_ = false;
  298. enable_event_package_name_filter_ = false;
  299. category_filter_.Clear();
  300. memory_dump_config_.Clear();
  301. process_filter_config_.Clear();
  302. event_filters_.clear();
  303. histogram_names_.clear();
  304. systrace_events_.clear();
  305. }
  306. void TraceConfig::InitializeDefault() {
  307. record_mode_ = RECORD_UNTIL_FULL;
  308. trace_buffer_size_in_events_ = 0;
  309. trace_buffer_size_in_kb_ = 0;
  310. enable_systrace_ = false;
  311. enable_argument_filter_ = false;
  312. enable_event_package_name_filter_ = false;
  313. }
  314. void TraceConfig::InitializeFromConfigDict(const Value& dict) {
  315. record_mode_ = RECORD_UNTIL_FULL;
  316. const std::string* record_mode = dict.FindStringKey(kRecordModeParam);
  317. if (record_mode) {
  318. if (*record_mode == kRecordUntilFull) {
  319. record_mode_ = RECORD_UNTIL_FULL;
  320. } else if (*record_mode == kRecordContinuously) {
  321. record_mode_ = RECORD_CONTINUOUSLY;
  322. } else if (*record_mode == kTraceToConsole) {
  323. record_mode_ = ECHO_TO_CONSOLE;
  324. } else if (*record_mode == kRecordAsMuchAsPossible) {
  325. record_mode_ = RECORD_AS_MUCH_AS_POSSIBLE;
  326. }
  327. }
  328. trace_buffer_size_in_events_ = base::saturated_cast<size_t>(
  329. dict.FindIntKey(kTraceBufferSizeInEvents).value_or(0));
  330. trace_buffer_size_in_kb_ = base::saturated_cast<size_t>(
  331. dict.FindIntKey(kTraceBufferSizeInKb).value_or(0));
  332. enable_systrace_ = dict.FindBoolKey(kEnableSystraceParam).value_or(false);
  333. enable_argument_filter_ =
  334. dict.FindBoolKey(kEnableArgumentFilterParam).value_or(false);
  335. enable_event_package_name_filter_ =
  336. dict.FindBoolKey(kEnableEventPackageNameFilterParam).value_or(false);
  337. category_filter_.InitializeFromConfigDict(dict);
  338. process_filter_config_.InitializeFromConfigDict(dict);
  339. const Value* category_event_filters = dict.FindListKey(kEventFiltersParam);
  340. if (category_event_filters)
  341. SetEventFiltersFromConfigList(*category_event_filters);
  342. const Value* histogram_names = dict.FindListKey(kHistogramNamesParam);
  343. if (histogram_names)
  344. SetHistogramNamesFromConfigList(*histogram_names);
  345. if (category_filter_.IsCategoryEnabled(MemoryDumpManager::kTraceCategory)) {
  346. // If dump triggers not set, the client is using the legacy with just
  347. // category enabled. So, use the default periodic dump config.
  348. const Value* memory_dump_config = dict.FindDictKey(kMemoryDumpConfigParam);
  349. if (memory_dump_config)
  350. SetMemoryDumpConfigFromConfigDict(*memory_dump_config);
  351. else
  352. SetDefaultMemoryDumpConfig();
  353. }
  354. systrace_events_.clear();
  355. if (enable_systrace_) {
  356. const Value* systrace_events = dict.FindListKey(kSystraceEventsParam);
  357. if (systrace_events) {
  358. for (const Value& value : systrace_events->GetListDeprecated())
  359. systrace_events_.insert(value.GetString());
  360. }
  361. }
  362. }
  363. void TraceConfig::InitializeFromConfigString(StringPiece config_string) {
  364. absl::optional<Value> dict = JSONReader::Read(config_string);
  365. if (dict && dict->is_dict())
  366. InitializeFromConfigDict(*dict);
  367. else
  368. InitializeDefault();
  369. }
  370. void TraceConfig::InitializeFromStrings(StringPiece category_filter_string,
  371. StringPiece trace_options_string) {
  372. if (!category_filter_string.empty())
  373. category_filter_.InitializeFromString(category_filter_string);
  374. record_mode_ = RECORD_UNTIL_FULL;
  375. trace_buffer_size_in_events_ = 0;
  376. trace_buffer_size_in_kb_ = 0;
  377. enable_systrace_ = false;
  378. systrace_events_.clear();
  379. enable_argument_filter_ = false;
  380. enable_event_package_name_filter_ = false;
  381. if (!trace_options_string.empty()) {
  382. std::vector<std::string> split =
  383. SplitString(trace_options_string, ",", TRIM_WHITESPACE, SPLIT_WANT_ALL);
  384. for (const std::string& token : split) {
  385. if (token == kRecordUntilFull) {
  386. record_mode_ = RECORD_UNTIL_FULL;
  387. } else if (token == kRecordContinuously) {
  388. record_mode_ = RECORD_CONTINUOUSLY;
  389. } else if (token == kTraceToConsole) {
  390. record_mode_ = ECHO_TO_CONSOLE;
  391. } else if (token == kRecordAsMuchAsPossible) {
  392. record_mode_ = RECORD_AS_MUCH_AS_POSSIBLE;
  393. } else if (token.find(kEnableSystrace) == 0) {
  394. // Find optional events list.
  395. const size_t length = token.length();
  396. if (length == kEnableSystraceLength) {
  397. // Use all predefined categories.
  398. enable_systrace_ = true;
  399. continue;
  400. }
  401. const auto system_events_not_trimmed =
  402. token.substr(kEnableSystraceLength);
  403. const auto system_events =
  404. TrimString(system_events_not_trimmed, kWhitespaceASCII, TRIM_ALL);
  405. if (system_events[0] != '=') {
  406. LOG(ERROR) << "Failed to parse " << token;
  407. continue;
  408. }
  409. enable_systrace_ = true;
  410. const std::vector<std::string> split_systrace_events = SplitString(
  411. system_events.substr(1), " ", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
  412. for (const std::string& systrace_event : split_systrace_events)
  413. systrace_events_.insert(systrace_event);
  414. } else if (token == kEnableArgumentFilter) {
  415. enable_argument_filter_ = true;
  416. }
  417. }
  418. }
  419. if (category_filter_.IsCategoryEnabled(MemoryDumpManager::kTraceCategory)) {
  420. SetDefaultMemoryDumpConfig();
  421. }
  422. }
  423. void TraceConfig::SetMemoryDumpConfigFromConfigDict(
  424. const Value& memory_dump_config) {
  425. // Set allowed dump modes.
  426. memory_dump_config_.allowed_dump_modes.clear();
  427. const Value* allowed_modes_list =
  428. memory_dump_config.FindListKey(kAllowedDumpModesParam);
  429. if (allowed_modes_list) {
  430. for (const Value& item : allowed_modes_list->GetListDeprecated()) {
  431. DCHECK(item.is_string());
  432. memory_dump_config_.allowed_dump_modes.insert(
  433. StringToMemoryDumpLevelOfDetail(item.GetString()));
  434. }
  435. } else {
  436. // If allowed modes param is not given then allow all modes by default.
  437. memory_dump_config_.allowed_dump_modes = GetDefaultAllowedMemoryDumpModes();
  438. }
  439. // Set triggers
  440. memory_dump_config_.triggers.clear();
  441. const Value* trigger_list = memory_dump_config.FindListKey(kTriggersParam);
  442. if (trigger_list) {
  443. for (const Value& trigger : trigger_list->GetListDeprecated()) {
  444. if (!trigger.is_dict())
  445. continue;
  446. MemoryDumpConfig::Trigger dump_config;
  447. absl::optional<int> interval = trigger.FindIntKey(kMinTimeBetweenDumps);
  448. if (!interval) {
  449. // If "min_time_between_dumps_ms" param was not given, then the trace
  450. // config uses old format where only periodic dumps are supported.
  451. interval = trigger.FindIntKey(kPeriodicIntervalLegacyParam);
  452. dump_config.trigger_type = MemoryDumpType::PERIODIC_INTERVAL;
  453. } else {
  454. const std::string* trigger_type_str =
  455. trigger.FindStringKey(kTriggerTypeParam);
  456. DCHECK(trigger_type_str);
  457. dump_config.trigger_type = StringToMemoryDumpType(*trigger_type_str);
  458. }
  459. DCHECK(interval.has_value());
  460. DCHECK_GT(*interval, 0);
  461. dump_config.min_time_between_dumps_ms = static_cast<uint32_t>(*interval);
  462. const std::string* level_of_detail_str =
  463. trigger.FindStringKey(kTriggerModeParam);
  464. DCHECK(level_of_detail_str);
  465. dump_config.level_of_detail =
  466. StringToMemoryDumpLevelOfDetail(*level_of_detail_str);
  467. memory_dump_config_.triggers.push_back(dump_config);
  468. }
  469. }
  470. // Set heap profiler options
  471. const Value* heap_profiler_options =
  472. memory_dump_config.FindDictKey(kHeapProfilerOptions);
  473. if (heap_profiler_options) {
  474. absl::optional<int> min_size_bytes =
  475. heap_profiler_options->FindIntKey(kBreakdownThresholdBytes);
  476. if (min_size_bytes && *min_size_bytes >= 0) {
  477. memory_dump_config_.heap_profiler_options.breakdown_threshold_bytes =
  478. static_cast<uint32_t>(*min_size_bytes);
  479. } else {
  480. memory_dump_config_.heap_profiler_options.breakdown_threshold_bytes =
  481. MemoryDumpConfig::HeapProfiler::kDefaultBreakdownThresholdBytes;
  482. }
  483. }
  484. }
  485. void TraceConfig::SetDefaultMemoryDumpConfig() {
  486. memory_dump_config_.Clear();
  487. memory_dump_config_.allowed_dump_modes = GetDefaultAllowedMemoryDumpModes();
  488. }
  489. void TraceConfig::SetProcessFilterConfig(const ProcessFilterConfig& config) {
  490. process_filter_config_ = config;
  491. }
  492. void TraceConfig::SetHistogramNamesFromConfigList(
  493. const Value& histogram_names) {
  494. histogram_names_.clear();
  495. for (const Value& value : histogram_names.GetListDeprecated())
  496. histogram_names_.insert(value.GetString());
  497. }
  498. void TraceConfig::SetEventFiltersFromConfigList(
  499. const Value& category_event_filters) {
  500. event_filters_.clear();
  501. for (const Value& event_filter : category_event_filters.GetListDeprecated()) {
  502. if (!event_filter.is_dict())
  503. continue;
  504. const std::string* predicate_name =
  505. event_filter.FindStringKey(kFilterPredicateParam);
  506. CHECK(predicate_name) << "Invalid predicate name in category event filter.";
  507. EventFilterConfig new_config(*predicate_name);
  508. new_config.InitializeFromConfigDict(event_filter);
  509. event_filters_.push_back(new_config);
  510. }
  511. }
  512. Value TraceConfig::ToValue() const {
  513. Value::Dict dict;
  514. dict.Set(kRecordModeParam, TraceConfig::TraceRecordModeToStr(record_mode_));
  515. dict.Set(kEnableSystraceParam, enable_systrace_);
  516. dict.Set(kEnableArgumentFilterParam, enable_argument_filter_);
  517. if (trace_buffer_size_in_events_ > 0) {
  518. dict.Set(kTraceBufferSizeInEvents,
  519. base::checked_cast<int>(trace_buffer_size_in_events_));
  520. }
  521. if (trace_buffer_size_in_kb_ > 0) {
  522. dict.Set(kTraceBufferSizeInKb,
  523. base::checked_cast<int>(trace_buffer_size_in_kb_));
  524. }
  525. dict.Set(kEnableEventPackageNameFilterParam,
  526. enable_event_package_name_filter_);
  527. category_filter_.ToDict(dict);
  528. process_filter_config_.ToDict(dict);
  529. if (!event_filters_.empty()) {
  530. Value::List filter_list;
  531. for (const EventFilterConfig& filter : event_filters_) {
  532. Value::Dict filter_dict;
  533. filter.ToDict(filter_dict);
  534. filter_list.Append(std::move(filter_dict));
  535. }
  536. dict.Set(kEventFiltersParam, std::move(filter_list));
  537. }
  538. if (category_filter_.IsCategoryEnabled(MemoryDumpManager::kTraceCategory)) {
  539. Value::List allowed_modes;
  540. for (auto dump_mode : memory_dump_config_.allowed_dump_modes)
  541. allowed_modes.Append(MemoryDumpLevelOfDetailToString(dump_mode));
  542. Value::Dict memory_dump_config;
  543. memory_dump_config.Set(kAllowedDumpModesParam, std::move(allowed_modes));
  544. Value::List triggers_list;
  545. for (const auto& config : memory_dump_config_.triggers) {
  546. Value::Dict trigger_dict;
  547. trigger_dict.Set(kTriggerTypeParam,
  548. MemoryDumpTypeToString(config.trigger_type));
  549. trigger_dict.Set(kMinTimeBetweenDumps,
  550. static_cast<int>(config.min_time_between_dumps_ms));
  551. trigger_dict.Set(kTriggerModeParam,
  552. MemoryDumpLevelOfDetailToString(config.level_of_detail));
  553. triggers_list.Append(std::move(trigger_dict));
  554. }
  555. // Empty triggers will still be specified explicitly since it means that
  556. // the periodic dumps are not enabled.
  557. memory_dump_config.Set(kTriggersParam, std::move(triggers_list));
  558. if (memory_dump_config_.heap_profiler_options.breakdown_threshold_bytes !=
  559. MemoryDumpConfig::HeapProfiler::kDefaultBreakdownThresholdBytes) {
  560. Value options(Value::Type::DICTIONARY);
  561. options.SetIntKey(
  562. kBreakdownThresholdBytes,
  563. base::checked_cast<int>(memory_dump_config_.heap_profiler_options
  564. .breakdown_threshold_bytes));
  565. memory_dump_config.Set(kHeapProfilerOptions, std::move(options));
  566. }
  567. dict.Set(kMemoryDumpConfigParam, std::move(memory_dump_config));
  568. }
  569. if (!histogram_names_.empty()) {
  570. base::Value::List histogram_names;
  571. for (const std::string& histogram_name : histogram_names_)
  572. histogram_names.Append(histogram_name);
  573. dict.Set(kHistogramNamesParam, std::move(histogram_names));
  574. }
  575. if (enable_systrace_) {
  576. if (!systrace_events_.empty()) {
  577. base::Value::List systrace_events;
  578. for (const std::string& systrace_event : systrace_events_)
  579. systrace_events.Append(systrace_event);
  580. dict.Set(kSystraceEventsParam, std::move(systrace_events));
  581. }
  582. }
  583. return Value(std::move(dict));
  584. }
  585. void TraceConfig::EnableSystraceEvent(const std::string& systrace_event) {
  586. systrace_events_.insert(systrace_event);
  587. }
  588. void TraceConfig::EnableHistogram(const std::string& histogram_name) {
  589. histogram_names_.insert(histogram_name);
  590. }
  591. std::string TraceConfig::ToTraceOptionsString() const {
  592. std::string ret;
  593. switch (record_mode_) {
  594. case RECORD_UNTIL_FULL:
  595. ret = kRecordUntilFull;
  596. break;
  597. case RECORD_CONTINUOUSLY:
  598. ret = kRecordContinuously;
  599. break;
  600. case RECORD_AS_MUCH_AS_POSSIBLE:
  601. ret = kRecordAsMuchAsPossible;
  602. break;
  603. case ECHO_TO_CONSOLE:
  604. ret = kTraceToConsole;
  605. break;
  606. default:
  607. NOTREACHED();
  608. }
  609. if (enable_systrace_) {
  610. ret += ",";
  611. ret += kEnableSystrace;
  612. bool first_param = true;
  613. for (const std::string& systrace_event : systrace_events_) {
  614. if (first_param) {
  615. ret += "=";
  616. first_param = false;
  617. } else {
  618. ret += " ";
  619. }
  620. ret = ret + systrace_event;
  621. }
  622. }
  623. if (enable_argument_filter_) {
  624. ret += ",";
  625. ret += kEnableArgumentFilter;
  626. }
  627. return ret;
  628. }
  629. } // namespace trace_event
  630. } // namespace base