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 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 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