|  | /* | 
|  | * Copyright (C) 2022 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 startup tracing with a custom data source. | 
|  | // Startup tracing can work only with kSystemBackend. Before running | 
|  | // this example, `traced` must already be running in a separate process. | 
|  |  | 
|  | // Run system tracing: ninja -C out/default/ traced && ./out/default/traced | 
|  | // And then run this example: ninja -C out/default example_startup_trace && | 
|  | //                            ./out/default/example_startup_trace | 
|  |  | 
|  | #if defined(PERFETTO_SDK_EXAMPLE_USE_INTERNAL_HEADERS) | 
|  | #include "perfetto/tracing.h" | 
|  | #include "perfetto/tracing/core/data_source_descriptor.h" | 
|  | #include "perfetto/tracing/core/trace_config.h" | 
|  | #include "perfetto/tracing/data_source.h" | 
|  | #include "perfetto/tracing/tracing.h" | 
|  | #include "protos/perfetto/trace/test_event.pbzero.h" | 
|  | #else | 
|  | #include <perfetto.h> | 
|  | #endif | 
|  |  | 
|  | #include <fstream> | 
|  | #include <iostream> | 
|  | #include <thread> | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | // 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> {}; | 
|  |  | 
|  | 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, because the in-process | 
|  | // backend doesn't support startup tracing. | 
|  | args.backends = perfetto::kSystemBackend; | 
|  | 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.startup_trace"); | 
|  | CustomDataSource::Register(dsd); | 
|  | } | 
|  |  | 
|  | // The trace config defines which types of data sources are enabled for | 
|  | // recording. | 
|  | perfetto::TraceConfig GetTraceConfig() { | 
|  | 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.startup_trace"); | 
|  | return cfg; | 
|  | } | 
|  |  | 
|  | void StartStartupTracing() { | 
|  | perfetto::Tracing::SetupStartupTracingOpts args; | 
|  | args.backend = perfetto::kSystemBackend; | 
|  | perfetto::Tracing::SetupStartupTracingBlocking(GetTraceConfig(), args); | 
|  | } | 
|  |  | 
|  | std::unique_ptr<perfetto::TracingSession> StartTracing() { | 
|  | auto tracing_session = perfetto::Tracing::NewTrace(); | 
|  | tracing_session->Setup(GetTraceConfig()); | 
|  | 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; | 
|  | const char* filename = "example_startup_trace.pftrace"; | 
|  | output.open(filename, std::ios::out | std::ios::binary); | 
|  | output.write(trace_data.data(), | 
|  | static_cast<std::streamsize>(trace_data.size())); | 
|  | output.close(); | 
|  | PERFETTO_LOG( | 
|  | "Trace written in %s file. To read this trace in " | 
|  | "text form, run `./tools/traceconv text %s`", | 
|  | filename, filename); | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(CustomDataSource); | 
|  | PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(CustomDataSource); | 
|  |  | 
|  | int main(int, const char**) { | 
|  | InitializePerfetto(); | 
|  |  | 
|  | StartStartupTracing(); | 
|  |  | 
|  | // Write an event using our custom data source before starting tracing | 
|  | // session. | 
|  | CustomDataSource::Trace([](CustomDataSource::TraceContext ctx) { | 
|  | auto packet = ctx.NewTracePacket(); | 
|  | packet->set_timestamp(41); | 
|  | packet->set_for_testing()->set_str("Startup Event"); | 
|  | }); | 
|  |  | 
|  | 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("Main Event"); | 
|  | }); | 
|  | StopTracing(std::move(tracing_session)); | 
|  |  | 
|  | return 0; | 
|  | } |