• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Tracing SDK
2
3The Perfetto Tracing SDK is a C++11 library that allows userspace applications
4to emit trace events and add more app-specific context to a Perfetto trace.
5
6When using the Tracing SDK there are two main aspects to consider:
7
81. Whether you are interested only in tracing events coming from your own app
9   or want to collect full-stack traces that overlay app trace events with
10   system trace events like scheduler traces, syscalls or any other Perfetto
11   data source.
12
132. For app-specific tracing, whether you need to trace simple types of timeline
14  events (e.g., slices, counters) or need to define complex data sources with a
15  custom strongly-typed schema (e.g., for dumping the state of a subsystem of
16  your app into the trace).
17
18For Android-only instrumentation, the advice is to keep using the existing
19[android.os.Trace (SDK)][atrace-sdk] / [ATrace_* (NDK)][atrace-ndk] if they
20are sufficient for your use cases. Atrace-based instrumentation is fully
21supported in Perfetto.
22See the [Data Sources -> Android System -> Atrace Instrumentation][atrace-ds]
23for details.
24
25## Getting started
26
27TIP: The code from these examples is also available [in the
28repository](/examples/sdk/README.md).
29
30To start using the Client API, first check out the latest SDK release:
31
32```bash
33git clone https://android.googlesource.com/platform/external/perfetto -b v14.0
34```
35
36The SDK consists of two files, `sdk/perfetto.h` and `sdk/perfetto.cc`. These are
37an amalgamation of the Client API designed to easy to integrate to existing
38build systems. The sources are self-contained and require only a C++11 compliant
39standard library.
40
41For example, to add the SDK to a CMake project, edit your CMakeLists.txt:
42
43```cmake
44cmake_minimum_required(VERSION 3.13)
45project(PerfettoExample)
46find_package(Threads)
47
48# Define a static library for Perfetto.
49include_directories(perfetto/sdk)
50add_library(perfetto STATIC perfetto/sdk/perfetto.cc)
51
52# Link the library to your main executable.
53add_executable(example example.cc)
54target_link_libraries(example perfetto ${CMAKE_THREAD_LIBS_INIT})
55```
56
57Next, initialize Perfetto in your program:
58
59```C++
60#include <perfetto.h>
61
62int main(int argv, char** argc) {
63  perfetto::TracingInitArgs args;
64
65  // The backends determine where trace events are recorded. You may select one
66  // or more of:
67
68  // 1) The in-process backend only records within the app itself.
69  args.backends |= perfetto::kInProcessBackend;
70
71  // 2) The system backend writes events into a system Perfetto daemon,
72  //    allowing merging app and system events (e.g., ftrace) on the same
73  //    timeline. Requires the Perfetto `traced` daemon to be running (e.g.,
74  //    on Android Pie and newer).
75  args.backends |= perfetto::kSystemBackend;
76
77  perfetto::Tracing::Initialize(args);
78}
79```
80
81You are now ready to instrument your app with trace events.
82
83## Custom data sources vs Track events
84
85The SDK offers two abstraction layers to inject tracing data, built on top of
86each other, which trade off code complexity vs expressive power:
87[track events](#track-events) and [custom data sources](#custom-data-sources).
88
89### Track events
90
91Track events are the suggested option when dealing with app-specific tracing as
92they take care of a number of subtleties (e.g., thread safety, flushing, string
93interning).
94Track events are time bounded events (e.g., slices, counter) based on simple
95`TRACE_EVENT` annotation tags in the codebase, like this:
96
97```c++
98#include <perfetto.h>
99
100PERFETTO_DEFINE_CATEGORIES(
101    perfetto::Category("rendering")
102        .SetDescription("Events from the graphics subsystem"),
103    perfetto::Category("network")
104        .SetDescription("Network upload and download statistics"));
105
106...
107
108int main(int argv, char** argc) {
109  ...
110  perfetto::Tracing::Initialize(args);
111  perfetto::TrackEvent::Register();
112}
113
114...
115
116void LayerTreeHost::DoUpdateLayers() {
117  TRACE_EVENT("rendering", "LayerTreeHost::DoUpdateLayers");
118  ...
119  for (PictureLayer& pl : layers) {
120    TRACE_EVENT("rendering", "PictureLayer::Update");
121    pl.Update();
122  }
123}
124```
125
126Which are rendered in the UI as follows:
127
128![Track event example](/docs/images/track-events.png)
129
130Track events are the best default option and serve most tracing use cases with
131very little complexity.
132
133To include your new track events in the trace, ensure that the `track_event`
134data source is included in the trace config. If you do not specify any
135categories then all non-debug categories will be included by default. However,
136you can also add just the categories you are interested in like so:
137
138```protobuf
139data_sources {
140  config {
141    name: "track_event"
142    track_event_config {
143    	enabled_categories: "rendering"
144    }
145  }
146}
147```
148
149See the [Track events page](track-events.md) for full instructions.
150
151### Custom data sources
152
153For most uses, track events are the most straightforward way of instrumenting
154apps for tracing. However, in some rare circumstances they are not
155flexible enough, e.g., when the data doesn't fit the notion of a track or is
156high volume enough that it needs a strongly typed schema to minimize the size of
157each event. In this case, you can implement a *custom data source* for
158Perfetto.
159
160Unlike track events, when working with custom data sources, you will also need
161corresponding changes in [trace processor](/docs/analysis/trace-processor.md)
162to enable importing your data format.
163
164A custom data source is a subclass of `perfetto::DataSource`. Perfetto will
165automatically create one instance of the class for each tracing session it is
166active in (usually just one).
167
168```C++
169class CustomDataSource : public perfetto::DataSource<CustomDataSource> {
170 public:
171  void OnSetup(const SetupArgs&) override {
172    // Use this callback to apply any custom configuration to your data source
173    // based on the TraceConfig in SetupArgs.
174  }
175
176  void OnStart(const StartArgs&) override {
177    // This notification can be used to initialize the GPU driver, enable
178    // counters, etc. StartArgs will contains the DataSourceDescriptor,
179    // which can be extended.
180  }
181
182  void OnStop(const StopArgs&) override {
183    // Undo any initialization done in OnStart.
184  }
185
186  // Data sources can also have per-instance state.
187  int my_custom_state = 0;
188};
189
190PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(CustomDataSource);
191```
192
193The data source's static data should be defined in one source file like this:
194
195```C++
196PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(CustomDataSource);
197```
198
199Custom data sources need to be registered with Perfetto:
200
201```C++
202int main(int argv, char** argc) {
203  ...
204  perfetto::Tracing::Initialize(args);
205  // Add the following:
206  perfetto::DataSourceDescriptor dsd;
207  dsd.set_name("com.example.custom_data_source");
208  CustomDataSource::Register(dsd);
209}
210```
211
212As with all data sources, the custom data source needs to be specified in the
213trace config to enable tracing:
214
215```C++
216perfetto::TraceConfig cfg;
217auto* ds_cfg = cfg.add_data_sources()->mutable_config();
218ds_cfg->set_name("com.example.custom_data_source");
219```
220
221Finally, call the `Trace()` method to record an event with your custom data
222source. The lambda function passed to that method will only be called if tracing
223is enabled. It is always called synchronously and possibly multiple times if
224multiple concurrent tracing sessions are active.
225
226```C++
227CustomDataSource::Trace([](CustomDataSource::TraceContext ctx) {
228  auto packet = ctx.NewTracePacket();
229  packet->set_timestamp(perfetto::TrackEvent::GetTraceTimeNs());
230  packet->set_for_testing()->set_str("Hello world!");
231});
232```
233
234If necessary the `Trace()` method can access the custom data source state
235(`my_custom_state` in the example above). Doing so, will take a mutex to
236ensure data source isn't destroyed (e.g., because of stopping tracing) while
237the `Trace()` method is called on another thread. For example:
238
239```C++
240CustomDataSource::Trace([](CustomDataSource::TraceContext ctx) {
241  auto safe_handle = trace_args.GetDataSourceLocked();  // Holds a RAII lock.
242  DoSomethingWith(safe_handle->my_custom_state);
243});
244```
245
246## In-process vs System mode
247
248The two modes are not mutually exclusive. An app can be configured to work
249in both modes and respond both to in-process tracing requests and system
250tracing requests. Both modes generate the same trace file format.
251
252### In-process mode
253
254In this mode both the perfetto service and the app-defined data sources are
255hosted fully in-process, in the same process of the profiled app. No connection
256to the system `traced` daemon will be attempted.
257
258In-process mode can be enabled by setting
259`TracingInitArgs.backends = perfetto::kInProcessBackend` when initializing the
260SDK, see examples below.
261
262This mode is used to generate traces that contain only events emitted by
263the app, but not other types of events (e.g. scheduler traces).
264
265The main advantage is that by running fully in-process, it doesn't require any
266special OS privileges and the profiled process can control the lifecycle of
267tracing sessions.
268
269This mode is supported on Android, Linux, MacOS and Windows.
270
271### System mode
272
273In this mode the app-defined data sources will connect to the external `traced`
274service using the [IPC over UNIX socket][ipc].
275
276System mode can be enabled by setting
277`TracingInitArgs.backends = perfetto::kSystemBackend` when initializing the SDK,
278see examples below.
279
280The main advantage of this mode is that it is possible to create fused traces where
281app events are overlaid on the same timeline of OS events. This enables
282full-stack performance investigations, looking all the way through syscalls and
283kernel scheduling events.
284
285The main limitation of this mode is that it requires the external `traced` daemon
286to be up and running and reachable through the UNIX socket connection.
287
288This is suggested for local debugging or lab testing scenarios where the user
289(or the test harness) can control the OS deployment (e.g., sideload binaries on
290Android).
291
292When using system mode, the tracing session must be controlled from the outside,
293using the `perfetto` command-line client
294(See [reference](/docs/reference/perfetto-cli)). This is because when collecting
295system traces, tracing data producers are not allowed to read back the trace
296data as it might disclose information about other processes and allow
297side-channel attacks.
298
299* On Android 9 (Pie) and beyond, traced is shipped as part of the platform.
300* On older versions of Android, traced can be built from sources using the
301  the [standalone NDK-based workflow](/docs/contributing/build-instructions.md)
302  and sideloaded via adb shell.
303* On Linux and MacOS `traced` must be built and run separately. See the
304  [Linux quickstart](/docs/quickstart/linux-tracing.md) for instructions.
305
306_System mode is not yet supported on Windows, due to the lack of an IPC
307implementation_.
308
309## {#recording} Recording traces through the API
310
311_Tracing through the API is currently only supported with the in-process mode.
312When using system mode, use the `perfetto` cmdline client (see quickstart
313guides)._
314
315First initialize a [TraceConfig](/docs/reference/trace-config-proto.autogen)
316message which specifies what type of data to record.
317
318If your app includes [track events](track-events.md) (i.e, `TRACE_EVENT`), you
319typically want to choose the categories which are enabled for tracing.
320
321By default, all non-debug categories are enabled, but you can enable a specific
322one like this:
323
324```C++
325perfetto::protos::gen::TrackEventConfig track_event_cfg;
326track_event_cfg.add_disabled_categories("*");
327track_event_cfg.add_enabled_categories("rendering");
328```
329
330Next, build the main trace config together with the track event part:
331
332```C++
333perfetto::TraceConfig cfg;
334cfg.add_buffers()->set_size_kb(1024);  // Record up to 1 MiB.
335auto* ds_cfg = cfg.add_data_sources()->mutable_config();
336ds_cfg->set_name("track_event");
337ds_cfg->set_track_event_config_raw(track_event_cfg.SerializeAsString());
338```
339
340If your app includes a custom data source, you can also enable it here:
341
342```C++
343ds_cfg = cfg.add_data_sources()->mutable_config();
344ds_cfg->set_name("my_data_source");
345```
346
347After building the trace config, you can begin tracing:
348
349```C++
350std::unique_ptr<perfetto::TracingSession> tracing_session(
351    perfetto::Tracing::NewTrace());
352tracing_session->Setup(cfg);
353tracing_session->StartBlocking();
354```
355
356TIP: API methods with `Blocking` in their name will suspend the calling thread
357     until the respective operation is complete. There are also asynchronous
358     variants that don't have this limitation.
359
360Now that tracing is active, instruct your app to perform the operation you
361want to record. After that, stop tracing and collect the
362protobuf-formatted trace data:
363
364```C++
365tracing_session->StopBlocking();
366std::vector<char> trace_data(tracing_session->ReadTraceBlocking());
367
368// Write the trace into a file.
369std::ofstream output;
370output.open("example.perfetto-trace", std::ios::out | std::ios::binary);
371output.write(&trace_data[0], trace_data.size());
372output.close();
373```
374
375To save memory with longer traces, you can also tell Perfetto to write
376directly into a file by passing a file descriptor into Setup(), remembering
377to close the file after tracing is done:
378
379```C++
380int fd = open("example.perfetto-trace", O_RDWR | O_CREAT | O_TRUNC, 0600);
381tracing_session->Setup(cfg, fd);
382tracing_session->StartBlocking();
383// ...
384tracing_session->StopBlocking();
385close(fd);
386```
387
388The resulting trace file can be directly opened in the [Perfetto
389UI](https://ui.perfetto.dev) or the [Trace Processor](/docs/analysis/trace-processor.md).
390
391[ipc]: /docs/design-docs/api-and-abi.md#socket-protocol
392[atrace-ds]: /docs/data-sources/atrace.md
393[atrace-ndk]: https://developer.android.com/ndk/reference/group/tracing
394[atrace-sdk]: https://developer.android.com/reference/android/os/Trace
395