blob: 4bdd0d4c0dc024ae933f3e9f9d70bb9af82be9a6 [file] [log] [blame] [edit]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "vm_tools/concierge/tracing.h"
#include <utility>
#include "base/logging.h"
#include "perfetto/perfetto.h"
PERFETTO_TRACK_EVENT_STATIC_STORAGE_IN_NAMESPACE(vm_tools::concierge);
namespace vm_tools::concierge {
namespace {
// We have to guess what the TraceConfig given to traced will eventually be.
// Empirically it is sufficient to just listen for all non-debug track events.
perfetto::TraceConfig GetConfig() {
perfetto::TraceConfig trace_cfg;
// This buffer should be large enough to hold whatever traces get generated
// before perfetto is done connecting.
trace_cfg.add_buffers()->set_size_kb(1024);
perfetto::DataSourceConfig* source_cfg =
trace_cfg.add_data_sources()->mutable_config();
// Include events for non-debug tracks.
source_cfg->set_name("track_event");
perfetto::protos::gen::TrackEventConfig te_cfg;
te_cfg.add_enabled_categories(kCategory);
// For some reason track event configs must be added as raw string protos...
source_cfg->set_track_event_config_raw(te_cfg.SerializeAsString());
return trace_cfg;
}
} // namespace
void InitTracing() {
perfetto::TracingInitArgs args;
// Concierge is a CrOS daemon, we make use of the system traced instance which
// runs on test images. This facilitates comparing concierge events to other
// system-generated events.
args.backends |= perfetto::kSystemBackend;
perfetto::Tracing::Initialize(args);
if (!::vm_tools::concierge::TrackEvent::Register()) {
LOG(ERROR) << "Failed to set up tracing";
return;
}
// Tracing with a system daemon doesn't *actually* begin until an asynchronous
// handshake between the provider and traced occurs. The intended workaround
// for this is to create a "startup trace" client which we emit to initially.
perfetto::Tracing::SetupStartupTracingOpts startup_tracing_opts{
.backend = perfetto::kSystemBackend,
.on_setup =
[](perfetto::Tracing::OnStartupTracingSetupCallbackArgs args) {
LOG(INFO) << "Finished setting up traces with "
<< args.num_data_sources_started << " sources.";
},
.on_aborted = []() { LOG(WARNING) << "Startup traces aborted"; },
.on_adopted = []() { LOG(INFO) << "Startup traces adopted"; },
};
// TODO(b/296025701): We need to block because we want to trace startup, which
// is also blocking. If startup goes to async we can do this async too (as
// long as we do it first).
perfetto::Tracing::SetupStartupTracingBlocking(
GetConfig(), std::move(startup_tracing_opts));
LOG_IF(WARNING, !TRACE_EVENT_CATEGORY_ENABLED(kCategory))
<< "Setting up startup traces failed for " << kCategory
<< ", initialization trace data will be lost";
}
} // namespace vm_tools::concierge