Commit f7e171e3 authored by Sami Kyostila's avatar Sami Kyostila Committed by Commit Bot

services/tracing: Implement Perfetto platform

Implement Perfetto's platform abstraction layer using Chrome's
TLS and task runner primitives.

Bug: b/158460267
Change-Id: I2b2653c550db4c6bb8c8e8e325af7693d1bb496b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2248559
Commit-Queue: Sami Kyöstilä <skyostil@chromium.org>
Reviewed-by: default avatarEric Seckler <eseckler@chromium.org>
Auto-Submit: Sami Kyöstilä <skyostil@chromium.org>
Cr-Commit-Position: refs/heads/master@{#782914}
parent 412b7589
...@@ -10,12 +10,16 @@ ...@@ -10,12 +10,16 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/strings/strcat.h" #include "base/strings/strcat.h"
#include "base/test/bind_test_util.h"
#include "base/test/task_environment.h" #include "base/test/task_environment.h"
#include "base/threading/thread.h"
#include "services/tracing/perfetto/perfetto_service.h" #include "services/tracing/perfetto/perfetto_service.h"
#include "services/tracing/perfetto/producer_host.h" #include "services/tracing/perfetto/producer_host.h"
#include "services/tracing/perfetto/test_utils.h" #include "services/tracing/perfetto/test_utils.h"
#include "services/tracing/public/cpp/perfetto/perfetto_platform.h"
#include "services/tracing/public/cpp/perfetto/producer_client.h" #include "services/tracing/public/cpp/perfetto/producer_client.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/perfetto/include/perfetto/tracing/tracing.h"
#include "third_party/perfetto/protos/perfetto/common/commit_data_request.pb.h" #include "third_party/perfetto/protos/perfetto/common/commit_data_request.pb.h"
// TODO(crbug.com/961066): Fix memory leaks in tests and re-enable on LSAN. // TODO(crbug.com/961066): Fix memory leaks in tests and re-enable on LSAN.
...@@ -363,6 +367,32 @@ TEST_F(PerfettoIntegrationTest, ...@@ -363,6 +367,32 @@ TEST_F(PerfettoIntegrationTest,
(*client2)->shared_memory_for_testing()); (*client2)->shared_memory_for_testing());
} }
TEST_F(PerfettoIntegrationTest, PerfettoPlatformTest) {
auto* platform =
PerfettoTracedProcess::Get()->perfetto_platform_for_testing();
auto* tls = platform->GetOrCreateThreadLocalObject();
EXPECT_TRUE(tls);
EXPECT_EQ(tls, platform->GetOrCreateThreadLocalObject());
base::Thread thread("TestThread");
thread.Start();
thread.task_runner()->PostTask(
FROM_HERE, base::BindLambdaForTesting([&platform, &tls] {
auto* thread_tls = platform->GetOrCreateThreadLocalObject();
EXPECT_TRUE(thread_tls);
EXPECT_NE(tls, thread_tls);
}));
thread.Stop();
}
TEST_F(PerfettoIntegrationTest, PerfettoClientLibraryTest) {
PerfettoTracedProcess::Get()->SetupClientLibrary();
// Create a dummy tracing session without any active backends to check that
// the client library was initialized.
auto tracing_session = perfetto::Tracing::NewTrace();
EXPECT_TRUE(tracing_session);
}
} // namespace } // namespace
} // namespace tracing } // namespace tracing
...@@ -58,30 +58,32 @@ std::string RandomASCII(size_t length) { ...@@ -58,30 +58,32 @@ std::string RandomASCII(size_t length) {
return tmp; return tmp;
} }
class SaveSystemProducerAndScopedRestore { class ClearAndRestoreSystemProducerScope {
public: public:
SaveSystemProducerAndScopedRestore() { ClearAndRestoreSystemProducerScope() {
base::RunLoop setup_loop;
PerfettoTracedProcess::GetTaskRunner()->GetOrCreateTaskRunner()->PostTask( PerfettoTracedProcess::GetTaskRunner()->GetOrCreateTaskRunner()->PostTask(
FROM_HERE, base::BindLambdaForTesting([this] { FROM_HERE, base::BindLambdaForTesting([this, &setup_loop] {
saved_producer_ = saved_producer_ =
PerfettoTracedProcess::Get()->SetSystemProducerForTesting( PerfettoTracedProcess::Get()->SetSystemProducerForTesting(
std::make_unique<DummyProducer>( nullptr);
PerfettoTracedProcess::GetTaskRunner())); setup_loop.Quit();
})); }));
setup_loop.Run();
} }
~SaveSystemProducerAndScopedRestore() { ~ClearAndRestoreSystemProducerScope() {
base::RunLoop destroy; base::RunLoop destroy_loop;
PerfettoTracedProcess::GetTaskRunner() PerfettoTracedProcess::GetTaskRunner()->GetOrCreateTaskRunner()->PostTask(
->GetOrCreateTaskRunner() FROM_HERE,
->PostTaskAndReply( base::BindLambdaForTesting(
FROM_HERE, base::BindLambdaForTesting([this]() { [this, &destroy_loop]() {
PerfettoTracedProcess::Get() PerfettoTracedProcess::Get()
->SetSystemProducerForTesting(std::move(saved_producer_)) ->SetSystemProducerForTesting(std::move(saved_producer_))
.reset(); .reset();
}), destroy_loop.Quit();
destroy.QuitClosure()); }));
destroy.Run(); destroy_loop.Run();
} }
private: private:
...@@ -889,18 +891,10 @@ TEST_F(SystemPerfettoTest, SystemToLowAPILevel) { ...@@ -889,18 +891,10 @@ TEST_F(SystemPerfettoTest, SystemToLowAPILevel) {
TEST_F(SystemPerfettoTest, EnabledOnDebugBuilds) { TEST_F(SystemPerfettoTest, EnabledOnDebugBuilds) {
base::test::ScopedFeatureList feature_list; base::test::ScopedFeatureList feature_list;
feature_list.InitAndDisableFeature(features::kEnablePerfettoSystemTracing); feature_list.InitAndDisableFeature(features::kEnablePerfettoSystemTracing);
// We have to prevent destroying the system producer because we might have
// created it on a different task environment (wrong sequence).
SaveSystemProducerAndScopedRestore saved_system_producer;
PerfettoTracedProcess::ReconstructForTesting(producer_socket_.c_str());
if (base::android::BuildInfo::GetInstance()->is_debug_android()) { if (base::android::BuildInfo::GetInstance()->is_debug_android()) {
EXPECT_FALSE(PerfettoTracedProcess::Get() EXPECT_TRUE(ShouldSetupSystemTracing());
->system_producer()
->IsDummySystemProducerForTesting());
} else { } else {
EXPECT_TRUE(PerfettoTracedProcess::Get() EXPECT_FALSE(ShouldSetupSystemTracing());
->system_producer()
->IsDummySystemProducerForTesting());
} }
} }
#endif // defined(OS_ANDROID) #endif // defined(OS_ANDROID)
...@@ -910,27 +904,19 @@ TEST_F(SystemPerfettoTest, RespectsFeatureList) { ...@@ -910,27 +904,19 @@ TEST_F(SystemPerfettoTest, RespectsFeatureList) {
if (base::android::BuildInfo::GetInstance()->is_debug_android()) { if (base::android::BuildInfo::GetInstance()->is_debug_android()) {
// The feature list is ignored on debug android builds so we should have a // The feature list is ignored on debug android builds so we should have a
// real system producer so just bail out of this test. // real system producer so just bail out of this test.
EXPECT_FALSE(PerfettoTracedProcess::Get() EXPECT_TRUE(ShouldSetupSystemTracing());
->system_producer()
->IsDummySystemProducerForTesting());
return; return;
} }
#endif // defined(OS_ANDROID) #endif // defined(OS_ANDROID)
{ {
base::test::ScopedFeatureList feature_list; base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(features::kEnablePerfettoSystemTracing); feature_list.InitAndEnableFeature(features::kEnablePerfettoSystemTracing);
PerfettoTracedProcess::ReconstructForTesting(producer_socket_.c_str()); EXPECT_TRUE(ShouldSetupSystemTracing());
EXPECT_FALSE(PerfettoTracedProcess::Get()
->system_producer()
->IsDummySystemProducerForTesting());
} }
{ {
base::test::ScopedFeatureList feature_list; base::test::ScopedFeatureList feature_list;
feature_list.InitAndDisableFeature(features::kEnablePerfettoSystemTracing); feature_list.InitAndDisableFeature(features::kEnablePerfettoSystemTracing);
PerfettoTracedProcess::ReconstructForTesting(producer_socket_.c_str()); EXPECT_FALSE(ShouldSetupSystemTracing());
EXPECT_TRUE(PerfettoTracedProcess::Get()
->system_producer()
->IsDummySystemProducerForTesting());
} }
} }
...@@ -951,7 +937,6 @@ TEST_F(SystemPerfettoTest, RespectsFeaturePreAndroidPie) { ...@@ -951,7 +937,6 @@ TEST_F(SystemPerfettoTest, RespectsFeaturePreAndroidPie) {
feature_list.InitAndDisableFeature( feature_list.InitAndDisableFeature(
features::kEnablePerfettoSystemTracing); features::kEnablePerfettoSystemTracing);
} }
PerfettoTracedProcess::ReconstructForTesting(producer_socket_.c_str());
std::string data_source_name = "temp_name"; std::string data_source_name = "temp_name";
...@@ -1007,10 +992,26 @@ TEST_F(SystemPerfettoTest, RespectsFeaturePreAndroidPie) { ...@@ -1007,10 +992,26 @@ TEST_F(SystemPerfettoTest, RespectsFeaturePreAndroidPie) {
return system_consumer.received_test_packets(); return system_consumer.received_test_packets();
}; };
EXPECT_EQ(1u, run_test(/* enable_feature = */ true));
EXPECT_EQ(0u, run_test(/* enable_feature = */ false)); EXPECT_EQ(0u, run_test(/* enable_feature = */ false));
EXPECT_EQ(1u, run_test(/* enable_feature = */ true));
} }
#endif // defined(OS_ANDROID) #endif // defined(OS_ANDROID)
TEST_F(SystemPerfettoTest, SetupSystemTracing) {
ClearAndRestoreSystemProducerScope saved_system_producer;
EXPECT_FALSE(PerfettoTracedProcess::Get()->system_producer());
PerfettoTracedProcess::Get()->SetupSystemTracing();
EXPECT_TRUE(PerfettoTracedProcess::Get()->system_producer());
#if defined(OS_POSIX)
EXPECT_FALSE(PerfettoTracedProcess::Get()
->system_producer()
->IsDummySystemProducerForTesting());
#else // defined(OS_POSIX)
EXPECT_TRUE(PerfettoTracedProcess::Get()
->system_producer()
->IsDummySystemProducerForTesting());
#endif // defined(OS_POSIX)
}
} // namespace } // namespace
} // namespace tracing } // namespace tracing
\ No newline at end of file
...@@ -74,6 +74,8 @@ target(tracing_lib_type, "cpp") { ...@@ -74,6 +74,8 @@ target(tracing_lib_type, "cpp") {
"perfetto/java_heap_profiler/java_heap_profiler_android.h", "perfetto/java_heap_profiler/java_heap_profiler_android.h",
"perfetto/perfetto_config.cc", "perfetto/perfetto_config.cc",
"perfetto/perfetto_config.h", "perfetto/perfetto_config.h",
"perfetto/perfetto_platform.cc",
"perfetto/perfetto_platform.h",
"perfetto/perfetto_producer.cc", "perfetto/perfetto_producer.cc",
"perfetto/perfetto_producer.h", "perfetto/perfetto_producer.h",
"perfetto/perfetto_traced_process.cc", "perfetto/perfetto_traced_process.cc",
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/tracing/public/cpp/perfetto/perfetto_platform.h"
#include "base/deferred_sequenced_task_runner.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "services/tracing/public/cpp/perfetto/task_runner.h"
namespace tracing {
PerfettoPlatform::PerfettoPlatform()
: deferred_task_runner_(new base::DeferredSequencedTaskRunner()),
thread_local_object_([](void* object) {
delete static_cast<ThreadLocalObject*>(object);
}) {}
PerfettoPlatform::~PerfettoPlatform() = default;
void PerfettoPlatform::OnThreadPoolAvailable() {
deferred_task_runner_->StartWithTaskRunner(
base::ThreadPool::CreateSequencedTaskRunner(
{base::MayBlock(), base::TaskPriority::USER_BLOCKING}));
}
PerfettoPlatform::ThreadLocalObject*
PerfettoPlatform::GetOrCreateThreadLocalObject() {
auto* object = static_cast<ThreadLocalObject*>(thread_local_object_.Get());
if (!object) {
object = ThreadLocalObject::CreateInstance().release();
thread_local_object_.Set(object);
}
return object;
}
std::unique_ptr<perfetto::base::TaskRunner> PerfettoPlatform::CreateTaskRunner(
const CreateTaskRunnerArgs&) {
// We can't create a real task runner yet because the ThreadPool may not be
// initialized. Instead, we point Perfetto to a buffering task runner which
// will become active as soon as the thread pool is up (see
// OnThreadPoolAvailable).
return std::make_unique<PerfettoTaskRunner>(deferred_task_runner_);
}
std::string PerfettoPlatform::GetCurrentProcessName() {
// TODO(skyostil): Unimplemented since we're not registering producers through
// the client API yet.
return "";
}
} // namespace tracing
\ No newline at end of file
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PERFETTO_PLATFORM_H_
#define SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PERFETTO_PLATFORM_H_
#include "third_party/perfetto/include/perfetto/tracing/platform.h"
#include "base/memory/scoped_refptr.h"
#include "base/threading/thread_local_storage.h"
namespace base {
class DeferredSequencedTaskRunner;
} // namespace base
namespace tracing {
class PerfettoPlatform : public perfetto::Platform {
public:
PerfettoPlatform();
~PerfettoPlatform() override;
void OnThreadPoolAvailable();
// perfetto::Platform implementation:
ThreadLocalObject* GetOrCreateThreadLocalObject() override;
std::unique_ptr<perfetto::base::TaskRunner> CreateTaskRunner(
const CreateTaskRunnerArgs&) override;
std::string GetCurrentProcessName() override;
private:
scoped_refptr<base::DeferredSequencedTaskRunner> deferred_task_runner_;
base::ThreadLocalStorage::Slot thread_local_object_;
};
} // namespace tracing
#endif // SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PERFETTO_PLATFORM_H_
\ No newline at end of file
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
#include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h" #include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h"
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
#include "base/feature_list.h"
#include "base/no_destructor.h" #include "base/no_destructor.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/sequenced_task_runner.h" #include "base/sequenced_task_runner.h"
...@@ -14,11 +13,12 @@ ...@@ -14,11 +13,12 @@
#include "base/trace_event/trace_log.h" #include "base/trace_event/trace_log.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "services/tracing/public/cpp/perfetto/dummy_producer.h" #include "services/tracing/public/cpp/perfetto/dummy_producer.h"
#include "services/tracing/public/cpp/perfetto/perfetto_platform.h"
#include "services/tracing/public/cpp/perfetto/producer_client.h" #include "services/tracing/public/cpp/perfetto/producer_client.h"
#include "services/tracing/public/cpp/perfetto/trace_event_data_source.h" #include "services/tracing/public/cpp/perfetto/trace_event_data_source.h"
#include "services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h" #include "services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h"
#include "services/tracing/public/cpp/trace_startup.h" #include "services/tracing/public/cpp/trace_startup.h"
#include "services/tracing/public/cpp/tracing_features.h" #include "third_party/perfetto/include/perfetto/tracing/tracing.h"
#if defined(OS_POSIX) #if defined(OS_POSIX)
// As per 'gn help check': // As per 'gn help check':
...@@ -38,10 +38,8 @@ namespace { ...@@ -38,10 +38,8 @@ namespace {
std::unique_ptr<SystemProducer> NewSystemProducer(PerfettoTaskRunner* runner, std::unique_ptr<SystemProducer> NewSystemProducer(PerfettoTaskRunner* runner,
const char* socket_name) { const char* socket_name) {
#if defined(OS_POSIX) #if defined(OS_POSIX)
if (ShouldSetupSystemTracing()) { DCHECK(socket_name);
DCHECK(socket_name); return std::make_unique<PosixSystemProducer>(socket_name, runner);
return std::make_unique<PosixSystemProducer>(socket_name, runner);
}
#endif // defined(OS_POSIX) #endif // defined(OS_POSIX)
return std::make_unique<DummyProducer>(runner); return std::make_unique<DummyProducer>(runner);
} }
...@@ -80,11 +78,8 @@ PerfettoTracedProcess* PerfettoTracedProcess::Get() { ...@@ -80,11 +78,8 @@ PerfettoTracedProcess* PerfettoTracedProcess::Get() {
} }
PerfettoTracedProcess::PerfettoTracedProcess() PerfettoTracedProcess::PerfettoTracedProcess()
: PerfettoTracedProcess(MaybeSocket()) {}
PerfettoTracedProcess::PerfettoTracedProcess(const char* system_socket)
: producer_client_(std::make_unique<ProducerClient>(GetTaskRunner())), : producer_client_(std::make_unique<ProducerClient>(GetTaskRunner())),
system_producer_(NewSystemProducer(GetTaskRunner(), system_socket)) { platform_(std::make_unique<PerfettoPlatform>()) {
DETACH_FROM_SEQUENCE(sequence_checker_); DETACH_FROM_SEQUENCE(sequence_checker_);
} }
...@@ -149,34 +144,14 @@ void PerfettoTracedProcess::ResetTaskRunnerForTesting( ...@@ -149,34 +144,14 @@ void PerfettoTracedProcess::ResetTaskRunnerForTesting(
PerfettoTracedProcess::Get() PerfettoTracedProcess::Get()
->producer_client() ->producer_client()
->ResetSequenceForTesting(); ->ResetSequenceForTesting();
PerfettoTracedProcess::Get() if (PerfettoTracedProcess::Get()->system_producer()) {
->system_producer() PerfettoTracedProcess::Get()
->ResetSequenceForTesting(); ->system_producer()
->ResetSequenceForTesting();
}
})); }));
} }
// static
void PerfettoTracedProcess::ReconstructForTesting(const char* socket_name) {
base::RunLoop finished_reconstruction_runloop;
// The Get() call ensures that the construct has run and any required tasks
// have been completed before this lambda below is executed.
Get()->GetTaskRunner()->GetOrCreateTaskRunner()->PostTask(
FROM_HERE,
base::BindOnce(
[](base::OnceClosure on_finish, const char* socket_name) {
PerfettoTracedProcess::Get()->~PerfettoTracedProcess();
new (PerfettoTracedProcess::Get()) PerfettoTracedProcess(
socket_name ? socket_name : MaybeSocket());
// The constructor and destructor needs to be run on the proper
// sequence, but the constructor also calls PostTask so we need to
// place a task afterwards to block until everything is initialized.
GetTaskRunner()->GetOrCreateTaskRunner()->PostTaskAndReply(
FROM_HERE, base::DoNothing(), std::move(on_finish));
},
finished_reconstruction_runloop.QuitClosure(), socket_name));
finished_reconstruction_runloop.Run();
}
void PerfettoTracedProcess::AddDataSource(DataSourceBase* data_source) { void PerfettoTracedProcess::AddDataSource(DataSourceBase* data_source) {
bool inserted; bool inserted;
{ {
...@@ -194,8 +169,10 @@ void PerfettoTracedProcess::AddDataSource(DataSourceBase* data_source) { ...@@ -194,8 +169,10 @@ void PerfettoTracedProcess::AddDataSource(DataSourceBase* data_source) {
PerfettoTracedProcess::Get(); PerfettoTracedProcess::Get();
traced_process->producer_client()->NewDataSourceAdded( traced_process->producer_client()->NewDataSourceAdded(
data_source); data_source);
traced_process->system_producer()->NewDataSourceAdded( if (traced_process->system_producer()) {
data_source); traced_process->system_producer()
->NewDataSourceAdded(data_source);
}
}, },
base::Unretained(data_source))); base::Unretained(data_source)));
} }
...@@ -212,7 +189,7 @@ bool PerfettoTracedProcess::SetupStartupTracing( ...@@ -212,7 +189,7 @@ bool PerfettoTracedProcess::SetupStartupTracing(
const base::trace_event::TraceConfig& trace_config, const base::trace_event::TraceConfig& trace_config,
bool privacy_filtering_enabled) { bool privacy_filtering_enabled) {
if (producer_client_->IsTracingActive() || if (producer_client_->IsTracingActive() ||
system_producer_->IsTracingActive()) { (system_producer_ && system_producer_->IsTracingActive())) {
LOG(WARNING) << "Cannot setup startup tracing - tracing is already active"; LOG(WARNING) << "Cannot setup startup tracing - tracing is already active";
return false; return false;
} }
...@@ -225,6 +202,12 @@ bool PerfettoTracedProcess::SetupStartupTracing( ...@@ -225,6 +202,12 @@ bool PerfettoTracedProcess::SetupStartupTracing(
return true; return true;
} }
void PerfettoTracedProcess::SetupClientLibrary() {
perfetto::TracingInitArgs init_args;
init_args.platform = platform_.get();
perfetto::Tracing::Initialize(init_args);
}
void PerfettoTracedProcess::OnThreadPoolAvailable() { void PerfettoTracedProcess::OnThreadPoolAvailable() {
// Create our task runner now, so that ProducerClient/SystemProducer are // Create our task runner now, so that ProducerClient/SystemProducer are
// notified about future data source registrations and schedule any necessary // notified about future data source registrations and schedule any necessary
...@@ -232,19 +215,44 @@ void PerfettoTracedProcess::OnThreadPoolAvailable() { ...@@ -232,19 +215,44 @@ void PerfettoTracedProcess::OnThreadPoolAvailable() {
GetTaskRunner()->GetOrCreateTaskRunner(); GetTaskRunner()->GetOrCreateTaskRunner();
producer_client_->OnThreadPoolAvailable(); producer_client_->OnThreadPoolAvailable();
if (system_producer_)
system_producer_->OnThreadPoolAvailable();
platform_->OnThreadPoolAvailable();
}
void PerfettoTracedProcess::SetupSystemTracing(
base::Optional<const char*> system_socket) {
// Note: Not checking for a valid sequence here so that we don't inadvertently
// bind this object on the wrong sequence during early initialization.
DCHECK(!system_producer_);
system_producer_ = NewSystemProducer(
GetTaskRunner(), system_socket ? *system_socket : MaybeSocket());
// If the thread pool is available, register all the known data sources with
// the system producer too.
if (!GetTaskRunner()->HasTaskRunner())
return;
system_producer_->OnThreadPoolAvailable(); system_producer_->OnThreadPoolAvailable();
GetTaskRunner()->GetOrCreateTaskRunner()->PostTask(
FROM_HERE, base::BindOnce([]() {
PerfettoTracedProcess* traced_process = PerfettoTracedProcess::Get();
base::AutoLock lock(traced_process->data_sources_lock_);
for (auto* data_source : traced_process->data_sources_) {
traced_process->system_producer()->NewDataSourceAdded(data_source);
}
}));
} }
bool PerfettoTracedProcess::CanStartTracing( bool PerfettoTracedProcess::CanStartTracing(
PerfettoProducer* producer, PerfettoProducer* producer,
base::OnceCallback<void()> start_tracing) { base::OnceCallback<void()> start_tracing) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(producer);
// If the |producer| asking is the local producer_client_ it has priority so // If the |producer| asking is the local producer_client_ it has priority so
// even if the other endpoint is tracing shut down the other endpoint and let // even if the other endpoint is tracing shut down the other endpoint and let
// the |producer_client_| go. The system Producer will periodically attempt to // the |producer_client_| go. The system Producer will periodically attempt to
// reconnect if we call DisconnectWithReply(). // reconnect if we call DisconnectWithReply().
if (producer == producer_client_.get()) { if (producer == producer_client_.get()) {
if (system_producer_->IsTracingActive()) { if (system_producer_ && system_producer_->IsTracingActive()) {
system_producer_->DisconnectWithReply(std::move(start_tracing)); system_producer_->DisconnectWithReply(std::move(start_tracing));
return true; return true;
} }
......
...@@ -20,6 +20,7 @@ class TraceConfig; ...@@ -20,6 +20,7 @@ class TraceConfig;
namespace tracing { namespace tracing {
class PerfettoPlatform;
class PerfettoProducer; class PerfettoProducer;
class ProducerClient; class ProducerClient;
class SystemProducer; class SystemProducer;
...@@ -95,7 +96,7 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final { ...@@ -95,7 +96,7 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final {
static PerfettoTracedProcess* Get(); static PerfettoTracedProcess* Get();
ProducerClient* producer_client() const; ProducerClient* producer_client() const;
SystemProducer* system_producer() const; SystemProducer* system_producer() const; // May be null.
~PerfettoTracedProcess(); ~PerfettoTracedProcess();
...@@ -119,9 +120,19 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final { ...@@ -119,9 +120,19 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final {
const base::trace_event::TraceConfig&, const base::trace_event::TraceConfig&,
bool privacy_filtering_enabled); bool privacy_filtering_enabled);
// Initialize the Perfetto client library (i.e., perfetto::Tracing) for this
// process. Should be called early during startup.
void SetupClientLibrary();
// Called on the process's main thread once the thread pool is ready. // Called on the process's main thread once the thread pool is ready.
void OnThreadPoolAvailable(); void OnThreadPoolAvailable();
// Called to initialize system tracing, i.e., connecting to a system Perfetto
// daemon as a producer. If |system_socket| isn't provided, Perfetto's default
// socket name is used.
void SetupSystemTracing(base::Optional<const char*> system_socket =
base::Optional<const char*>());
// If the provided |producer| can begin tracing then |start_tracing| will be // If the provided |producer| can begin tracing then |start_tracing| will be
// invoked (unless cancelled by the Perfetto service) at some point later // invoked (unless cancelled by the Perfetto service) at some point later
// using the GetTaskRunner()'s sequence and this function will return true. // using the GetTaskRunner()'s sequence and this function will return true.
...@@ -150,12 +161,14 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final { ...@@ -150,12 +161,14 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final {
void ClearDataSourcesForTesting(); void ClearDataSourcesForTesting();
static void DeleteSoonForTesting(std::unique_ptr<PerfettoTracedProcess>); static void DeleteSoonForTesting(std::unique_ptr<PerfettoTracedProcess>);
static void ReconstructForTesting(const char* system_socket);
PerfettoPlatform* perfetto_platform_for_testing() const {
return platform_.get();
}
protected: protected:
// protected for testing. // protected for testing.
PerfettoTracedProcess(); PerfettoTracedProcess();
explicit PerfettoTracedProcess(const char* system_socket);
private: private:
friend class base::NoDestructor<PerfettoTracedProcess>; friend class base::NoDestructor<PerfettoTracedProcess>;
...@@ -173,6 +186,9 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final { ...@@ -173,6 +186,9 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final {
// calls will be noops. // calls will be noops.
std::unique_ptr<SystemProducer> system_producer_; std::unique_ptr<SystemProducer> system_producer_;
// Platform implementation for the Perfetto client library.
std::unique_ptr<PerfettoPlatform> platform_;
SEQUENCE_CHECKER(sequence_checker_); SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(PerfettoTracedProcess); DISALLOW_COPY_AND_ASSIGN(PerfettoTracedProcess);
}; };
......
...@@ -38,8 +38,11 @@ void EnableStartupTracingIfNeeded() { ...@@ -38,8 +38,11 @@ void EnableStartupTracingIfNeeded() {
*base::CommandLine::ForCurrentProcess(); *base::CommandLine::ForCurrentProcess();
TraceEventDataSource::GetInstance()->RegisterStartupHooks(); TraceEventDataSource::GetInstance()->RegisterStartupHooks();
// TODO(eseckler): Initialize the entire perfetto client library instead.
perfetto::internal::TrackRegistry::InitializeInstance(); // Initialize the Perfetto client library now that we're past the zygote's
// fork point. This is important to ensure Perfetto's track registry gets a
// unique uuid for generating track ids.
PerfettoTracedProcess::Get()->SetupClientLibrary();
// TODO(oysteine): Support startup tracing to a perfetto protobuf trace. This // TODO(oysteine): Support startup tracing to a perfetto protobuf trace. This
// should also enable TraceLog and call SetupStartupTracing(). // should also enable TraceLog and call SetupStartupTracing().
...@@ -61,6 +64,7 @@ void EnableStartupTracingIfNeeded() { ...@@ -61,6 +64,7 @@ void EnableStartupTracingIfNeeded() {
PerfettoTracedProcess::Get()->producer_client(); PerfettoTracedProcess::Get()->producer_client();
if (startup_config->GetSessionOwner() == if (startup_config->GetSessionOwner() ==
TraceStartupConfig::SessionOwner::kSystemTracing) { TraceStartupConfig::SessionOwner::kSystemTracing) {
PerfettoTracedProcess::Get()->SetupSystemTracing();
producer = PerfettoTracedProcess::Get()->system_producer(); producer = PerfettoTracedProcess::Get()->system_producer();
} }
...@@ -102,6 +106,8 @@ void InitTracingPostThreadPoolStartAndFeatureList() { ...@@ -102,6 +106,8 @@ void InitTracingPostThreadPoolStartAndFeatureList() {
// Connect to system service if available (currently a no-op except on // Connect to system service if available (currently a no-op except on
// Posix). Has to happen on the producer's sequence, as all communication // Posix). Has to happen on the producer's sequence, as all communication
// with the system Perfetto service should occur on a single sequence. // with the system Perfetto service should occur on a single sequence.
if (!PerfettoTracedProcess::Get()->system_producer())
PerfettoTracedProcess::Get()->SetupSystemTracing();
PerfettoTracedProcess::Get() PerfettoTracedProcess::Get()
->GetTaskRunner() ->GetTaskRunner()
->GetOrCreateTaskRunner() ->GetOrCreateTaskRunner()
...@@ -130,8 +136,10 @@ void PropagateTracingFlagsToChildProcessCmdLine(base::CommandLine* cmd_line) { ...@@ -130,8 +136,10 @@ void PropagateTracingFlagsToChildProcessCmdLine(base::CommandLine* cmd_line) {
// (Posix)SystemProducer doesn't currently support startup tracing, so don't // (Posix)SystemProducer doesn't currently support startup tracing, so don't
// attempt to enable startup tracing in child processes if system tracing is // attempt to enable startup tracing in child processes if system tracing is
// active. // active.
if (PerfettoTracedProcess::Get()->system_producer()->IsTracingActive()) if (PerfettoTracedProcess::Get()->system_producer() &&
PerfettoTracedProcess::Get()->system_producer()->IsTracingActive()) {
return; return;
}
// The child process startup may race with a concurrent disabling of the // The child process startup may race with a concurrent disabling of the
// tracing session by the tracing service. To avoid being stuck in startup // tracing session by the tracing service. To avoid being stuck in startup
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment