• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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"
22 
23 namespace perfetto {
24 namespace {
25 using ValueUnit = std::pair<uint64_t, std::string>;
26 using UnitMultipler = std::pair<const char*, uint64_t>;
27 
SplitValueAndUnit(const std::string & arg,ValueUnit * out)28 bool SplitValueAndUnit(const std::string& arg, ValueUnit* out) {
29   char* end;
30   if (!arg.size())
31     return false;
32   out->first = strtoull(arg.c_str(), &end, 10);
33   if (end == arg.data())
34     return false;
35   std::string unit = arg.substr(static_cast<size_t>(end - arg.data()));
36   out->second = std::move(unit);
37   return true;
38 }
39 
ConvertValue(const std::string & arg,std::vector<UnitMultipler> units,uint64_t * out)40 bool ConvertValue(const std::string& arg,
41                   std::vector<UnitMultipler> units,
42                   uint64_t* out) {
43   if (arg.empty()) {
44     *out = 0;
45     return true;
46   }
47 
48   ValueUnit value_unit{};
49   if (!SplitValueAndUnit(arg, &value_unit))
50     return false;
51 
52   for (const auto& unit_multiplier : units) {
53     if (value_unit.second != unit_multiplier.first)
54       continue;
55     *out = value_unit.first * unit_multiplier.second;
56     return true;
57   }
58   return false;
59 }
60 
ConvertTimeToMs(const std::string & arg,uint64_t * out)61 bool ConvertTimeToMs(const std::string& arg, uint64_t* out) {
62   return ConvertValue(
63       arg,
64       {
65           {"ms", 1}, {"s", 1000}, {"m", 1000 * 60}, {"h", 1000 * 60 * 60},
66       },
67       out);
68 }
69 
ConvertSizeToKb(const std::string & arg,uint64_t * out)70 bool ConvertSizeToKb(const std::string& arg, uint64_t* out) {
71   return ConvertValue(arg,
72                       {
73                           {"kb", 1},
74                           {"mb", 1024},
75                           {"gb", 1024 * 1024},
76                           {"k", 1},
77                           {"m", 1024},
78                           {"g", 1024 * 1024},
79                       },
80                       out);
81 }
82 
83 }  // namespace
84 
CreateConfigFromOptions(const ConfigOptions & options,protos::TraceConfig * config)85 bool CreateConfigFromOptions(const ConfigOptions& options,
86                              protos::TraceConfig* config) {
87   uint64_t duration_ms = 0;
88   if (!ConvertTimeToMs(options.time, &duration_ms)) {
89     PERFETTO_ELOG("--time argument is invalid");
90     return false;
91   }
92 
93   uint64_t buffer_size_kb = 0;
94   if (!ConvertSizeToKb(options.buffer_size, &buffer_size_kb)) {
95     PERFETTO_ELOG("--buffer argument is invalid");
96     return false;
97   }
98 
99   uint64_t max_file_size_kb = 0;
100   if (!ConvertSizeToKb(options.max_file_size, &max_file_size_kb)) {
101     PERFETTO_ELOG("--size argument is invalid");
102     return false;
103   }
104 
105   std::vector<std::string> ftrace_events;
106   std::vector<std::string> atrace_categories;
107   std::vector<std::string> atrace_apps = options.atrace_apps;
108 
109   for (const auto& category : options.categories) {
110     if (category.find("/") == std::string::npos) {
111       atrace_categories.push_back(category);
112     } else {
113       ftrace_events.push_back(category);
114     }
115   }
116 
117   config->set_duration_ms(static_cast<unsigned int>(duration_ms));
118   config->set_max_file_size_bytes(max_file_size_kb * 1024);
119   config->set_flush_period_ms(30 * 1000);
120   if (max_file_size_kb)
121     config->set_write_into_file(true);
122   config->add_buffers()->set_size_kb(static_cast<unsigned int>(buffer_size_kb));
123   auto* ds_config = config->add_data_sources()->mutable_config();
124   ds_config->set_name("linux.ftrace");
125   for (const auto& evt : ftrace_events)
126     ds_config->mutable_ftrace_config()->add_ftrace_events(evt);
127   for (const auto& cat : atrace_categories)
128     ds_config->mutable_ftrace_config()->add_atrace_categories(cat);
129   for (const auto& app : atrace_apps)
130     ds_config->mutable_ftrace_config()->add_atrace_apps(app);
131 
132   auto* ps_config = config->add_data_sources()->mutable_config();
133   ps_config->set_name("linux.process_stats");
134   ps_config->set_target_buffer(0);
135 
136   return true;
137 }
138 
139 }  // namespace perfetto
140