xref: /aosp_15_r20/external/perfetto/src/profiling/perf/event_config.h (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2019 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 #ifndef SRC_PROFILING_PERF_EVENT_CONFIG_H_
18 #define SRC_PROFILING_PERF_EVENT_CONFIG_H_
19 
20 #include <cinttypes>
21 #include <functional>
22 #include <string>
23 #include <vector>
24 
25 #include <linux/perf_event.h>
26 #include <stdint.h>
27 #include <sys/types.h>
28 #include <optional>
29 
30 #include "perfetto/base/flat_set.h"
31 #include "perfetto/tracing/core/data_source_config.h"
32 
33 #include "protos/perfetto/common/perf_events.gen.h"
34 #include "protos/perfetto/config/profiling/perf_event_config.gen.h"
35 
36 namespace perfetto {
37 namespace protos {
38 namespace gen {
39 class PerfEventConfig;
40 }  // namespace gen
41 }  // namespace protos
42 
43 namespace profiling {
44 
45 // Callstack sampling parameter for unwinding only a fraction of seen processes
46 // (without enumerating them in the config).
47 struct ProcessSharding {
48   uint32_t shard_count = 0;
49   uint32_t chosen_shard = 0;
50 };
51 
52 // Parsed allow/deny-list for filtering samples.
53 // An empty allow-list means that all targets are allowed unless explicitly
54 // denied.
55 struct TargetFilter {
56   std::vector<std::string> cmdlines;
57   std::vector<std::string> exclude_cmdlines;
58   base::FlatSet<pid_t> pids;
59   base::FlatSet<pid_t> exclude_pids;
60   std::optional<ProcessSharding> process_sharding;
61   uint32_t additional_cmdline_count = 0;
62 };
63 
64 // Describes a perf event for two purposes:
65 // * encoding the event in the perf_event_open syscall
66 // * echoing the counter's config in the trace packet defaults, so that the
67 //   parser can tell which datastream belongs to which counter.
68 // Note: It's slightly odd to decode & pass around values we don't use outside
69 // of reencoding back into a defaults proto. One option would be to carry the
70 // Timebase proto, but this won't fit with the eventual support of multiple
71 // counters, as at the proto level it'll be a distinct message from Timebase.
72 struct PerfCounter {
73   enum class Type { kBuiltinCounter, kTracepoint, kRawEvent };
74 
75   Type type = Type::kBuiltinCounter;
76 
77   // Optional config-supplied name for the counter, to identify it during
78   // trace parsing, does not affect the syscall.
79   std::string name;
80 
81   // valid if kBuiltinCounter
82   protos::gen::PerfEvents::Counter counter =
83       protos::gen::PerfEvents::PerfEvents::UNKNOWN_COUNTER;
84   // valid if kTracepoint. Example: "sched:sched_switch".
85   std::string tracepoint_name;
86   // valid if kTracepoint
87   std::string tracepoint_filter;
88 
89   // sycall-level description of the event (perf_event_attr):
90   uint32_t attr_type = 0;
91   uint64_t attr_config = 0;
92   uint64_t attr_config1 = 0;  // optional extension
93   uint64_t attr_config2 = 0;  // optional extension
94 
event_typePerfCounter95   Type event_type() const { return type; }
96 
97   static PerfCounter BuiltinCounter(std::string name,
98                                     protos::gen::PerfEvents::Counter counter,
99                                     uint32_t type,
100                                     uint64_t config);
101 
102   static PerfCounter Tracepoint(std::string name,
103                                 std::string tracepoint_name,
104                                 std::string tracepoint_filter,
105                                 uint64_t id);
106 
107   static PerfCounter RawEvent(std::string name,
108                               uint32_t type,
109                               uint64_t config,
110                               uint64_t config1,
111                               uint64_t config2);
112 };
113 
114 // Describes a single profiling configuration. Bridges the gap between the data
115 // source config proto, and the raw "perf_event_attr" structs to pass to the
116 // perf_event_open syscall.
117 class EventConfig {
118  public:
119   using tracepoint_id_fn_t =
120       std::function<uint32_t(const std::string&, const std::string&)>;
121 
122   static std::optional<EventConfig> Create(
123       const protos::gen::PerfEventConfig& pb_config,
124       const DataSourceConfig& raw_ds_config,
125       std::optional<ProcessSharding> process_sharding,
126       tracepoint_id_fn_t tracepoint_id_lookup);
127 
ring_buffer_pages()128   uint32_t ring_buffer_pages() const { return ring_buffer_pages_; }
read_tick_period_ms()129   uint32_t read_tick_period_ms() const { return read_tick_period_ms_; }
samples_per_tick_limit()130   uint64_t samples_per_tick_limit() const { return samples_per_tick_limit_; }
remote_descriptor_timeout_ms()131   uint32_t remote_descriptor_timeout_ms() const {
132     return remote_descriptor_timeout_ms_;
133   }
unwind_state_clear_period_ms()134   uint32_t unwind_state_clear_period_ms() const {
135     return unwind_state_clear_period_ms_;
136   }
max_enqueued_footprint_bytes()137   uint64_t max_enqueued_footprint_bytes() const {
138     return max_enqueued_footprint_bytes_;
139   }
sample_callstacks()140   bool sample_callstacks() const { return user_frames() || kernel_frames_; }
user_frames()141   bool user_frames() const { return IsUserFramesEnabled(unwind_mode_); }
kernel_frames()142   bool kernel_frames() const { return kernel_frames_; }
unwind_mode()143   protos::gen::PerfEventConfig::UnwindMode unwind_mode() const {
144     return unwind_mode_;
145   }
filter()146   const TargetFilter& filter() const { return target_filter_; }
perf_attr()147   perf_event_attr* perf_attr() const {
148     return const_cast<perf_event_attr*>(&perf_event_attr_);
149   }
perf_attr_followers()150   const std::vector<perf_event_attr>& perf_attr_followers() const {
151     return perf_event_followers_;
152   }
timebase_event()153   const PerfCounter& timebase_event() const { return timebase_event_; }
154 
follower_events()155   const std::vector<PerfCounter>& follower_events() const {
156     return follower_events_;
157   }
158 
target_installed_by()159   const std::vector<std::string>& target_installed_by() const {
160     return target_installed_by_;
161   }
raw_ds_config()162   const DataSourceConfig& raw_ds_config() const { return raw_ds_config_; }
163 
164  private:
165   static bool IsUserFramesEnabled(
166       const protos::gen::PerfEventConfig::UnwindMode unwind_mode);
167 
168   EventConfig(const DataSourceConfig& raw_ds_config,
169               const perf_event_attr& pe_timebase,
170               std::vector<perf_event_attr> pe_followers,
171               const PerfCounter& timebase_event,
172               std::vector<PerfCounter> follower_events,
173               bool kernel_frames,
174               protos::gen::PerfEventConfig::UnwindMode unwind_mode,
175               TargetFilter target_filter,
176               uint32_t ring_buffer_pages,
177               uint32_t read_tick_period_ms,
178               uint64_t samples_per_tick_limit,
179               uint32_t remote_descriptor_timeout_ms,
180               uint32_t unwind_state_clear_period_ms,
181               uint64_t max_enqueued_footprint_bytes,
182               std::vector<std::string> target_installed_by);
183 
184   // Parameter struct for the timebase perf_event_open syscall.
185   perf_event_attr perf_event_attr_ = {};
186 
187   std::vector<perf_event_attr> perf_event_followers_ = {};
188 
189   // Timebase event, which is already described by |perf_event_attr_|. But this
190   // additionally carries a tracepoint filter if that needs to be set via an
191   // ioctl after creating the event.
192   const PerfCounter timebase_event_;
193 
194   // Timebase event, which are already described by |perf_event_followers_|.
195   std::vector<PerfCounter> follower_events_;
196 
197   // If true, include kernel frames in sampled callstacks.
198   const bool kernel_frames_;
199 
200   // Userspace unwinding mode.
201   const protos::gen::PerfEventConfig::UnwindMode unwind_mode_;
202 
203   // Parsed allow/deny-list for filtering samples.
204   const TargetFilter target_filter_;
205 
206   // Size (in 4k pages) of each per-cpu ring buffer shared with the kernel.
207   // Must be a power of two.
208   const uint32_t ring_buffer_pages_;
209 
210   // How often the ring buffers should be read.
211   const uint32_t read_tick_period_ms_;
212 
213   // Guardrail for the amount of samples a given read attempt will extract from
214   // *each* per-cpu buffer.
215   const uint64_t samples_per_tick_limit_;
216 
217   // Timeout for proc-fd lookup.
218   const uint32_t remote_descriptor_timeout_ms_;
219 
220   // Optional period for clearing cached unwinder state. Skipped if zero.
221   const uint32_t unwind_state_clear_period_ms_;
222 
223   const uint64_t max_enqueued_footprint_bytes_;
224 
225   // Only profile target if it was installed by one of the packages given.
226   // Special values are:
227   // * "@system": installed on the system partition
228   // * "@product": installed on the product partition
229   // * "@null": sideloaded
230   const std::vector<std::string> target_installed_by_;
231 
232   // The raw data source config, as a pbzero-generated C++ class.
233   const DataSourceConfig raw_ds_config_;
234 };
235 
236 }  // namespace profiling
237 }  // namespace perfetto
238 
239 #endif  // SRC_PROFILING_PERF_EVENT_CONFIG_H_
240