0

tracing: support system backend in tracing scenarios

This change allows tracing scenarios to collect system-wide traces using
the system tracing backend (traced).

To enable this feature:

This revision adds the support of system-wide background tracing in
tracing scenarios. A tracing scenario switches to the system tracing
backend (traced) when the following conditions are all met:

1. EnablePerfettoSystemTracing is enabled: Chrome sends trace data to
the system backend.
2. EnablePerfettoSystemBackgroundTracing is enabled: this feature flag
controls whether the scenarios are allowed to use the system backend.
3 use_system_backend is set to true in the scenario config. The scenario
needs to explicitly specify that it will use the system backend.

In cases of mismatched configuration between feature flags and scenario
config:

* If the scenario requests the system backend but the feature flags
  are disabled, the scenario will be ignored (considered a server
  config error).
* If the feature flags are enabled but the scenario doesn't request the
  system backend, the default custom backend will be used.

Bug: b:388424720
Test: unit tests TracingScenarioSystemBackendTest.*
Change-Id: I33cb2f45e59194e4348a09573e2db3f44df43d60
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5581575
Reviewed-by: Eric Seckler <eseckler@chromium.org>
Reviewed-by: Etienne Pierre-Doray <etiennep@chromium.org>
Commit-Queue: Chinglin Yu <chinglinyu@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1413380}
This commit is contained in:
Chinglin Yu
2025-01-30 02:23:26 -08:00
committed by Chromium LUCI CQ
parent 0187c35235
commit 6e02296d22
13 changed files with 461 additions and 22 deletions

@ -39,12 +39,12 @@ perfetto::TraceConfig GetDefaultTraceConfig(
MockProducer::MockProducer() = default;
MockProducer::~MockProducer() = default;
void MockProducer::Connect(PerfettoService* service,
void MockProducer::Connect(perfetto::TracingService* service,
const std::string& producer_name,
uid_t uid,
pid_t pid) {
producer_name_ = producer_name;
service_endpoint_ = service->GetService()->ConnectProducer(
service_endpoint_ = service->ConnectProducer(
this, perfetto::ClientIdentity(uid, pid), producer_name, 0,
/*in_process=*/true,
perfetto::TracingService::ProducerSMBScrapingMode::kDefault, 0, nullptr);

@ -38,7 +38,11 @@ class MockProducer : public perfetto::Producer {
MockProducer();
~MockProducer() override;
void Connect(PerfettoService* service,
inline void Connect(PerfettoService* service,
const std::string& producer_name) {
Connect(service->GetService(), producer_name);
}
void Connect(perfetto::TracingService* service,
const std::string& producer_name,
uid_t uid = 42,
pid_t pid = 1025);

@ -264,17 +264,26 @@ void AdaptDataSourceConfig(
perfetto::DataSourceConfig* config,
const std::string& chrome_config_string,
bool privacy_filtering_enabled,
perfetto::protos::gen::ChromeConfig::ClientPriority client_priority) {
perfetto::protos::gen::ChromeConfig::ClientPriority client_priority,
bool enable_system_backend = false) {
if (!config->has_target_buffer()) {
config->set_target_buffer(0);
}
auto* chrome_config = config->mutable_chrome_config();
chrome_config->set_privacy_filtering_enabled(privacy_filtering_enabled);
// There are no use case for legacy json, since this is used to adapt
// background tracing configs.
chrome_config->set_convert_to_legacy_json(false);
chrome_config->set_client_priority(client_priority);
chrome_config->set_trace_config(chrome_config_string);
// Adapt data source config if
// 1. the scenario uses the default custom backend, or
// 2. the scenario uses the system backend. Only Chrome data source should be
// adapted. Other data source names are ignored.
if (!enable_system_backend || (config->name() == "track_event" ||
config->name().starts_with("org.chromium."))) {
auto* chrome_config = config->mutable_chrome_config();
chrome_config->set_privacy_filtering_enabled(privacy_filtering_enabled);
// There are no use case for legacy json, since this is used to adapt
// background tracing configs.
chrome_config->set_convert_to_legacy_json(false);
chrome_config->set_client_priority(client_priority);
chrome_config->set_trace_config(chrome_config_string);
}
if (!config->track_event_config_raw().empty()) {
config->set_name("track_event");
@ -347,7 +356,8 @@ bool AdaptPerfettoConfigForChrome(
perfetto::TraceConfig* perfetto_config,
bool privacy_filtering_enabled,
bool enable_package_name_filter,
perfetto::protos::gen::ChromeConfig::ClientPriority client_priority) {
perfetto::protos::gen::ChromeConfig::ClientPriority client_priority,
bool enable_system_backend) {
if (perfetto_config->buffers_size() < 1) {
auto* buffer_config = perfetto_config->add_buffers();
buffer_config->set_size_kb(GetDefaultTraceBufferSize());

@ -38,7 +38,8 @@ bool COMPONENT_EXPORT(TRACING_CPP) AdaptPerfettoConfigForChrome(
bool privacy_filtering_enabled = false,
bool enable_package_name_filter = false,
perfetto::protos::gen::ChromeConfig::ClientPriority =
perfetto::protos::gen::ChromeConfig::USER_INITIATED);
perfetto::protos::gen::ChromeConfig::USER_INITIATED,
bool enable_system_backend = false);
} // namespace tracing

@ -5,9 +5,11 @@
#include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h"
#include "base/command_line.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/no_destructor.h"
#include "base/synchronization/waitable_event.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/trace_event/trace_config.h"
@ -236,12 +238,31 @@ void PerfettoTracedProcess::SetupForTesting(
}
void PerfettoTracedProcess::ResetForTesting() {
task_runner_ = nullptr;
tracing_backend_.reset();
startup_tracing_needed_ = false;
// TODO(skyostil): We only uninitialize Perfetto for now, but there may also
// be other tracing-related state which should not leak between tests.
perfetto::Tracing::ResetForTesting();
base::WaitableEvent on_reset_done;
// The tracing backend is used internally in Perfetto on the |task_runner_|
// sequence. Reset and destroy the backend on the task runner to avoid racing
// in resetting Perfetto.
auto reset_task = base::BindOnce(
[](decltype(tracing_backend_) tracing_backend,
base::WaitableEvent* on_reset_done) {
tracing_backend.reset();
// TODO(skyostil): We only uninitialize Perfetto
// for now, but there may also be other
// tracing-related state which should not leak
// between tests.
perfetto::Tracing::ResetForTesting();
on_reset_done->Signal();
},
std::move(tracing_backend_), &on_reset_done);
if (task_runner_->RunsTasksInCurrentSequence()) {
std::move(reset_task).Run();
} else {
task_runner_->PostTask(FROM_HERE, std::move(reset_task));
on_reset_done.Wait();
}
task_runner_ = nullptr;
}
void PerfettoTracedProcess::RequestStartupTracing(

@ -719,7 +719,13 @@ PerfettoTracingBackend::ConnectProducer(const ConnectProducerArgs& args) {
// Return the ProducerEndpoint to the tracing muxer, and then call
// BindProducerConnectionIfNecessary().
muxer_task_runner_->PostTask([this] { BindProducerConnectionIfNecessary(); });
muxer_task_runner_->PostTask([weak_this = weak_factory_.GetWeakPtr()] {
if (!weak_this) {
// Can be destroyed in testing.
return;
}
weak_this->BindProducerConnectionIfNecessary();
});
return producer_endpoint;
}
@ -741,7 +747,13 @@ void PerfettoTracingBackend::OnProducerConnected(
}
if (task_runner) {
task_runner->PostTask([this] { BindProducerConnectionIfNecessary(); });
task_runner->PostTask([weak_this = weak_factory_.GetWeakPtr()] {
if (!weak_this) {
// Can be destroyed in testing.
return;
}
weak_this->BindProducerConnectionIfNecessary();
});
}
}

@ -6,6 +6,7 @@
#define SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PERFETTO_TRACING_BACKEND_H_
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/task/sequenced_task_runner.h"
#include "mojo/public/cpp/bindings/remote.h"
@ -67,6 +68,8 @@ class PerfettoTracingBackend : public perfetto::TracingBackend {
scoped_refptr<base::SequencedTaskRunner> consumer_connection_task_runner_;
ConsumerConnectionFactory consumer_connection_factory_;
base::WeakPtrFactory<PerfettoTracingBackend> weak_factory_{this};
};
} // namespace tracing

@ -40,6 +40,10 @@ BASE_FEATURE(kEnablePerfettoSystemTracing,
#endif
);
BASE_FEATURE(kEnablePerfettoSystemBackgroundTracing,
"EnablePerfettoSystemBackgroundTracing",
base::FEATURE_DISABLED_BY_DEFAULT);
} // namespace features
namespace tracing {
@ -57,4 +61,10 @@ bool ShouldSetupSystemTracing() {
base::FEATURE_ENABLED_BY_DEFAULT;
}
bool SystemBackgroundTracingEnabled() {
return ShouldSetupSystemTracing() &&
base::FeatureList::IsEnabled(
features::kEnablePerfettoSystemBackgroundTracing);
}
} // namespace tracing

@ -21,6 +21,9 @@ extern const COMPONENT_EXPORT(TRACING_CPP) base::Feature
extern const COMPONENT_EXPORT(TRACING_CPP) base::Feature
kEnablePerfettoSystemTracing;
extern const COMPONENT_EXPORT(TRACING_CPP) base::Feature
kEnablePerfettoSystemBackgroundTracing;
} // namespace features
namespace tracing {
@ -30,6 +33,10 @@ namespace tracing {
// android builds).
bool COMPONENT_EXPORT(TRACING_CPP) ShouldSetupSystemTracing();
// Returns true if the system tracing backend is available for background
// tracing scenarios.
bool COMPONENT_EXPORT(TRACING_CPP) SystemBackgroundTracingEnabled();
} // namespace tracing
#endif // SERVICES_TRACING_PUBLIC_CPP_TRACING_FEATURES_H_