xref: /aosp_15_r20/external/perfetto/docs/concepts/config.md (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1# Trace configuration
2
3Unlike many always-on logging systems (e.g. Linux's rsyslog, Android's logcat),
4in Perfetto all tracing data sources are idle by default and record data only
5when instructed to do so.
6
7Data sources record data only when one (or more) tracing sessions are active. A
8tracing session is started by invoking the `perfetto` cmdline client and passing
9a config (see QuickStart guide for
10[Android](/docs/quickstart/android-tracing.md),
11[Linux](/docs/quickstart/linux-tracing.md), or
12[Chrome on desktop](/docs/quickstart/chrome-tracing.md)).
13
14A simple trace config looks like this:
15
16```protobuf
17duration_ms: 10000
18
19buffers {
20  size_kb: 65536
21  fill_policy: RING_BUFFER
22}
23
24data_sources {
25  config {
26    name: "linux.ftrace"
27    target_buffer: 0
28    ftrace_config {
29      ftrace_events: "sched_switch"
30      ftrace_events: "sched_wakeup"
31    }
32  }
33}
34
35```
36
37And is used as follows:
38
39```bash
40perfetto --txt -c config.pbtx -o trace_file.perfetto-trace
41```
42
43TIP: Some more complete examples of trace configs can be found in the repo in
44[`/test/configs/`](/test/configs/).
45
46NOTE: If you are tracing on Android using adb and experiencing problems, see
47[the Android section](#android) below.
48
49## TraceConfig
50
51The TraceConfig is a protobuf message
52([reference docs](/docs/reference/trace-config-proto.autogen)) that defines:
53
541. The general behavior of the whole tracing system, e.g.:
55
56   - The max duration of the trace.
57   - The number of in-memory buffers and their size.
58   - The max size of the output trace file.
59
602. Which data sources to enable and their configuration, e.g.:
61
62   - For the [kernel tracing data source](/docs/data-sources/cpu-scheduling.md)
63     , which ftrace events to enable.
64   - For the [heap profiler](/docs/data-sources/native-heap-profiler.md), the
65     target process name and sampling rate.
66
67   See the _data sources_ section of the docs for details on how to configure
68   the data sources bundled with Perfetto.
69
703. The `{data source} x {buffer}` mappings: which buffer each data source should
71   write into (see [buffers section](#buffers) below).
72
73The tracing service (`traced`) acts as a configuration dispatcher: it receives a
74config from the `perfetto` cmdline client (or any other
75[Consumer](/docs/concepts/service-model.md#consumer)) and forwards parts of the
76config to the various [Producers](/docs/concepts/service-model.md#producer)
77connected.
78
79When a tracing session is started by a consumer, the tracing service will:
80
81- Read the outer section of the TraceConfig (e.g. `duration_ms`, `buffers`) and
82  use that to determine its own behavior.
83- Read the list of data sources in the `data_sources` section. For each data
84  source listed in the config, if a corresponding name (`"linux.ftrace"` in the
85  example below) was registered, the service will ask the producer process to
86  start that data source, passing it the raw bytes of the [`DataSourceConfig`
87  subsection][dss] verbatim to the data source (See backward/forward compat
88  section below).
89
90![TraceConfig diagram](/docs/images/trace_config.png)
91
92[dss]: /docs/reference/trace-config-proto.autogen#DataSourceConfig
93
94## Buffers
95
96The buffer sections define the number, size and policy of the in-memory buffers
97owned by the tracing service. It looks as follows:
98
99```protobuf
100# Buffer #0
101buffers {
102  size_kb: 4096
103  fill_policy: RING_BUFFER
104}
105
106# Buffer #1
107buffers {
108  size_kb: 8192
109  fill_policy: DISCARD
110}
111```
112
113Each buffer has a fill policy which is either:
114
115- RING_BUFFER (default): the buffer behaves like a ring buffer and writes when
116  full will wrap over and replace the oldest trace data in the buffer.
117
118- DISCARD: the buffer stops accepting data once full. Further write attempts are
119  dropped.
120
121WARNING: DISCARD can have unexpected side-effect with data sources that commit
122data at the end of the trace.
123
124A trace config must define at least one buffer to be valid. In the simplest case
125all data sources will write their trace data into the same buffer.
126
127While this is fine for most basic cases, it can be problematic in cases where
128different data sources write at significantly different rates.
129
130For instance, imagine a trace config that enables both:
131
1321. The kernel scheduler tracer. On a typical Android phone this records ~10000
133   events/second, writing ~1 MB/s of trace data into the buffer.
134
1352. Memory stat polling. This data source writes the contents of /proc/meminfo
136   into the trace buffer and is configured to poll every 5 seconds, writing ~100
137   KB per poll interval.
138
139If both data sources are configured to write into the same buffer and such
140buffer is set to 4MB, most traces will contain only one memory snapshot. There
141are very good chances that most traces won't contain any memory snapshot at all,
142even if the 2nd data sources was working perfectly. This is because during the 5
143s. polling interval, the scheduler data source can end up filling the whole
144buffer, pushing the memory snapshot data out of the buffer.
145
146## Dynamic buffer mapping
147
148Data-source <> buffer mappings are dynamic in Perfetto. In the simplest case a
149tracing session can define only one buffer. By default, all data sources will
150record data into that one buffer.
151
152In cases like the example above, it might be preferable separating these data
153sources into different buffers. This can be achieved with the `target_buffer`
154field of the TraceConfig.
155
156![Buffer mapping](/docs/images/trace_config_buffer_mapping.png)
157
158Can be achieved with:
159
160```protobuf
161data_sources {
162  config {
163    name: "linux.ftrace"
164    target_buffer: 0       # <-- This goes into buffer 0.
165    ftrace_config { ... }
166  }
167}
168
169data_sources: {
170  config {
171      name: "linux.sys_stats"
172      target_buffer: 1     # <-- This goes into buffer 1.
173      sys_stats_config { ... }
174  }
175}
176
177data_sources: {
178  config {
179    name: "android.heapprofd"
180    target_buffer: 1       # <-- This goes into buffer 1 as well.
181    heapprofd_config { ... }
182  }
183}
184```
185
186## PBTX vs binary format
187
188There are two ways to pass the trace config when using the `perfetto` cmdline
189client format:
190
191#### Text format
192
193It is the preferred format for human-driven workflows and exploration. It allows
194to pass directly the text file in the PBTX (ProtoBuf TeXtual representation)
195syntax, for the schema defined in the
196[trace_config.proto](/protos/perfetto/config/trace_config.proto) (see
197[reference docs](/docs/reference/trace-config-proto.autogen))
198
199When using this mode pass the `--txt` flag to `perfetto` to indicate the config
200should be interpreted as a PBTX file:
201
202```bash
203perfetto -c /path/to/config.pbtx --txt -o trace_file.perfetto-trace
204```
205
206NOTE: The `--txt` option has been introduced only in Android 10 (Q). Older
207versions support only the binary format.
208
209WARNING: Do not use the text format for machine-to-machine interaction
210benchmark, scripts and tools) as it's more prone to breakages (e.g. if a field
211is renamed or an enum is turned into an integer)
212
213#### Binary format
214
215It is the preferred format for machine-to-machine (M2M) interaction. It involves
216passing the protobuf-encoded binary of the TraceConfig message. This can be
217obtained passing the PBTX in input to the protobuf's `protoc` compiler (which
218can be downloaded [here](https://github.com/protocolbuffers/protobuf/releases)).
219
220```bash
221cd ~/code/perfetto  # external/perfetto in the Android tree.
222
223protoc --encode=perfetto.protos.TraceConfig \
224        -I. protos/perfetto/config/perfetto_config.proto \
225        < config.txpb \
226        > config.bin
227```
228
229and then passing it to perfetto as follows, without the `--txt` argument:
230
231```bash
232perfetto -c config.bin -o trace_file.perfetto-trace
233```
234
235## {#long-traces} Streaming long traces
236
237By default Perfetto keeps the full trace buffer(s) in memory and writes it into
238the destination file (the `-o` cmdline argument) only at the end of the tracing
239session. This is to reduce the perf-intrusiveness of the tracing system. This,
240however, limits the max size of the trace to the physical memory size of the
241device, which is often too limiting.
242
243In some cases (e.g., benchmarks, hard to repro cases) it is desirable to capture
244traces that are way larger than that, at the cost of extra I/O overhead.
245
246To achieve that, Perfetto allows to periodically write the trace buffers into
247the target file (or stdout) using the following TraceConfig fields:
248
249- `write_into_file (bool)`: When true periodically drains the trace buffers into
250  the output file. When this option is enabled, the userspace buffers need to be
251  just big enough to hold tracing data between two write periods. The buffer
252  sizing depends on the activity of the device. The data rate of a typical trace
253  is ~1-4 MB/s. So a 16MB in-memory buffer can hold for up write periods of ~4
254  seconds before starting to lose data.
255
256- `file_write_period_ms (uint32)`: Overrides the default drain period (5s).
257  Shorter periods require a smaller userspace buffer but increase the
258  performance intrusiveness of tracing. If the period given is less than 100ms,
259  the tracing service will use a period of 100ms.
260
261- `max_file_size_bytes (uint64)`: If set, stops the tracing session after N
262  bytes have been written. Used to cap the size of the trace.
263
264For a complete example of a working trace config in long-tracing mode see
265[`/test/configs/long_trace.cfg`](/test/configs/long_trace.cfg).
266
267Summary: to capture a long trace just set `write_into_file:true`, set a long
268`duration_ms` and use an in-memory buffer size of 32MB or more.
269
270## Data-source specific config
271
272Alongside the trace-wide configuration parameters, the trace config also defines
273data-source-specific behaviors. At the proto schema level, this is defined in
274the `DataSourceConfig` section of `TraceConfig`:
275
276From
277[data_source_config.proto](/protos/perfetto/config/data_source_config.proto):
278
279```protobuf
280message TraceConfig {
281  ...
282  repeated DataSource data_sources = 2;  // See below.
283}
284
285message DataSource {
286  optional protos.DataSourceConfig config = 1;  // See below.
287  ...
288}
289
290message DataSourceConfig {
291  optional string name = 1;
292  ...
293  optional FtraceConfig ftrace_config = 100 [lazy = true];
294  ...
295  optional AndroidPowerConfig android_power_config = 106 [lazy = true];
296}
297```
298
299Fields like `ftrace_config`, `android_power_config` are examples of data-source
300specific configs. The tracing service will completely ignore the contents of
301those fields and route the whole DataSourceConfig object to any data source
302registered with the same name.
303
304The `[lazy=true]` marker has a special implication in the
305[protozero](/docs/design-docs/protozero.md) code generator. Unlike standard
306nested messages, it generates raw accessors (e.g.,
307`const std::string& ftrace_config_raw()` instead of
308`const protos::FtraceConfig& ftrace_config()`). This is to avoid injecting too
309many `#include` dependencies and avoiding binary size bloat in the code that
310implements data sources.
311
312#### A note on backwards/forward compatibility
313
314The tracing service will route the raw binary blob of the `DataSourceConfig`
315message to the data sources with a matching name, without attempting to decode
316and re-encode it. If the `DataSourceConfig` section of the trace config contains
317a new field that didn't exist at the time when the service was built, the
318service will still pass the `DataSourceConfig` through to the data source. This
319allows to introduced new data sources without needing the service to know
320anything about them upfront.
321
322TODO: we are aware of the fact that today extending the `DataSourceConfig` with
323a custom proto requires changing the `data_source_config.proto` in the Perfetto
324repo, which is unideal for external projects. The long-term plan is to reserve a
325range of fields for non-upstream extensions and provide generic templated
326accessors for client code. Until then, we accept patches upstream to introduce
327ad-hoc configurations for your own data sources.
328
329## Multi-process data sources
330
331Some data sources are singletons. E.g., in the case of scheduler tracing that
332Perfetto ships on Android, there is only data source for the whole system, owned
333by the `traced_probes` service.
334
335However, in the general case multiple processes can advertise the same data
336source. This is the case, for instance, when using the
337[Perfetto SDK](/docs/instrumentation/tracing-sdk.md) for userspace
338instrumentation.
339
340If this happens, when starting a tracing session that specifies that data source
341in the trace config, Perfetto by default will ask all processes that advertise
342that data source to start it.
343
344In some cases it might be desirable to further limit the enabling of the data
345source to a specific process (or set of processes). That is possible through the
346`producer_name_filter` and `producer_name_regex_filter`.
347
348NOTE: the typical Perfetto run-time model is: one process == one Perfetto
349Producer; one Producer typically hosts multiple data sources.
350
351When those filters are set, the Perfetto tracing service will activate the data
352source only in the subset of producers matching the filter.
353
354Example:
355
356```protobuf
357buffers {
358  size_kb: 4096
359}
360
361data_sources {
362  config {
363    name: "track_event"
364  }
365  # Enable the data source only on Chrome and Chrome canary.
366  producer_name_filter: "com.android.chrome"
367  producer_name_filter: "com.google.chrome.canary"
368}
369```
370
371## Triggers
372
373In nominal conditions, a tracing session has a lifecycle that simply matches the
374invocation of the `perfetto` cmdline client: trace data recording starts when
375the TraceConfig is passed to `perfetto` and ends when either the
376`TraceConfig.duration_ms` has elapsed, or when the cmdline client terminates.
377
378Perfetto supports an alternative mode of either starting or stopping the trace
379which is based on triggers. The overall idea is to declare in the trace config
380itself:
381
382- A set of triggers, which are just free-form strings.
383- Whether a given trigger should cause the trace to be started or stopped, and
384  the start/stop delay.
385
386Why using triggers? Why can't one just start perfetto or kill(SIGTERM) it when
387needed? The rationale of all this is the security model: in most Perfetto
388deployments (e.g., on Android) only privileged entities (e.g., adb shell) can
389configure/start/stop tracing. Apps are unprivileged in this sense and they
390cannot control tracing.
391
392Triggers offer a way to unprivileged apps to control, in a limited fashion, the
393lifecycle of a tracing session. The conceptual model is:
394
395- The privileged Consumer (see
396  [_Service model_](/docs/concepts/service-model.md)), i.e. the entity that is
397  normally authorized to start tracing (e.g., adb shell in Android), declares
398  upfront what are the possible trigger names for the trace and what they will
399  do.
400- Unprivileged entities (any random app process) can activate those triggers.
401  Unprivileged entities don't get a say on what the triggers will do, they only
402  communicate that an event happened.
403
404Triggers can be signaled via the cmdline util
405
406```bash
407/system/bin/trigger_perfetto "trigger_name"
408```
409
410(or also by starting an independent trace session which uses only the
411`activate_triggers: "trigger_name"` field in the config)
412
413There are two types of triggers:
414
415#### Start triggers
416
417Start triggers allow activating a tracing session only after some significant
418event has happened. Passing a trace config that has `START_TRACING` trigger
419causes the tracing session to stay idle (i.e. not recording any data) until
420either the trigger is hit or the `trigger_timeout_ms` timeout is hit.
421
422`trace_duration_ms` and triggered traces can not be used at the same time.
423
424Example config:
425
426```protobuf
427# If the "myapp_is_slow" is hit, the trace starts recording data and will be
428# stopped after 5s.
429trigger_config {
430  trigger_mode: START_TRACING
431  triggers {
432    name: "myapp_is_slow"
433    stop_delay_ms: 5000
434  }
435  # If no trigger is hit, the trace will end without having recorded any data
436  # after 30s.
437  trigger_timeout_ms: 30000
438}
439
440# The rest of the config is as usual.
441buffers { ... }
442data_sources { ... }
443```
444
445#### Stop triggers
446
447STOP_TRACING triggers allow to prematurely finalize a trace when the trigger is
448hit. In this mode the trace starts immediately when the `perfetto` client is
449invoked (like in nominal cases). The trigger acts as a premature finalization
450signal.
451
452This can be used to use perfetto in flight-recorder mode. By starting a trace
453with buffers configured in `RING_BUFFER` mode and `STOP_TRACING` triggers, the
454trace will be recorded in a loop and finalized when the culprit event is
455detected. This is key for events where the root cause is in the recent past
456(e.g., the app detects a slow scroll or a missing frame).
457
458Example config:
459
460```protobuf
461# If no trigger is hit, the trace will end after 30s.
462trigger_timeout_ms: 30000
463
464# If the "missed_frame" is hit, the trace is stopped after 1s.
465trigger_config {
466  trigger_mode: STOP_TRACING
467  triggers {
468    name: "missed_frame"
469    stop_delay_ms: 1000
470  }
471}
472
473# The rest of the config is as usual.
474buffers { ... }
475data_sources { ... }
476```
477
478## Android
479
480On Android, there are some caveats around using `adb shell`
481
482- Ctrl+C, which normally causes a graceful termination of the trace, is not
483  propagated by ADB when using `adb shell perfetto` but only when using an
484  interactive PTY-based session via `adb shell`.
485- On non-rooted devices before Android 12, the config can only be passed as
486  `cat config | adb shell perfetto -c -` (-: stdin) because of over-restrictive
487  SELinux rules. Since Android 12 `/data/misc/perfetto-configs` can be used for
488  storing configs.
489- On devices before Android 10, adb cannot directly pull
490  `/data/misc/perfetto-traces`. Use
491  `adb shell cat /data/misc/perfetto-traces/trace > trace` to work around.
492- When capturing longer traces, e.g. in the context of benchmarks or CI, use
493  `PID=$(perfetto --background)` and then `kill $PID` to stop.
494
495## Other resources
496
497- [TraceConfig Reference](/docs/reference/trace-config-proto.autogen)
498- [Buffers and dataflow](/docs/concepts/buffers.md)
499