blob: 1cf3799fb953e0c3b52dfbe1535fa9ee8ebb779d [file] [log] [blame]
Mohit Saini0a0850b2022-07-12 15:34:33 +01001/*
2 * Copyright (C) 2022 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// This example demonstrates startup tracing with a custom data source.
18// Startup tracing can work only with kSystemBackend. Before running
19// this example, `traced` must already be running in a separate process.
20
21// Run system tracing: ninja -C out/default/ traced && ./out/default/traced
22// And then run this example: ninja -C out/default example_startup_trace &&
23// ./out/default/example_startup_trace
24
25#if defined(PERFETTO_SDK_EXAMPLE_USE_INTERNAL_HEADERS)
26#include "perfetto/tracing.h"
27#include "perfetto/tracing/core/data_source_descriptor.h"
28#include "perfetto/tracing/core/trace_config.h"
29#include "perfetto/tracing/data_source.h"
30#include "perfetto/tracing/tracing.h"
31#include "protos/perfetto/trace/test_event.pbzero.h"
32#else
33#include <perfetto.h>
34#endif
35
Mohit Saini0a0850b2022-07-12 15:34:33 +010036#include <fstream>
37#include <iostream>
38#include <thread>
39
40namespace {
41
Mohit Saini0a0850b2022-07-12 15:34:33 +010042// The definition of our custom data source. Instances of this class will be
43// automatically created and destroyed by Perfetto.
Mohit Saini23247852022-07-21 13:39:50 +010044class CustomDataSource : public perfetto::DataSource<CustomDataSource> {};
Mohit Saini0a0850b2022-07-12 15:34:33 +010045
Mohit Saini23247852022-07-21 13:39:50 +010046void InitializePerfetto() {
Mohit Saini0a0850b2022-07-12 15:34:33 +010047 perfetto::TracingInitArgs args;
48 // The backends determine where trace events are recorded. For this example we
49 // are going to use the system-wide tracing service, because the in-process
50 // backend doesn't support startup tracing.
51 args.backends = perfetto::kSystemBackend;
52 perfetto::Tracing::Initialize(args);
53
54 // Register our custom data source. Only the name is required, but other
55 // properties can be advertised too.
56 perfetto::DataSourceDescriptor dsd;
57 dsd.set_name("com.example.startup_trace");
Mohit Saini23247852022-07-21 13:39:50 +010058 CustomDataSource::Register(dsd);
Mohit Saini0a0850b2022-07-12 15:34:33 +010059}
60
61// The trace config defines which types of data sources are enabled for
62// recording.
63perfetto::TraceConfig GetTraceConfig() {
64 perfetto::TraceConfig cfg;
65 cfg.add_buffers()->set_size_kb(1024);
66 auto* ds_cfg = cfg.add_data_sources()->mutable_config();
67 ds_cfg->set_name("com.example.startup_trace");
68 return cfg;
69}
70
71void StartStartupTracing() {
72 perfetto::Tracing::SetupStartupTracingOpts args;
73 args.backend = perfetto::kSystemBackend;
Mohit Saini23247852022-07-21 13:39:50 +010074 perfetto::Tracing::SetupStartupTracingBlocking(GetTraceConfig(), args);
Mohit Saini0a0850b2022-07-12 15:34:33 +010075}
76
77std::unique_ptr<perfetto::TracingSession> StartTracing() {
78 auto tracing_session = perfetto::Tracing::NewTrace();
79 tracing_session->Setup(GetTraceConfig());
80 tracing_session->StartBlocking();
81 return tracing_session;
82}
83
84void StopTracing(std::unique_ptr<perfetto::TracingSession> tracing_session) {
85 // Flush to make sure the last written event ends up in the trace.
86 CustomDataSource::Trace(
87 [](CustomDataSource::TraceContext ctx) { ctx.Flush(); });
88
89 // Stop tracing and read the trace data.
90 tracing_session->StopBlocking();
91 std::vector<char> trace_data(tracing_session->ReadTraceBlocking());
92
93 // Write the result into a file.
94 // Note: To save memory with longer traces, you can tell Perfetto to write
95 // directly into a file by passing a file descriptor into Setup() above.
96 std::ofstream output;
97 const char* filename = "example_startup_trace.pftrace";
98 output.open(filename, std::ios::out | std::ios::binary);
Daniele Di Proietto9da9fc02022-09-05 11:01:22 +010099 output.write(trace_data.data(),
100 static_cast<std::streamsize>(trace_data.size()));
Mohit Saini0a0850b2022-07-12 15:34:33 +0100101 output.close();
102 PERFETTO_LOG(
103 "Trace written in %s file. To read this trace in "
104 "text form, run `./tools/traceconv text %s`",
105 filename, filename);
106}
107
108} // namespace
109
110PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(CustomDataSource);
111PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(CustomDataSource);
112
113int main(int, const char**) {
Mohit Saini23247852022-07-21 13:39:50 +0100114 InitializePerfetto();
Mohit Saini0a0850b2022-07-12 15:34:33 +0100115
116 StartStartupTracing();
Mohit Saini0a0850b2022-07-12 15:34:33 +0100117
118 // Write an event using our custom data source before starting tracing
119 // session.
120 CustomDataSource::Trace([](CustomDataSource::TraceContext ctx) {
121 auto packet = ctx.NewTracePacket();
122 packet->set_timestamp(41);
123 packet->set_for_testing()->set_str("Startup Event");
124 });
125
126 auto tracing_session = StartTracing();
127
128 // Write an event using our custom data source.
129 CustomDataSource::Trace([](CustomDataSource::TraceContext ctx) {
130 auto packet = ctx.NewTracePacket();
131 packet->set_timestamp(42);
132 packet->set_for_testing()->set_str("Main Event");
133 });
134 StopTracing(std::move(tracing_session));
135
136 return 0;
137}