sdk: Add example code
Add SDK example code imported from https://github.com/skyostil/perfetto-sdk-example
Change-Id: Ic3a478091575d7129e39114d4b0c4280137b5f40
diff --git a/examples/README.md b/examples/README.md
new file mode 100644
index 0000000..cc39a16
--- /dev/null
+++ b/examples/README.md
@@ -0,0 +1,5 @@
+# Perfetto examples
+
+This directory contains examples for integrating Perfetto into your projects.
+
+- Example applications using the [Perfetto SDK](sdk/README.md).
diff --git a/examples/sdk/CMakeLists.txt b/examples/sdk/CMakeLists.txt
new file mode 100644
index 0000000..fc13851
--- /dev/null
+++ b/examples/sdk/CMakeLists.txt
@@ -0,0 +1,46 @@
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+cmake_minimum_required(VERSION 3.13)
+project(perfetto-sdk-example)
+
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+find_package(Threads)
+
+# Define a static library for Perfetto. In this example, we expect the SDK
+# (perfetto.cc and perfetto.h) to live in the top level sdk/ directory.
+include_directories(../../sdk)
+add_library(perfetto STATIC ../../sdk/perfetto.cc)
+
+# Link the library to the main executables.
+add_executable(example example.cc trace_categories.cc)
+add_executable(example_system_wide example_system_wide.cc
+ trace_categories.cc)
+add_executable(example_custom_data_source example_custom_data_source.cc)
+
+target_link_libraries(example perfetto
+ ${CMAKE_THREAD_LIBS_INIT})
+target_link_libraries(example_system_wide perfetto
+ ${CMAKE_THREAD_LIBS_INIT})
+target_link_libraries(example_custom_data_source perfetto
+ ${CMAKE_THREAD_LIBS_INIT})
+
+# On Android we also need the logging library.
+if (ANDROID)
+ target_link_libraries(example log)
+ target_link_libraries(example_system_wide log)
+ target_link_libraries(example_custom_data_source log)
+endif (ANDROID)
\ No newline at end of file
diff --git a/examples/sdk/README.md b/examples/sdk/README.md
new file mode 100644
index 0000000..2fba4b6
--- /dev/null
+++ b/examples/sdk/README.md
@@ -0,0 +1,129 @@
+# Perfetto SDK example project
+
+This directory contains an example project using the [Perfetto
+SDK](https://perfetto.dev/docs/instrumentation/tracing-sdk). It demonstrates
+how to instrument your application with track events to give more context in
+developing, debugging and performance analysis.
+
+Dependencies:
+
+- [CMake](https://cmake.org/)
+- C++11
+
+## Building
+
+First, check out the latest Perfetto release:
+
+```bash
+git clone https://android.googlesource.com/platform/external/perfetto -b v4.0
+```
+
+Then, build using CMake:
+
+```bash
+cd perfetto/examples/sdk
+cmake -B build
+cmake --build build
+```
+
+## Track event example
+
+The [basic example](example.cc) shows how to instrument an app with track
+events. Run it with:
+
+```bash
+build/example
+```
+
+The program will create a trace file in `example.pftrace`, which can be
+directly opened in the [Perfetto UI](https://ui.perfetto.dev). The result
+should look like this:
+
+
+
+## System-wide example
+
+While the above example only records events from the program itself, with
+Perfetto it's also possible to combine app trace events with system-wide
+profiling data (e.g., ftrace on Linux). The repository has a [second
+example](example_system_wide.cc) which demonstrates this on Android.
+
+Requirements:
+- [Android NDK](https://developer.android.com/ndk)
+- A device running Android Pie or newer
+
+> Tip: It's also possible to sideload Perfetto on pre-Pie Android devices.
+> See the [build
+> instructions](https://perfetto.dev/docs/contributing/build-instructions).
+
+To build:
+
+```bash
+export NDK=/path/to/ndk
+cmake -DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake \
+ -B build_android
+cmake --build build_android
+```
+
+Next, plug in an Android device into a USB port, download the example and run
+it while simultaneously recording a trace using the `perfetto` command line
+tool:
+
+```bash
+adb push build_android/example_system_wide ../system_wide_trace_cfg.pbtxt \
+ /data/local/tmp/
+adb shell "\
+ cd /data/local/tmp; \
+ rm -f /data/misc/perfetto-traces/example_system_wide.pftrace; \
+ cat system_wide_trace_cfg.pbtxt | \
+ perfetto --config - --txt --background \
+ -o /data/misc/perfetto-traces/example_system_wide.pftrace; \
+ ./example_system_wide"
+```
+
+Finally, retrieve the resulting trace:
+
+```bash
+adb pull /data/misc/perfetto-traces/example_system_wide.pftrace
+```
+
+When opened in the Perfetto UI, the trace now shows additional contextual
+information such as CPU frequencies and kernel scheduler information.
+
+
+
+> Tip: You can generate a new trace config with additional data sources using
+> the [Perfetto UI](https://ui.perfetto.dev/#!/record) and replace
+> `system_wide_trace_cfg.pbtxt` with the [generated config](
+> https://ui.perfetto.dev/#!/record?p=instructions).
+
+## Custom data source example
+
+The [final example](example_custom_data_source.cc) shows how to use an
+application defined data source to emit custom, strongly typed data into a
+trace. Run it with:
+
+```bash
+build/example_custom_data_source
+```
+
+The program generates a trace file in `example_custom_data_source.pftrace`,
+which we can examine using Perfetto's `trace_to_text` tool to show the trace
+packet written by the custom data source:
+
+```bash
+trace_to_text text example_custom_data_source.pftrace
+...
+packet {
+ trusted_uid: 0
+ timestamp: 42
+ trusted_packet_sequence_id: 2
+ previous_packet_dropped: true
+ for_testing {
+ str: "Hello world!"
+ }
+}
+...
+```
\ No newline at end of file
diff --git a/examples/sdk/example.cc b/examples/sdk/example.cc
new file mode 100644
index 0000000..a1898d2
--- /dev/null
+++ b/examples/sdk/example.cc
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// This example demonstrates in-process tracing with Perfetto.
+
+#include "trace_categories.h"
+
+#include <chrono>
+#include <fstream>
+#include <thread>
+
+void InitializePerfetto() {
+ perfetto::TracingInitArgs args;
+ // The backends determine where trace events are recorded. For this example we
+ // are going to use the in-process tracing service, which only includes in-app
+ // events.
+ args.backends = perfetto::kInProcessBackend;
+
+ perfetto::Tracing::Initialize(args);
+ perfetto::TrackEvent::Register();
+}
+
+std::unique_ptr<perfetto::TracingSession> StartTracing() {
+ // The trace config defines which types of data sources are enabled for
+ // recording. In this example we just need the "track_event" data source,
+ // which corresponds to the TRACE_EVENT trace points.
+ perfetto::TraceConfig cfg;
+ cfg.add_buffers()->set_size_kb(1024);
+ auto* ds_cfg = cfg.add_data_sources()->mutable_config();
+ ds_cfg->set_name("track_event");
+
+ auto tracing_session = perfetto::Tracing::NewTrace();
+ tracing_session->Setup(cfg);
+ tracing_session->StartBlocking();
+ return tracing_session;
+}
+
+void StopTracing(std::unique_ptr<perfetto::TracingSession> tracing_session) {
+ // Make sure the last event is closed for this example.
+ perfetto::TrackEvent::Flush();
+
+ // Stop tracing and read the trace data.
+ tracing_session->StopBlocking();
+ std::vector<char> trace_data(tracing_session->ReadTraceBlocking());
+
+ // Write the result into a file.
+ // Note: To save memory with longer traces, you can tell Perfetto to write
+ // directly into a file by passing a file descriptor into Setup() above.
+ std::ofstream output;
+ output.open("example.pftrace", std::ios::out | std::ios::binary);
+ output.write(&trace_data[0], trace_data.size());
+ output.close();
+}
+
+void DrawPlayer(int player_number) {
+ TRACE_EVENT("rendering", "DrawPlayer", "player_number", player_number);
+ // Sleep to simulate a long computation.
+ std::this_thread::sleep_for(std::chrono::milliseconds(500));
+}
+
+void DrawGame() {
+ TRACE_EVENT("rendering", "DrawGame");
+ DrawPlayer(1);
+ DrawPlayer(2);
+}
+
+int main(int, const char**) {
+ InitializePerfetto();
+ auto tracing_session = StartTracing();
+
+ // Simulate some work that emits trace events.
+ DrawGame();
+
+ StopTracing(std::move(tracing_session));
+ return 0;
+}
diff --git a/examples/sdk/example.png b/examples/sdk/example.png
new file mode 100644
index 0000000..4246216
--- /dev/null
+++ b/examples/sdk/example.png
Binary files differ
diff --git a/examples/sdk/example_custom_data_source.cc b/examples/sdk/example_custom_data_source.cc
new file mode 100644
index 0000000..2d475c1
--- /dev/null
+++ b/examples/sdk/example_custom_data_source.cc
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// This example demonstrates a custom tracing data source.
+
+#include <perfetto.h>
+
+#include <fstream>
+#include <thread>
+
+// The definition of our custom data source. Instances of this class will be
+// automatically created and destroyed by Perfetto.
+class CustomDataSource : public perfetto::DataSource<CustomDataSource> {
+ public:
+ void OnSetup(const SetupArgs&) override {
+ // Use this callback to apply any custom configuration to your data source
+ // based on the TraceConfig in SetupArgs.
+ }
+
+ // Optional callbacks for tracking the lifecycle of the data source.
+ void OnStart(const StartArgs&) override {}
+ void OnStop(const StopArgs&) override {}
+};
+
+PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(CustomDataSource);
+PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(CustomDataSource);
+
+void InitializePerfetto() {
+ perfetto::TracingInitArgs args;
+ // The backends determine where trace events are recorded. For this example we
+ // are going to use the in-process tracing service, which only includes in-app
+ // events.
+ args.backends = perfetto::kInProcessBackend;
+ perfetto::Tracing::Initialize(args);
+
+ // Register our custom data source. Only the name is required, but other
+ // properties can be advertised too.
+ perfetto::DataSourceDescriptor dsd;
+ dsd.set_name("com.example.custom_data_source");
+ CustomDataSource::Register(dsd);
+}
+
+std::unique_ptr<perfetto::TracingSession> StartTracing() {
+ // The trace config defines which types of data sources are enabled for
+ // recording. In this example we enable the custom data source we registered
+ // above.
+ perfetto::TraceConfig cfg;
+ cfg.add_buffers()->set_size_kb(1024);
+ auto* ds_cfg = cfg.add_data_sources()->mutable_config();
+ ds_cfg->set_name("com.example.custom_data_source");
+
+ auto tracing_session = perfetto::Tracing::NewTrace();
+ tracing_session->Setup(cfg);
+ tracing_session->StartBlocking();
+ return tracing_session;
+}
+
+void StopTracing(std::unique_ptr<perfetto::TracingSession> tracing_session) {
+ // Flush to make sure the last written event ends up in the trace.
+ CustomDataSource::Trace(
+ [](CustomDataSource::TraceContext ctx) { ctx.Flush(); });
+
+ // Stop tracing and read the trace data.
+ tracing_session->StopBlocking();
+ std::vector<char> trace_data(tracing_session->ReadTraceBlocking());
+
+ // Write the result into a file.
+ // Note: To save memory with longer traces, you can tell Perfetto to write
+ // directly into a file by passing a file descriptor into Setup() above.
+ std::ofstream output;
+ output.open("example_custom_data_source.pftrace",
+ std::ios::out | std::ios::binary);
+ output.write(&trace_data[0], trace_data.size());
+ output.close();
+}
+
+int main(int, const char**) {
+ InitializePerfetto();
+ auto tracing_session = StartTracing();
+
+ // Write an event using our custom data source.
+ CustomDataSource::Trace([](CustomDataSource::TraceContext ctx) {
+ auto packet = ctx.NewTracePacket();
+ packet->set_timestamp(42);
+ packet->set_for_testing()->set_str("Hello world!");
+ });
+
+ StopTracing(std::move(tracing_session));
+ return 0;
+}
diff --git a/examples/sdk/example_system_wide.cc b/examples/sdk/example_system_wide.cc
new file mode 100644
index 0000000..f755d37
--- /dev/null
+++ b/examples/sdk/example_system_wide.cc
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// This example demonstrates system-wide tracing with Perfetto.
+
+#include "trace_categories.h"
+
+#include <chrono>
+#include <fstream>
+#include <thread>
+
+void InitializePerfetto() {
+ perfetto::TracingInitArgs args;
+ // The backends determine where trace events are recorded. For this example we
+ // are going to use the system-wide tracing service, so that we can see our
+ // app's events in context with system profiling information.
+ args.backends = perfetto::kSystemBackend;
+
+ perfetto::Tracing::Initialize(args);
+ perfetto::TrackEvent::Register();
+}
+
+void WaitForTracingStart() {
+ PERFETTO_LOG("Waiting for tracing to start...");
+ while (!TRACE_EVENT_CATEGORY_ENABLED("rendering")) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ }
+ PERFETTO_LOG("Tracing started");
+}
+
+void DrawPlayer(int player_number) {
+ TRACE_EVENT("rendering", "DrawPlayer", "player_number", player_number);
+ // Sleep to simulate a long computation.
+ std::this_thread::sleep_for(std::chrono::milliseconds(500));
+}
+
+void DrawGame() {
+ TRACE_EVENT("rendering", "DrawGame");
+ DrawPlayer(1);
+ DrawPlayer(2);
+}
+
+int main(int, const char**) {
+ InitializePerfetto();
+ WaitForTracingStart();
+
+ // Simulate some work that emits trace events.
+ // Note that we don't start and stop tracing here; for system-wide tracing
+ // this needs to be done through the "perfetto" command line tool or the
+ // Perfetto UI (https://ui.perfetto.dev).
+ DrawGame();
+
+ // Make sure the last event is closed for this example.
+ perfetto::TrackEvent::Flush();
+
+ return 0;
+}
diff --git a/examples/sdk/example_system_wide.png b/examples/sdk/example_system_wide.png
new file mode 100644
index 0000000..7aa4dbc
--- /dev/null
+++ b/examples/sdk/example_system_wide.png
Binary files differ
diff --git a/examples/sdk/system_wide_trace_cfg.pbtxt b/examples/sdk/system_wide_trace_cfg.pbtxt
new file mode 100644
index 0000000..c9b5bdd
--- /dev/null
+++ b/examples/sdk/system_wide_trace_cfg.pbtxt
@@ -0,0 +1,47 @@
+buffers: {
+ size_kb: 8960
+ fill_policy: DISCARD
+}
+data_sources: {
+ config {
+ name: "linux.process_stats"
+ target_buffer: 1
+ process_stats_config {
+ scan_all_processes_on_start: true
+ }
+ }
+}
+data_sources: {
+ config {
+ name: "linux.sys_stats"
+ sys_stats_config {
+ stat_period_ms: 1000
+ stat_counters: STAT_CPU_TIMES
+ stat_counters: STAT_FORK_COUNT
+ }
+ }
+}
+data_sources: {
+ config {
+ name: "linux.ftrace"
+ ftrace_config {
+ ftrace_events: "sched/sched_switch"
+ ftrace_events: "power/suspend_resume"
+ ftrace_events: "sched/sched_wakeup"
+ ftrace_events: "sched/sched_wakeup_new"
+ ftrace_events: "sched/sched_waking"
+ ftrace_events: "power/cpu_frequency"
+ ftrace_events: "power/cpu_idle"
+ ftrace_events: "sched/sched_process_exit"
+ ftrace_events: "sched/sched_process_free"
+ ftrace_events: "task/task_newtask"
+ ftrace_events: "task/task_rename"
+ }
+ }
+}
+data_sources: {
+ config {
+ name: "track_event"
+ }
+}
+duration_ms: 5000
diff --git a/examples/sdk/trace_categories.cc b/examples/sdk/trace_categories.cc
new file mode 100644
index 0000000..cce90f8
--- /dev/null
+++ b/examples/sdk/trace_categories.cc
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "trace_categories.h"
+
+// Reserves internal static storage for our tracing categories.
+PERFETTO_TRACK_EVENT_STATIC_STORAGE();
\ No newline at end of file
diff --git a/examples/sdk/trace_categories.h b/examples/sdk/trace_categories.h
new file mode 100644
index 0000000..c2dd852
--- /dev/null
+++ b/examples/sdk/trace_categories.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TRACE_CATEGORIES_H
+#define TRACE_CATEGORIES_H
+
+#include <perfetto.h>
+
+// The set of track event categories that the example is using.
+PERFETTO_DEFINE_CATEGORIES(
+ perfetto::Category("rendering")
+ .SetDescription("Rendering and graphics events"),
+ perfetto::Category("network.debug")
+ .SetTags("debug")
+ .SetDescription("Verbose network events"),
+ perfetto::Category("audio.latency")
+ .SetTags("verbose")
+ .SetDescription("Detailed audio latency metrics"));
+
+#endif // TRACE_CATEGORIES_H