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