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:

committed by
Chromium LUCI CQ

parent
0187c35235
commit
6e02296d22
content
services/tracing
@ -22,6 +22,7 @@
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "services/tracing/public/cpp/perfetto/perfetto_config.h"
|
||||
#include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h"
|
||||
#include "services/tracing/public/cpp/tracing_features.h"
|
||||
#include "third_party/perfetto/protos/perfetto/config/track_event/track_event_config.gen.h"
|
||||
|
||||
namespace content {
|
||||
@ -245,6 +246,7 @@ TracingScenario::TracingScenario(
|
||||
privacy_filtering_enabled_(enable_privacy_filter),
|
||||
is_local_scenario_(is_local_scenario),
|
||||
request_startup_tracing_(request_startup_tracing),
|
||||
use_system_backend_(config.use_system_backend()),
|
||||
trace_config_(config.trace_config()),
|
||||
scenario_delegate_(scenario_delegate) {}
|
||||
|
||||
@ -253,10 +255,13 @@ TracingScenario::~TracingScenario() = default;
|
||||
bool TracingScenario::Initialize(
|
||||
const perfetto::protos::gen::ScenarioConfig& config,
|
||||
bool enable_package_name_filter) {
|
||||
bool enable_system_backend =
|
||||
use_system_backend_ && tracing::SystemBackgroundTracingEnabled();
|
||||
if (!tracing::AdaptPerfettoConfigForChrome(
|
||||
&trace_config_, privacy_filtering_enabled_,
|
||||
enable_package_name_filter,
|
||||
perfetto::protos::gen::ChromeConfig::BACKGROUND)) {
|
||||
perfetto::protos::gen::ChromeConfig::BACKGROUND,
|
||||
enable_system_backend)) {
|
||||
return false;
|
||||
}
|
||||
for (const auto& nested_config : config.nested_scenarios()) {
|
||||
@ -318,7 +323,15 @@ void TracingScenario::GenerateMetadataProto(
|
||||
|
||||
std::unique_ptr<perfetto::TracingSession>
|
||||
TracingScenario::CreateTracingSession() {
|
||||
return perfetto::Tracing::NewTrace(perfetto::BackendType::kCustomBackend);
|
||||
// If the scenario is configured to use the system backend, the platform
|
||||
// should support it (see OnSetupTrigger()). Otherwise this is a configuration
|
||||
// error.
|
||||
DCHECK(!use_system_backend_ || tracing::SystemBackgroundTracingEnabled());
|
||||
auto backend_type =
|
||||
(use_system_backend_ && tracing::SystemBackgroundTracingEnabled())
|
||||
? perfetto::BackendType::kSystemBackend
|
||||
: perfetto::BackendType::kCustomBackend;
|
||||
return perfetto::Tracing::NewTrace(backend_type);
|
||||
}
|
||||
|
||||
void TracingScenario::SetupTracingSession() {
|
||||
@ -431,6 +444,12 @@ bool TracingScenario::OnSetupTrigger(
|
||||
const BackgroundTracingRule* triggered_rule) {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
|
||||
// Skip this scenario if it requires the system backend, but the system
|
||||
// backend is unavailable (a configuration error).
|
||||
if (use_system_backend_ && !tracing::SystemBackgroundTracingEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!scenario_delegate_->OnScenarioActive(this)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -262,6 +262,7 @@ class CONTENT_EXPORT TracingScenario : public TracingScenarioBase,
|
||||
const bool privacy_filtering_enabled_;
|
||||
const bool is_local_scenario_;
|
||||
const bool request_startup_tracing_;
|
||||
const bool use_system_backend_ = false;
|
||||
State current_state_ = State::kDisabled;
|
||||
std::vector<std::unique_ptr<BackgroundTracingRule>> setup_rules_;
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "base/test/test_proto_loader.h"
|
||||
#include "base/token.h"
|
||||
#include "base/trace_event/named_trigger.h"
|
||||
#include "build/build_config.h"
|
||||
#include "content/public/browser/background_tracing_manager.h"
|
||||
#include "content/public/test/browser_task_environment.h"
|
||||
#include "services/tracing/perfetto/test_utils.h"
|
||||
@ -20,6 +21,16 @@
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
#if BUILDFLAG(IS_POSIX)
|
||||
#include "base/files/scoped_temp_dir.h"
|
||||
#include "base/task/current_thread.h"
|
||||
#include "base/test/bind.h"
|
||||
#include "base/test/scoped_feature_list.h"
|
||||
#include "services/tracing/perfetto/system_test_utils.h"
|
||||
#include "services/tracing/public/cpp/tracing_features.h"
|
||||
#include "services/tracing/tracing_service.h"
|
||||
#endif // BUILDFLAG(IS_POSIX)
|
||||
|
||||
namespace content {
|
||||
namespace {
|
||||
|
||||
@ -771,4 +782,343 @@ TEST_F(NestedTracingScenarioTest, StopUpload) {
|
||||
tracing_scenario.current_state());
|
||||
}
|
||||
|
||||
#if BUILDFLAG(IS_POSIX)
|
||||
|
||||
const char* kSystemProbeScenarioConfig = R"pb(
|
||||
scenario_name: "test_scenario"
|
||||
setup_rules: { manual_trigger_name: "setup_trigger" }
|
||||
start_rules: { manual_trigger_name: "start_trigger" }
|
||||
stop_rules: { manual_trigger_name: "stop_trigger" }
|
||||
trace_config: { data_sources: { config: { name: "mock_data_source" } } }
|
||||
use_system_backend: true
|
||||
)pb";
|
||||
|
||||
class TracingScenarioSystemBackendTest : public testing::Test {
|
||||
public:
|
||||
static constexpr char kPerfettoConsumerSockName[] =
|
||||
"PERFETTO_CONSUMER_SOCK_NAME";
|
||||
static constexpr char kPerfettoProducerSockName[] =
|
||||
"PERFETTO_PRODUCER_SOCK_NAME";
|
||||
TracingScenarioSystemBackendTest()
|
||||
: task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP) {}
|
||||
|
||||
void TearDown() override {
|
||||
system_producer_ = nullptr;
|
||||
system_service_ = nullptr;
|
||||
traced_process_ = nullptr;
|
||||
|
||||
// Restore env variables after shutdown of the above to data races with the
|
||||
// muxer thread.
|
||||
if (saved_consumer_sock_name_) {
|
||||
ASSERT_EQ(0, setenv(kPerfettoConsumerSockName,
|
||||
saved_consumer_sock_name_->c_str(), 1));
|
||||
} else {
|
||||
ASSERT_EQ(0, unsetenv(kPerfettoConsumerSockName));
|
||||
}
|
||||
if (saved_producer_sock_name_) {
|
||||
ASSERT_EQ(0, setenv(kPerfettoProducerSockName,
|
||||
saved_producer_sock_name_->c_str(), 1));
|
||||
} else {
|
||||
ASSERT_EQ(0, unsetenv(kPerfettoConsumerSockName));
|
||||
}
|
||||
}
|
||||
|
||||
// This is not implemented as Setup() because system tracing feature flags
|
||||
// affect the behavior of PerfettoTracedProcess::SetupClientLibrary(). The
|
||||
// tests will need to enable/disable features before |traced_process| is
|
||||
// created.
|
||||
void InitTracing() {
|
||||
// The test connects to the mock system service.
|
||||
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
|
||||
system_service_ = std::make_unique<tracing::MockSystemService>(temp_dir_);
|
||||
|
||||
const auto* env_val = getenv(kPerfettoConsumerSockName);
|
||||
if (env_val) {
|
||||
saved_consumer_sock_name_ = env_val;
|
||||
}
|
||||
ASSERT_EQ(0, setenv(kPerfettoConsumerSockName,
|
||||
system_service_->consumer().c_str(), 1));
|
||||
|
||||
env_val = getenv(kPerfettoProducerSockName);
|
||||
if (env_val) {
|
||||
saved_producer_sock_name_ = env_val;
|
||||
}
|
||||
ASSERT_EQ(0, setenv(kPerfettoProducerSockName,
|
||||
system_service_->producer().c_str(), 1));
|
||||
|
||||
traced_process_ = std::make_unique<tracing::TracedProcessForTesting>(
|
||||
base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()}));
|
||||
background_tracing_manager_ =
|
||||
content::BackgroundTracingManager::CreateInstance();
|
||||
|
||||
// Connect the producer to the tracing service.
|
||||
system_producer_ = std::make_unique<tracing::MockProducer>();
|
||||
system_producer_->Connect(system_service_->GetService(), "mock_producer");
|
||||
system_producer_->RegisterDataSource("mock_data_source");
|
||||
|
||||
// Also enable the custom backend.
|
||||
static tracing::mojom::TracingService* s_service;
|
||||
s_service = &tracing_service_;
|
||||
// Check if the consumer backend is used.
|
||||
static bool* consumer_conn_created;
|
||||
consumer_conn_created = &custom_backend_consumer_conn_created_;
|
||||
auto factory = []() -> tracing::mojom::TracingService& {
|
||||
*consumer_conn_created = true;
|
||||
return *s_service;
|
||||
};
|
||||
tracing::PerfettoTracedProcess::Get().SetConsumerConnectionFactory(
|
||||
factory, base::SequencedTaskRunner::GetCurrentDefault());
|
||||
|
||||
// Reset the callback that controls whether system consumer is allowed.
|
||||
tracing::PerfettoTracedProcess::Get().SetAllowSystemTracingConsumerCallback(
|
||||
base::RepeatingCallback<bool()>());
|
||||
}
|
||||
|
||||
protected:
|
||||
// Not inheriting from TracingScenarioTest because initialization of
|
||||
// |traced_process_| depends on feature flags and environment variables.
|
||||
BrowserTaskEnvironment task_environment_;
|
||||
std::unique_ptr<tracing::TracedProcessForTesting> traced_process_;
|
||||
TestTracingScenarioDelegate delegate;
|
||||
std::unique_ptr<content::BackgroundTracingManager>
|
||||
background_tracing_manager_;
|
||||
|
||||
base::ScopedTempDir temp_dir_;
|
||||
std::unique_ptr<tracing::MockSystemService> system_service_;
|
||||
std::optional<std::string> saved_consumer_sock_name_;
|
||||
std::optional<std::string> saved_producer_sock_name_;
|
||||
std::unique_ptr<tracing::MockProducer> system_producer_;
|
||||
|
||||
tracing::PerfettoService perfetto_service_;
|
||||
tracing::TracingService tracing_service_;
|
||||
|
||||
// Set to true when a consumer connection of the custom backend is created.
|
||||
bool custom_backend_consumer_conn_created_ = false;
|
||||
};
|
||||
|
||||
// Test the system backend by creating a real Perfetto tracing service thread
|
||||
// that listens to producer and consumer sockets. Config the tracing scenario to
|
||||
// use the system backend and check from the producer that a trace session is
|
||||
// started and stopped through the system backend.
|
||||
TEST_F(TracingScenarioSystemBackendTest, StartStop) {
|
||||
base::test::ScopedFeatureList scoped_feature_list;
|
||||
scoped_feature_list.InitWithFeatures(
|
||||
/*enabled_features=*/{features::kEnablePerfettoSystemTracing,
|
||||
features::kEnablePerfettoSystemBackgroundTracing},
|
||||
/*disabled_features=*/{});
|
||||
InitTracing();
|
||||
|
||||
bool allow_system_consumer_checked = false;
|
||||
auto callback =
|
||||
base::BindLambdaForTesting([&allow_system_consumer_checked]() {
|
||||
allow_system_consumer_checked = true;
|
||||
// Allow system consumer connections. This is typically checked in
|
||||
// ChromeTracingDelegate::IsSystemWideTracingEnabled().
|
||||
return true;
|
||||
});
|
||||
tracing::PerfettoTracedProcess::Get().SetAllowSystemTracingConsumerCallback(
|
||||
std::move(callback));
|
||||
|
||||
// Create a real tracing scenario. Under the hood the system backend is used.
|
||||
auto tracing_scenario = TracingScenario::Create(
|
||||
ParseScenarioConfigFromText(kSystemProbeScenarioConfig), false, false,
|
||||
false, false, &delegate);
|
||||
|
||||
tracing_scenario->Enable();
|
||||
EXPECT_EQ(TracingScenario::State::kEnabled,
|
||||
tracing_scenario->current_state());
|
||||
EXPECT_CALL(delegate, OnScenarioActive(tracing_scenario.get()))
|
||||
.WillOnce(testing::Return(true));
|
||||
EXPECT_TRUE(base::trace_event::EmitNamedTrigger("setup_trigger"));
|
||||
EXPECT_TRUE(base::trace_event::EmitNamedTrigger("start_trigger"));
|
||||
|
||||
// Wait until the data source is started.
|
||||
base::RunLoop run_loop_start;
|
||||
EXPECT_CALL(*system_producer_.get(), OnStartDataSource(_, _))
|
||||
.WillOnce([&run_loop_start]() {
|
||||
run_loop_start.Quit();
|
||||
return true;
|
||||
});
|
||||
run_loop_start.Run();
|
||||
|
||||
// Stop tracing. Wait until the data source is stopped.
|
||||
EXPECT_TRUE(base::trace_event::EmitNamedTrigger("stop_trigger"));
|
||||
base::RunLoop run_loop_stop;
|
||||
EXPECT_CALL(*system_producer_.get(), OnStopDataSource(_, _))
|
||||
.WillOnce([&run_loop_stop]() {
|
||||
run_loop_stop.Quit();
|
||||
return true;
|
||||
});
|
||||
run_loop_stop.Run();
|
||||
|
||||
// Run until the scenario is idle.
|
||||
base::RunLoop run_loop_idle;
|
||||
EXPECT_CALL(delegate, OnScenarioIdle(tracing_scenario.get()))
|
||||
.WillOnce([&run_loop_idle]() {
|
||||
run_loop_idle.Quit();
|
||||
return true;
|
||||
});
|
||||
run_loop_idle.Run();
|
||||
|
||||
EXPECT_EQ(TracingScenario::State::kDisabled,
|
||||
tracing_scenario->current_state());
|
||||
EXPECT_TRUE(allow_system_consumer_checked);
|
||||
}
|
||||
|
||||
// Test that system consumer connections are denied.
|
||||
TEST_F(TracingScenarioSystemBackendTest, SystemConsumerNotAllowedByCallback) {
|
||||
base::test::ScopedFeatureList scoped_feature_list;
|
||||
scoped_feature_list.InitWithFeatures(
|
||||
/*enabled_features=*/{features::kEnablePerfettoSystemTracing,
|
||||
features::kEnablePerfettoSystemBackgroundTracing},
|
||||
/*disabled_features=*/{});
|
||||
InitTracing();
|
||||
|
||||
bool allow_system_consumer_checked = false;
|
||||
auto callback =
|
||||
base::BindLambdaForTesting([&allow_system_consumer_checked]() {
|
||||
allow_system_consumer_checked = true;
|
||||
return false; // Deny system consumer connection.
|
||||
});
|
||||
|
||||
tracing::PerfettoTracedProcess::Get().SetAllowSystemTracingConsumerCallback(
|
||||
std::move(callback));
|
||||
|
||||
// Create a real tracing scenario.
|
||||
auto tracing_scenario = TracingScenario::Create(
|
||||
ParseScenarioConfigFromText(kSystemProbeScenarioConfig), false, false,
|
||||
false, false, &delegate);
|
||||
|
||||
tracing_scenario->Enable();
|
||||
EXPECT_EQ(TracingScenario::State::kEnabled,
|
||||
tracing_scenario->current_state());
|
||||
EXPECT_CALL(delegate, OnScenarioActive(tracing_scenario.get()))
|
||||
.WillOnce(testing::Return(true));
|
||||
EXPECT_TRUE(base::trace_event::EmitNamedTrigger("setup_trigger"));
|
||||
EXPECT_TRUE(base::trace_event::EmitNamedTrigger("start_trigger"));
|
||||
|
||||
// The system data producer isn't used.
|
||||
EXPECT_CALL(*system_producer_.get(), OnStartDataSource(_, _)).Times(0);
|
||||
// The callback doesn't allow system consumer. The scenario won't be started.
|
||||
|
||||
tracing_scenario->Abort();
|
||||
base::RunLoop run_loop_idle;
|
||||
EXPECT_CALL(delegate, OnScenarioIdle(tracing_scenario.get()))
|
||||
.WillOnce([&run_loop_idle]() {
|
||||
run_loop_idle.Quit();
|
||||
return true;
|
||||
});
|
||||
run_loop_idle.Run();
|
||||
EXPECT_TRUE(allow_system_consumer_checked);
|
||||
// Not using the custom backend.
|
||||
EXPECT_FALSE(custom_backend_consumer_conn_created_);
|
||||
}
|
||||
|
||||
// The scenario is ignored if it requests to use the system backend, but the
|
||||
// system backend is unavailable (feature
|
||||
// "EnablePerfettoSystemBackgroundTracing" isn't enabled).
|
||||
TEST_F(TracingScenarioSystemBackendTest, FeatureNotEnabled_1) {
|
||||
base::test::ScopedFeatureList scoped_feature_list;
|
||||
scoped_feature_list.InitWithFeatures(
|
||||
/*enabled_features=*/{features::kEnablePerfettoSystemTracing},
|
||||
/*disabled_features=*/{features::kEnablePerfettoSystemBackgroundTracing});
|
||||
InitTracing();
|
||||
|
||||
// Create a real tracing scenario. The system backend isn't used.
|
||||
auto tracing_scenario = TracingScenario::Create(
|
||||
ParseScenarioConfigFromText(kSystemProbeScenarioConfig), false, false,
|
||||
false, false, &delegate);
|
||||
|
||||
tracing_scenario->Enable();
|
||||
EXPECT_EQ(TracingScenario::State::kEnabled,
|
||||
tracing_scenario->current_state());
|
||||
EXPECT_CALL(delegate, OnScenarioActive(tracing_scenario.get())).Times(0);
|
||||
EXPECT_FALSE(base::trace_event::EmitNamedTrigger("setup_trigger"));
|
||||
EXPECT_FALSE(base::trace_event::EmitNamedTrigger("start_trigger"));
|
||||
|
||||
tracing_scenario->Disable();
|
||||
EXPECT_EQ(TracingScenario::State::kDisabled,
|
||||
tracing_scenario->current_state());
|
||||
// Not using the custom backend.
|
||||
EXPECT_FALSE(custom_backend_consumer_conn_created_);
|
||||
}
|
||||
|
||||
// EnablePerfettoSystemTracing doesn't have an effect on Android. In debugging
|
||||
// (which is always true in content_unittests) system tracing is always enabled.
|
||||
// Disable this test on Android.
|
||||
#if !BUILDFLAG(IS_ANDROID)
|
||||
// The scenario is ignored if it requests to use the system backend, but the
|
||||
// system backend is unavailable (feature "EnablePerfettoSystemTracing" isn't
|
||||
// enabled).
|
||||
TEST_F(TracingScenarioSystemBackendTest, FeatureNotEnabled_2) {
|
||||
base::test::ScopedFeatureList scoped_feature_list;
|
||||
scoped_feature_list.InitWithFeatures(
|
||||
/*enabled_features=*/{features::kEnablePerfettoSystemBackgroundTracing},
|
||||
/*disabled_features=*/{features::kEnablePerfettoSystemTracing});
|
||||
|
||||
InitTracing();
|
||||
// Create a real tracing scenario. The system backend isn't used.
|
||||
auto tracing_scenario = TracingScenario::Create(
|
||||
ParseScenarioConfigFromText(kSystemProbeScenarioConfig), false, false,
|
||||
false, false, &delegate);
|
||||
|
||||
tracing_scenario->Enable();
|
||||
EXPECT_EQ(TracingScenario::State::kEnabled,
|
||||
tracing_scenario->current_state());
|
||||
EXPECT_CALL(delegate, OnScenarioActive(tracing_scenario.get())).Times(0);
|
||||
EXPECT_FALSE(base::trace_event::EmitNamedTrigger("setup_trigger"));
|
||||
EXPECT_FALSE(base::trace_event::EmitNamedTrigger("start_trigger"));
|
||||
|
||||
tracing_scenario->Disable();
|
||||
EXPECT_EQ(TracingScenario::State::kDisabled,
|
||||
tracing_scenario->current_state());
|
||||
// Not using the custom backend.
|
||||
EXPECT_FALSE(custom_backend_consumer_conn_created_);
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* kScenarioConfigWithoutSystemBackend = R"pb(
|
||||
scenario_name: "test_scenario"
|
||||
setup_rules: { manual_trigger_name: "setup_trigger" }
|
||||
start_rules: { manual_trigger_name: "start_trigger" }
|
||||
stop_rules: { manual_trigger_name: "stop_trigger" }
|
||||
trace_config: { data_sources: { config: { name: "mock_data_source" } } }
|
||||
)pb";
|
||||
|
||||
// The custom backend is used on a platform that has system background tracing
|
||||
// enabled if the scenario doesn't specify the system backend
|
||||
TEST_F(TracingScenarioSystemBackendTest, ScenarioConfigWithoutSystemBackend) {
|
||||
base::test::ScopedFeatureList scoped_feature_list;
|
||||
scoped_feature_list.InitWithFeatures(
|
||||
/*enabled_features=*/{features::kEnablePerfettoSystemTracing,
|
||||
features::kEnablePerfettoSystemBackgroundTracing},
|
||||
/*disabled_features=*/{});
|
||||
|
||||
InitTracing();
|
||||
|
||||
// Create a real tracing scenario. The system backend isn't used.
|
||||
auto tracing_scenario = TracingScenario::Create(
|
||||
ParseScenarioConfigFromText(kScenarioConfigWithoutSystemBackend), false,
|
||||
false, false, false, &delegate);
|
||||
|
||||
tracing_scenario->Enable();
|
||||
EXPECT_EQ(TracingScenario::State::kEnabled,
|
||||
tracing_scenario->current_state());
|
||||
EXPECT_CALL(delegate, OnScenarioActive(tracing_scenario.get()))
|
||||
.WillOnce(testing::Return(true));
|
||||
EXPECT_TRUE(base::trace_event::EmitNamedTrigger("setup_trigger"));
|
||||
EXPECT_TRUE(base::trace_event::EmitNamedTrigger("start_trigger"));
|
||||
|
||||
// The system data producer isn't used.
|
||||
EXPECT_CALL(*system_producer_.get(), OnStartDataSource(_, _)).Times(0);
|
||||
// Instead, the custom backend connection factory is called.
|
||||
base::test::RunUntil([&]() { return custom_backend_consumer_conn_created_; });
|
||||
|
||||
EXPECT_TRUE(base::trace_event::EmitNamedTrigger("stop_trigger"));
|
||||
// Not waiting until OnScenarioIdle because mojo of |tracing_service_| isn't
|
||||
// fully set up.
|
||||
}
|
||||
|
||||
#endif // BUILDFLAG(IS_POSIX)
|
||||
|
||||
} // namespace content
|
||||
|
@ -3146,6 +3146,7 @@ test("content_unittests") {
|
||||
"//services/network/public/cpp:test_support",
|
||||
"//services/network/public/mojom",
|
||||
"//services/service_manager/public/cpp/test:test_support",
|
||||
"//services/tracing:lib",
|
||||
"//services/tracing:test_utils",
|
||||
"//services/video_capture/public/cpp:mocks",
|
||||
"//services/video_capture/public/mojom",
|
||||
|
@ -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_
|
||||
|
Reference in New Issue
Block a user