blob: 56a8f061a129e49125cb2a7ef1677bc76e2fc3cd [file] [log] [blame]
Hector Dearman5edeafc2018-11-29 13:27:33 +00001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "src/perfetto_cmd/config.h"
18
19#include <stdlib.h>
20
21#include "perfetto/base/logging.h"
Hector Dearman2ccf2d72021-04-20 11:28:50 +010022#include "perfetto/ext/base/string_utils.h"
Primiano Tucci54985c22019-12-03 12:14:08 +000023#include "perfetto/tracing/core/data_source_config.h"
24#include "perfetto/tracing/core/trace_config.h"
25
26#include "protos/perfetto/config/ftrace/ftrace_config.gen.h"
Hector Dearman5edeafc2018-11-29 13:27:33 +000027
28namespace perfetto {
29namespace {
Hector Dearman5edeafc2018-11-29 13:27:33 +000030using ValueUnit = std::pair<uint64_t, std::string>;
31using UnitMultipler = std::pair<const char*, uint64_t>;
32
33bool SplitValueAndUnit(const std::string& arg, ValueUnit* out) {
34 char* end;
Hector Dearmane97c89b2021-01-08 13:00:13 +000035 if (arg.empty())
Hector Dearman5edeafc2018-11-29 13:27:33 +000036 return false;
37 out->first = strtoull(arg.c_str(), &end, 10);
38 if (end == arg.data())
39 return false;
40 std::string unit = arg.substr(static_cast<size_t>(end - arg.data()));
41 out->second = std::move(unit);
42 return true;
43}
44
45bool ConvertValue(const std::string& arg,
46 std::vector<UnitMultipler> units,
47 uint64_t* out) {
48 if (arg.empty()) {
49 *out = 0;
50 return true;
51 }
52
Hector Dearman146b5b72020-07-31 18:46:32 +010053 if (arg == "0") {
54 *out = 0;
55 return true;
56 }
57
Hector Dearman5edeafc2018-11-29 13:27:33 +000058 ValueUnit value_unit{};
59 if (!SplitValueAndUnit(arg, &value_unit))
60 return false;
61
62 for (const auto& unit_multiplier : units) {
63 if (value_unit.second != unit_multiplier.first)
64 continue;
65 *out = value_unit.first * unit_multiplier.second;
66 return true;
67 }
68 return false;
69}
70
71bool ConvertTimeToMs(const std::string& arg, uint64_t* out) {
Hector Dearman859d8f82022-05-10 15:13:45 +010072 return ConvertValue(arg,
73 {
74 {"ms", 1},
75 {"s", 1000},
76 {"m", 1000 * 60},
77 {"h", 1000 * 60 * 60},
78 },
79 out);
Hector Dearman5edeafc2018-11-29 13:27:33 +000080}
81
82bool ConvertSizeToKb(const std::string& arg, uint64_t* out) {
83 return ConvertValue(arg,
84 {
85 {"kb", 1},
86 {"mb", 1024},
87 {"gb", 1024 * 1024},
88 {"k", 1},
89 {"m", 1024},
90 {"g", 1024 * 1024},
91 },
92 out);
93}
94
95} // namespace
96
97bool CreateConfigFromOptions(const ConfigOptions& options,
Primiano Tucci54985c22019-12-03 12:14:08 +000098 TraceConfig* config) {
Hector Dearman5edeafc2018-11-29 13:27:33 +000099 uint64_t duration_ms = 0;
Primiano Tucciaaf562c2018-12-04 21:21:36 +0000100 if (!ConvertTimeToMs(options.time, &duration_ms)) {
101 PERFETTO_ELOG("--time argument is invalid");
Hector Dearman5edeafc2018-11-29 13:27:33 +0000102 return false;
Primiano Tucciaaf562c2018-12-04 21:21:36 +0000103 }
Hector Dearman5edeafc2018-11-29 13:27:33 +0000104
105 uint64_t buffer_size_kb = 0;
Primiano Tucciaaf562c2018-12-04 21:21:36 +0000106 if (!ConvertSizeToKb(options.buffer_size, &buffer_size_kb)) {
107 PERFETTO_ELOG("--buffer argument is invalid");
Hector Dearman5edeafc2018-11-29 13:27:33 +0000108 return false;
Primiano Tucciaaf562c2018-12-04 21:21:36 +0000109 }
Hector Dearman5edeafc2018-11-29 13:27:33 +0000110
111 uint64_t max_file_size_kb = 0;
Primiano Tucciaaf562c2018-12-04 21:21:36 +0000112 if (!ConvertSizeToKb(options.max_file_size, &max_file_size_kb)) {
113 PERFETTO_ELOG("--size argument is invalid");
Hector Dearman5edeafc2018-11-29 13:27:33 +0000114 return false;
Primiano Tucciaaf562c2018-12-04 21:21:36 +0000115 }
Hector Dearman5edeafc2018-11-29 13:27:33 +0000116
117 std::vector<std::string> ftrace_events;
118 std::vector<std::string> atrace_categories;
119 std::vector<std::string> atrace_apps = options.atrace_apps;
120
121 for (const auto& category : options.categories) {
Hector Dearman2ccf2d72021-04-20 11:28:50 +0100122 if (base::Contains(category, '/')) {
Hector Dearman5edeafc2018-11-29 13:27:33 +0000123 ftrace_events.push_back(category);
Hector Dearman2ccf2d72021-04-20 11:28:50 +0100124 } else {
125 atrace_categories.push_back(category);
Hector Dearman5edeafc2018-11-29 13:27:33 +0000126 }
Lalit Maganti3a5a52f2021-05-04 13:12:43 +0100127
128 // For the gfx category, also add the frame timeline data source
129 // as it's very useful for debugging gfx issues.
130 if (category == "gfx") {
131 auto* frame_timeline = config->add_data_sources();
132 frame_timeline->mutable_config()->set_name(
133 "android.surfaceflinger.frametimeline");
134 }
Hector Dearman5edeafc2018-11-29 13:27:33 +0000135 }
136
137 config->set_duration_ms(static_cast<unsigned int>(duration_ms));
Primiano Tucciaaf562c2018-12-04 21:21:36 +0000138 config->set_max_file_size_bytes(max_file_size_kb * 1024);
Hector Dearman2f380292019-02-27 13:15:44 +0000139 config->set_flush_period_ms(30 * 1000);
Hector Dearman5edeafc2018-11-29 13:27:33 +0000140 if (max_file_size_kb)
141 config->set_write_into_file(true);
142 config->add_buffers()->set_size_kb(static_cast<unsigned int>(buffer_size_kb));
143 auto* ds_config = config->add_data_sources()->mutable_config();
144 ds_config->set_name("linux.ftrace");
Primiano Tucci54985c22019-12-03 12:14:08 +0000145 protos::gen::FtraceConfig ftrace_cfg;
Hector Dearman5edeafc2018-11-29 13:27:33 +0000146 for (const auto& evt : ftrace_events)
Primiano Tucci54985c22019-12-03 12:14:08 +0000147 ftrace_cfg.add_ftrace_events(evt);
Hector Dearman5edeafc2018-11-29 13:27:33 +0000148 for (const auto& cat : atrace_categories)
Primiano Tucci54985c22019-12-03 12:14:08 +0000149 ftrace_cfg.add_atrace_categories(cat);
Hector Dearman5edeafc2018-11-29 13:27:33 +0000150 for (const auto& app : atrace_apps)
Primiano Tucci54985c22019-12-03 12:14:08 +0000151 ftrace_cfg.add_atrace_apps(app);
Hector Dearman35c86de2022-03-23 13:31:01 +0000152 ftrace_cfg.set_symbolize_ksyms(true);
Primiano Tucci54985c22019-12-03 12:14:08 +0000153 ds_config->set_ftrace_config_raw(ftrace_cfg.SerializeAsString());
Hector Dearman5edeafc2018-11-29 13:27:33 +0000154
Hector Dearman5edeafc2018-11-29 13:27:33 +0000155 auto* ps_config = config->add_data_sources()->mutable_config();
156 ps_config->set_name("linux.process_stats");
157 ps_config->set_target_buffer(0);
158
159 return true;
160}
161
162} // namespace perfetto