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 system-wide tracing with Perfetto.
18 //
19 // 1). To use it, first build the `tracebox` and this file. The tracebox will
20 // internally build tracing service (traced, which is long running
21 // process / daemon ) and perfetto consumer client, and many other perfetto
22 // tracing related tools.
23 // `ninja -C out/default/ tracebox example_system_wide`
24 //
25 // 2). Run traced (long running process), and open another terminal tab.
26 // `./out/default/tracebox traced`
27 //
28 // 3). Run this file. This is main application to trace.
29 // `./out/default/example_system_wide`
30 //
31 // 4). Use perfetto client to start a session and record trace in a file.
32 // `./out/default/tracebox perfetto -c /tmp/trace_config.txt --txt
33 // -o /tmp/trace_output`
34 //
35 // but before running that command, put following trace config (protobuf config)
36 // in a file named `/tmp/trace_config.txt`
37 // This can also be copied from: https://pastebin.com/embed_iframe/ufmtBBuq
38 // ---------------------
39 // buffers: {
40 // size_kb: 63488
41 // }
42 // data_sources: {
43 // config {
44 // name: "track_event"
45 // }
46 // }
47 // duration_ms: 10000
48 // ---------------------
49 // After running the command above, trace will be saved in `/tmp/trace_output`
50 // file. It is a binary content. We can read it by running:
51 // `./tools/traceconv text /tmp/trace_output`
52 // Or we can use "Open Trace File" option in the perfetto UI
53 // (https://ui.perfetto.dev)
54 //
55 // Learn More:
56 // https://perfetto.dev/docs/quickstart/linux-tracing#capturing-a-trace
57
58 #include "trace_categories.h"
59
60 #include <chrono>
61 #include <condition_variable>
62 #include <fstream>
63 #include <thread>
64
65 namespace {
66
67 class Observer : public perfetto::TrackEventSessionObserver {
68 public:
Observer()69 Observer() { perfetto::TrackEvent::AddSessionObserver(this); }
~Observer()70 ~Observer() override { perfetto::TrackEvent::RemoveSessionObserver(this); }
71
OnStart(const perfetto::DataSourceBase::StartArgs &)72 void OnStart(const perfetto::DataSourceBase::StartArgs&) override {
73 std::unique_lock<std::mutex> lock(mutex);
74 cv.notify_one();
75 }
76
WaitForTracingStart()77 void WaitForTracingStart() {
78 PERFETTO_LOG("Waiting for tracing to start...");
79 std::unique_lock<std::mutex> lock(mutex);
80 cv.wait(lock, [] { return perfetto::TrackEvent::IsEnabled(); });
81 PERFETTO_LOG("Tracing started");
82 }
83
84 std::mutex mutex;
85 std::condition_variable cv;
86 };
87
InitializePerfetto()88 void InitializePerfetto() {
89 perfetto::TracingInitArgs args;
90 // The backends determine where trace events are recorded. For this example we
91 // are going to use the system-wide tracing service, so that we can see our
92 // app's events in context with system profiling information.
93 args.backends = perfetto::kSystemBackend;
94 args.enable_system_consumer = false;
95
96 perfetto::Tracing::Initialize(args);
97 perfetto::TrackEvent::Register();
98 }
99
DrawPlayer(int player_number)100 void DrawPlayer(int player_number) {
101 TRACE_EVENT("rendering", "DrawPlayer", "player_number", player_number);
102 // Sleep to simulate a long computation.
103 std::this_thread::sleep_for(std::chrono::milliseconds(500));
104 }
105
DrawGame()106 void DrawGame() {
107 TRACE_EVENT("rendering", "DrawGame");
108 DrawPlayer(1);
109 DrawPlayer(2);
110 }
111
112 } // namespace
113
main(int,const char **)114 int main(int, const char**) {
115 InitializePerfetto();
116
117 Observer observer;
118 observer.WaitForTracingStart();
119
120 // Simulate some work that emits trace events.
121 // Note that we don't start and stop tracing here; for system-wide tracing
122 // this needs to be done through the "perfetto" command line tool or the
123 // Perfetto UI (https://ui.perfetto.dev).
124 DrawGame();
125
126 // Make sure the last event is closed for this example.
127 perfetto::TrackEvent::Flush();
128
129 return 0;
130 }
131