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