1 /*
2 * Copyright (C) 2020 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 a custom tracing data source.
18
19 #include <perfetto.h>
20
21 #include <fstream>
22 #include <thread>
23
24 // The definition of our custom data source. Instances of this class will be
25 // automatically created and destroyed by Perfetto.
26 class CustomDataSource : public perfetto::DataSource<CustomDataSource> {
27 public:
OnSetup(const SetupArgs &)28 void OnSetup(const SetupArgs&) override {
29 // Use this callback to apply any custom configuration to your data source
30 // based on the TraceConfig in SetupArgs.
31 }
32
33 // Optional callbacks for tracking the lifecycle of the data source.
OnStart(const StartArgs &)34 void OnStart(const StartArgs&) override {}
OnStop(const StopArgs &)35 void OnStop(const StopArgs&) override {}
36 };
37
38 PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(CustomDataSource);
39 PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(CustomDataSource);
40
InitializePerfetto()41 void InitializePerfetto() {
42 perfetto::TracingInitArgs args;
43 // The backends determine where trace events are recorded. For this example we
44 // are going to use the in-process tracing service, which only includes in-app
45 // events.
46 args.backends = perfetto::kInProcessBackend;
47 perfetto::Tracing::Initialize(args);
48
49 // Register our custom data source. Only the name is required, but other
50 // properties can be advertised too.
51 perfetto::DataSourceDescriptor dsd;
52 dsd.set_name("com.example.custom_data_source");
53 CustomDataSource::Register(dsd);
54 }
55
StartTracing()56 std::unique_ptr<perfetto::TracingSession> StartTracing() {
57 // The trace config defines which types of data sources are enabled for
58 // recording. In this example we enable the custom data source we registered
59 // above.
60 perfetto::TraceConfig cfg;
61 cfg.add_buffers()->set_size_kb(1024);
62 auto* ds_cfg = cfg.add_data_sources()->mutable_config();
63 ds_cfg->set_name("com.example.custom_data_source");
64
65 auto tracing_session = perfetto::Tracing::NewTrace();
66 tracing_session->Setup(cfg);
67 tracing_session->StartBlocking();
68 return tracing_session;
69 }
70
StopTracing(std::unique_ptr<perfetto::TracingSession> tracing_session)71 void StopTracing(std::unique_ptr<perfetto::TracingSession> tracing_session) {
72 // Flush to make sure the last written event ends up in the trace.
73 CustomDataSource::Trace(
74 [](CustomDataSource::TraceContext ctx) { ctx.Flush(); });
75
76 // Stop tracing and read the trace data.
77 tracing_session->StopBlocking();
78 std::vector<char> trace_data(tracing_session->ReadTraceBlocking());
79
80 // Write the result into a file.
81 // Note: To save memory with longer traces, you can tell Perfetto to write
82 // directly into a file by passing a file descriptor into Setup() above.
83 std::ofstream output;
84 output.open("example_custom_data_source.pftrace",
85 std::ios::out | std::ios::binary);
86 output.write(&trace_data[0], trace_data.size());
87 output.close();
88 }
89
main(int,const char **)90 int main(int, const char**) {
91 InitializePerfetto();
92 auto tracing_session = StartTracing();
93
94 // Write an event using our custom data source.
95 CustomDataSource::Trace([](CustomDataSource::TraceContext ctx) {
96 auto packet = ctx.NewTracePacket();
97 packet->set_timestamp(42);
98 packet->set_for_testing()->set_str("Hello world!");
99 });
100
101 StopTracing(std::move(tracing_session));
102 return 0;
103 }
104