xref: /aosp_15_r20/external/perfetto/examples/sdk/example_startup_trace.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
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 
36 #include <fstream>
37 #include <iostream>
38 #include <thread>
39 
40 namespace {
41 
42 // The definition of our custom data source. Instances of this class will be
43 // automatically created and destroyed by Perfetto.
44 class CustomDataSource : public perfetto::DataSource<CustomDataSource> {};
45 
InitializePerfetto()46 void InitializePerfetto() {
47   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");
58   CustomDataSource::Register(dsd);
59 }
60 
61 // The trace config defines which types of data sources are enabled for
62 // recording.
GetTraceConfig()63 perfetto::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 
StartStartupTracing()71 void StartStartupTracing() {
72   perfetto::Tracing::SetupStartupTracingOpts args;
73   args.backend = perfetto::kSystemBackend;
74   perfetto::Tracing::SetupStartupTracingBlocking(GetTraceConfig(), args);
75 }
76 
StartTracing()77 std::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 
StopTracing(std::unique_ptr<perfetto::TracingSession> tracing_session)84 void 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);
99   output.write(trace_data.data(),
100                static_cast<std::streamsize>(trace_data.size()));
101   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 
110 PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(CustomDataSource);
111 PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(CustomDataSource);
112 
main(int,const char **)113 int main(int, const char**) {
114   InitializePerfetto();
115 
116   StartStartupTracing();
117 
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 }
138