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

BackgroundTracing: Switch to Perfetto client API

This patch switches the background tracing subsystem to control tracing
through the Perfetto client API. The main benefit of this is being able
to specify priorities for tracing sessions (incl. legacy JSON ones),
which avoids interfering with interactive tracing sessions such as ones
from the DevTools profiler.

Bug: 1058632
Change-Id: I9c35e079a75a51fd4472011eee23fd431a720bec
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2404830Reviewed-by: default avataroysteine <oysteine@chromium.org>
Reviewed-by: default avatarssid <ssid@chromium.org>
Reviewed-by: default avatarMatthew Denton <mpdenton@chromium.org>
Auto-Submit: Sami Kyöstilä <skyostil@chromium.org>
Commit-Queue: Matthew Denton <mpdenton@chromium.org>
Cr-Commit-Position: refs/heads/master@{#812959}
parent b740ffb2
...@@ -19,15 +19,16 @@ ...@@ -19,15 +19,16 @@
#include "content/browser/tracing/background_tracing_manager_impl.h" #include "content/browser/tracing/background_tracing_manager_impl.h"
#include "content/browser/tracing/background_tracing_rule.h" #include "content/browser/tracing/background_tracing_rule.h"
#include "content/browser/tracing/tracing_controller_impl.h" #include "content/browser/tracing/tracing_controller_impl.h"
#include "content/public/browser/tracing_service.h" #include "content/public/browser/browser_task_traits.h"
#include "mojo/public/cpp/bindings/receiver.h" #include "content/public/browser/browser_thread.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/system/data_pipe_drainer.h"
#include "services/tracing/public/cpp/perfetto/perfetto_config.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/perfetto/perfetto_traced_process.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/perfetto/trace_packet_tokenizer.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 "services/tracing/public/cpp/tracing_features.h"
#include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_packet.h"
#include "third_party/perfetto/include/perfetto/tracing/tracing.h"
using base::trace_event::TraceConfig; using base::trace_event::TraceConfig;
using Metrics = content::BackgroundTracingManagerImpl::Metrics; using Metrics = content::BackgroundTracingManagerImpl::Metrics;
...@@ -65,37 +66,25 @@ class BackgroundTracingActiveScenario::TracingTimer { ...@@ -65,37 +66,25 @@ class BackgroundTracingActiveScenario::TracingTimer {
class BackgroundTracingActiveScenario::TracingSession { class BackgroundTracingActiveScenario::TracingSession {
public: public:
virtual ~TracingSession() = default; TracingSession(BackgroundTracingActiveScenario* parent_scenario,
virtual void BeginFinalizing(base::OnceClosure on_success,
base::OnceClosure on_failure) = 0;
virtual void AbortScenario(
const base::RepeatingClosure& on_abort_callback) = 0;
};
class PerfettoTracingSession
: public BackgroundTracingActiveScenario::TracingSession,
public tracing::mojom::TracingSessionClient,
public mojo::DataPipeDrainer::Client {
public:
PerfettoTracingSession(BackgroundTracingActiveScenario* parent_scenario,
const TraceConfig& chrome_config, const TraceConfig& chrome_config,
const BackgroundTracingConfigImpl* config) const BackgroundTracingConfigImpl* config,
bool convert_to_legacy_json)
: parent_scenario_(parent_scenario), : parent_scenario_(parent_scenario),
raw_data_(std::make_unique<std::string>()) { convert_to_legacy_json_(convert_to_legacy_json) {
#if !defined(OS_ANDROID) #if !defined(OS_ANDROID)
// TODO(crbug.com/941318): Re-enable startup tracing for Android once all // TODO(crbug.com/941318): Re-enable startup tracing for Android once all
// Perfetto-related deadlocks are resolved and we also handle concurrent // Perfetto-related deadlocks are resolved and we also handle concurrent
// system tracing for startup tracing. // system tracing for startup tracing.
if (!TracingControllerImpl::GetInstance()->IsTracing()) { if (!TracingControllerImpl::GetInstance()->IsTracing()) {
// Privacy filtering is done as part of JSON conversion, so if we are
// generating JSON, we don't need to enable privacy filtering at the data
// source level.
tracing::EnableStartupTracingForProcess( tracing::EnableStartupTracingForProcess(
chrome_config, chrome_config,
/*privacy_filtering_enabled=*/true); /*privacy_filtering_enabled=*/!convert_to_legacy_json);
} }
#endif #endif
GetTracingService().BindConsumerHost(
consumer_host_.BindNewPipeAndPassReceiver());
perfetto::TraceConfig perfetto_config; perfetto::TraceConfig perfetto_config;
perfetto_config.mutable_incremental_state_config()->set_clear_period_ms( perfetto_config.mutable_incremental_state_config()->set_clear_period_ms(
config->interning_reset_interval_ms()); config->interning_reset_interval_ms());
...@@ -106,155 +95,87 @@ class PerfettoTracingSession ...@@ -106,155 +95,87 @@ class PerfettoTracingSession
} }
perfetto_config = tracing::GetPerfettoConfigWithDataSources( perfetto_config = tracing::GetPerfettoConfigWithDataSources(
chrome_config, data_source_filter, chrome_config, data_source_filter,
/*privacy_filtering_enabled=*/true); /*privacy_filtering_enabled=*/true,
/*convert_to_legacy_json=*/convert_to_legacy_json,
consumer_host_->EnableTracing( perfetto::protos::gen::ChromeConfig::BACKGROUND);
tracing_session_host_.BindNewPipeAndPassReceiver(), tracing_session_ = perfetto::Tracing::NewTrace();
receiver_.BindNewPipeAndPassRemote(), std::move(perfetto_config), tracing_session_->Setup(perfetto_config);
tracing::mojom::TracingClientPriority::kBackground);
receiver_.set_disconnect_handler( auto category_preset = parent_scenario->GetConfig()->category_preset();
base::BindOnce(&PerfettoTracingSession::OnTracingSessionEnded, tracing_session_->SetOnStartCallback([category_preset] {
base::Unretained(this))); GetUIThreadTaskRunner({})->PostTask(
tracing_session_host_.set_disconnect_handler( FROM_HERE,
base::BindOnce(&PerfettoTracingSession::OnTracingSessionEnded, base::BindOnce(
base::Unretained(this))); &BackgroundTracingManagerImpl::OnStartTracingDone,
} base::Unretained(BackgroundTracingManagerImpl::GetInstance()),
category_preset));
// BackgroundTracingActiveScenario::TracingSession implementation. });
void BeginFinalizing(base::OnceClosure on_success, tracing_session_->Start();
base::OnceClosure on_failure) override { // We check IsEnabled() before creating the LegacyTracingSession,
bool is_allowed_finalization = // so any failures to start tracing at this point would be due to invalid
BackgroundTracingManagerImpl::GetInstance()->IsAllowedFinalization(); // configs which we treat as a failure scenario.
if (!is_allowed_finalization) {
std::move(on_failure).Run();
return;
} }
tracing_session_host_->DisableTracing(); ~TracingSession() {
std::move(on_success).Run(); DCHECK(!tracing_session_);
DCHECK(!TracingControllerImpl::GetInstance()->IsTracing());
} }
void AbortScenario(const base::RepeatingClosure& on_abort_callback) override { void BeginFinalizing(base::OnceClosure on_success,
if (is_tracing_disabled_) { base::OnceClosure on_failure) {
on_abort_callback.Run(); // If the finalization was already in progress, ignore this call.
if (!tracing_session_)
return; return;
} if (!BackgroundTracingManagerImpl::GetInstance()->IsAllowedFinalization()) {
on_abort_callback_ = on_abort_callback; auto on_failure_cb =
tracing_session_host_->DisableTracing(); base::MakeRefCounted<base::RefCountedData<base::OnceClosure>>(
} std::move(on_failure));
auto tracing_session = TakeTracingSession();
// mojo::DataPipeDrainer::Client implementation: tracing_session->data->SetOnStopCallback(
void OnDataAvailable(const void* data, size_t num_bytes) override { [tracing_session, on_failure_cb] {
raw_data_->append(reinterpret_cast<const char*>(data), num_bytes); GetUIThreadTaskRunner({})->PostTask(FROM_HERE,
} std::move(on_failure_cb->data));
});
void OnDataComplete() override { tracing_session->data->Stop();
has_finished_receiving_data_ = true;
MaybeFinishedReceivingTrace();
}
// tracing::mojom::TracingSession implementation:
void OnTracingEnabled() override {
BackgroundTracingManagerImpl::GetInstance()->OnStartTracingDone(
parent_scenario_->GetConfig()->category_preset());
}
void OnTracingDisabled() override {
is_tracing_disabled_ = true;
if (on_abort_callback_) {
std::move(on_abort_callback_).Run();
return; return;
} }
mojo::ScopedDataPipeProducerHandle producer_handle; if (convert_to_legacy_json_) {
mojo::ScopedDataPipeConsumerHandle consumer_handle; FinalizeTraceAsJson(std::move(on_success));
} else {
MojoResult result = FinalizeTraceAsProtobuf(std::move(on_success));
mojo::CreateDataPipe(nullptr, &producer_handle, &consumer_handle);
DCHECK_EQ(MOJO_RESULT_OK, result);
drainer_ = std::make_unique<mojo::DataPipeDrainer>(
this, std::move(consumer_handle));
tracing_session_host_->ReadBuffers(
std::move(producer_handle),
base::BindOnce(&PerfettoTracingSession::OnReadBuffersComplete,
base::Unretained(this)));
} }
DCHECK(!tracing_session_);
void OnReadBuffersComplete() {
has_finished_read_buffers_ = true;
MaybeFinishedReceivingTrace();
} }
void MaybeFinishedReceivingTrace() { void AbortScenario(const base::RepeatingClosure& on_abort_callback) {
if (has_finished_read_buffers_ && has_finished_receiving_data_) { if (tracing_session_) {
DCHECK(raw_data_); auto tracing_session = TakeTracingSession();
parent_scenario_->OnProtoDataComplete(std::move(raw_data_)); auto on_abort_cb =
base::MakeRefCounted<base::RefCountedData<base::OnceClosure>>(
std::move(on_abort_callback));
tracing_session->data->SetOnStopCallback([on_abort_cb, tracing_session] {
GetUIThreadTaskRunner({})->PostTask(FROM_HERE,
std::move(on_abort_cb->data));
});
tracing_session->data->Stop();
} else {
on_abort_callback.Run();
} }
} }
private: private:
void OnTracingSessionEnded() { parent_scenario_->AbortScenario(); } // Wraps the tracing session in a refcounted handle that can be passed through
// callbacks.
BackgroundTracingActiveScenario* const parent_scenario_; scoped_refptr<base::RefCountedData<std::unique_ptr<perfetto::TracingSession>>>
mojo::Receiver<tracing::mojom::TracingSessionClient> receiver_{this}; TakeTracingSession() {
mojo::Remote<tracing::mojom::TracingSessionHost> tracing_session_host_; return base::MakeRefCounted<
std::unique_ptr<mojo::DataPipeDrainer> drainer_; base::RefCountedData<std::unique_ptr<perfetto::TracingSession>>>(
mojo::Remote<tracing::mojom::ConsumerHost> consumer_host_; std::move(tracing_session_));
std::unique_ptr<std::string> raw_data_;
bool has_finished_read_buffers_ = false;
bool has_finished_receiving_data_ = false;
bool is_tracing_disabled_ = false;
base::OnceClosure on_abort_callback_;
};
class LegacyTracingSession
: public BackgroundTracingActiveScenario::TracingSession {
public:
LegacyTracingSession(BackgroundTracingActiveScenario* parent_scenario,
const TraceConfig& chrome_config)
: parent_scenario_(parent_scenario) {
#if !defined(OS_ANDROID)
// TODO(crbug.com/941318): Re-enable startup tracing for Android once all
// Perfetto-related deadlocks are resolved and we also handle concurrent
// system tracing for startup tracing.
if (!TracingControllerImpl::GetInstance()->IsTracing()) {
tracing::EnableStartupTracingForProcess(
chrome_config,
/*privacy_filtering_enabled=*/false);
}
#endif
bool result = TracingControllerImpl::GetInstance()->StartTracing(
chrome_config,
base::BindOnce(
&BackgroundTracingManagerImpl::OnStartTracingDone,
base::Unretained(BackgroundTracingManagerImpl::GetInstance()),
parent_scenario->GetConfig()->category_preset()));
// We check IsEnabled() before creating the LegacyTracingSession,
// so any failures to start tracing at this point would be due to invalid
// configs which we treat as a failure scenario.
DCHECK(result);
}
~LegacyTracingSession() override {
DCHECK(!TracingControllerImpl::GetInstance()->IsTracing());
}
// BackgroundTracingActiveScenario::TracingSession implementation.
void BeginFinalizing(base::OnceClosure on_success,
base::OnceClosure on_failure) override {
if (!BackgroundTracingManagerImpl::GetInstance()->IsAllowedFinalization()) {
TracingControllerImpl::GetInstance()->StopTracing(
TracingControllerImpl::CreateCallbackEndpoint(base::BindOnce(
[](base::OnceClosure on_failure, std::unique_ptr<std::string>) {
std::move(on_failure).Run();
},
std::move(on_failure))));
return;
} }
void FinalizeTraceAsJson(base::OnceClosure on_success) {
auto tracing_session = TakeTracingSession();
auto trace_data_endpoint = auto trace_data_endpoint =
TracingControllerImpl::CreateCompressedStringEndpoint( TracingControllerImpl::CreateCompressedStringEndpoint(
TracingControllerImpl::CreateCallbackEndpoint(base::BindOnce( TracingControllerImpl::CreateCallbackEndpoint(base::BindOnce(
...@@ -268,26 +189,70 @@ class LegacyTracingSession ...@@ -268,26 +189,70 @@ class LegacyTracingSession
}, },
parent_scenario_->GetWeakPtr(), std::move(on_success))), parent_scenario_->GetWeakPtr(), std::move(on_success))),
true /* compress_with_background_priority */); true /* compress_with_background_priority */);
auto tokenizer = base::MakeRefCounted<
TracingControllerImpl::GetInstance()->StopTracing( base::RefCountedData<std::unique_ptr<tracing::TracePacketTokenizer>>>(
trace_data_endpoint, "", std::make_unique<tracing::TracePacketTokenizer>());
parent_scenario_->GetConfig()->requires_anonymized_data()); tracing_session->data->SetOnStopCallback([tracing_session, tokenizer,
} trace_data_endpoint] {
tracing_session->data->ReadTrace(
void AbortScenario(const base::RepeatingClosure& on_abort_callback) override { [tracing_session, tokenizer, trace_data_endpoint](
if (TracingControllerImpl::GetInstance()->IsTracing()) { perfetto::TracingSession::ReadTraceCallbackArgs args) {
TracingControllerImpl::GetInstance()->StopTracing( if (args.size) {
TracingControllerImpl::CreateCallbackEndpoint(base::BindOnce( auto packets = tokenizer->data->Parse(
[](const base::RepeatingClosure& on_abort_callback, reinterpret_cast<const uint8_t*>(args.data), args.size);
std::unique_ptr<std::string>) { on_abort_callback.Run(); }, for (const auto& packet : packets) {
std::move(on_abort_callback)))); for (const auto& slice : packet.slices()) {
} else { auto data_string = std::make_unique<std::string>(
on_abort_callback.Run(); reinterpret_cast<const char*>(slice.start), slice.size);
trace_data_endpoint->ReceiveTraceChunk(
std::move(data_string));
}
}
}
if (!args.has_more) {
DCHECK(!tokenizer->data->has_more());
GetUIThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(
&content::TracingController::TraceDataEndpoint::
ReceivedTraceFinalContents,
trace_data_endpoint));
}
});
});
tracing_session->data->Stop();
}
void FinalizeTraceAsProtobuf(base::OnceClosure on_success) {
auto tracing_session = TakeTracingSession();
auto raw_data = base::MakeRefCounted<
base::RefCountedData<std::unique_ptr<std::string>>>(
std::make_unique<std::string>());
auto parent_scenario = parent_scenario_->GetWeakPtr();
tracing_session->data->SetOnStopCallback(
[parent_scenario, tracing_session, raw_data] {
tracing_session->data->ReadTrace(
[parent_scenario, tracing_session,
raw_data](perfetto::TracingSession::ReadTraceCallbackArgs args) {
if (args.size) {
raw_data->data->append(args.data, args.size);
}
if (!args.has_more) {
GetUIThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(
&BackgroundTracingActiveScenario::OnProtoDataComplete,
parent_scenario,
base::Passed(std::move(raw_data->data))));
} }
});
});
tracing_session->data->Stop();
} }
private:
BackgroundTracingActiveScenario* const parent_scenario_; BackgroundTracingActiveScenario* const parent_scenario_;
const bool convert_to_legacy_json_;
std::unique_ptr<perfetto::TracingSession> tracing_session_;
}; };
BackgroundTracingActiveScenario::BackgroundTracingActiveScenario( BackgroundTracingActiveScenario::BackgroundTracingActiveScenario(
...@@ -380,13 +345,10 @@ bool BackgroundTracingActiveScenario::StartTracing() { ...@@ -380,13 +345,10 @@ bool BackgroundTracingActiveScenario::StartTracing() {
modes |= base::trace_event::TraceLog::FILTERING_MODE; modes |= base::trace_event::TraceLog::FILTERING_MODE;
DCHECK(!tracing_session_); DCHECK(!tracing_session_);
if (base::FeatureList::IsEnabled(features::kBackgroundTracingProtoOutput)) { bool convert_to_legacy_json =
tracing_session_ = std::make_unique<PerfettoTracingSession>( !base::FeatureList::IsEnabled(features::kBackgroundTracingProtoOutput);
this, chrome_config, config_.get()); tracing_session_ = std::make_unique<TracingSession>(
} else { this, chrome_config, config_.get(), convert_to_legacy_json);
tracing_session_ =
std::make_unique<LegacyTracingSession>(this, chrome_config);
}
SetState(State::kTracing); SetState(State::kTracing);
BackgroundTracingManagerImpl::RecordMetric(Metrics::RECORDING_ENABLED); BackgroundTracingManagerImpl::RecordMetric(Metrics::RECORDING_ENABLED);
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include "content/browser/tracing/tracing_controller_impl.h" #include "content/browser/tracing/tracing_controller_impl.h"
#include "content/public/browser/background_tracing_manager.h" #include "content/public/browser/background_tracing_manager.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/mojom/perfetto_service.mojom.h"
namespace content { namespace content {
...@@ -49,9 +48,9 @@ class BackgroundTracingActiveScenario { ...@@ -49,9 +48,9 @@ class BackgroundTracingActiveScenario {
const BackgroundTracingRule* triggered_rule, const BackgroundTracingRule* triggered_rule,
BackgroundTracingManager::StartedFinalizingCallback callback); BackgroundTracingManager::StartedFinalizingCallback callback);
// Called by LegacyTracingSession when the final trace data is ready. // Called by TracingSession when the final trace data is ready.
void OnJSONDataComplete(std::unique_ptr<std::string>); void OnJSONDataComplete(std::unique_ptr<std::string>);
// Called by the PerfettoTracingSession when the proto trace is ready. // Called by TracingSession when the proto trace is ready.
void OnProtoDataComplete(std::unique_ptr<std::string> proto_trace); void OnProtoDataComplete(std::unique_ptr<std::string> proto_trace);
// Called when the finalized trace data has been uploaded/transferred away // Called when the finalized trace data has been uploaded/transferred away
......
...@@ -167,6 +167,9 @@ ConsumerHost::TracingSession::TracingSession( ...@@ -167,6 +167,9 @@ ConsumerHost::TracingSession::TracingSession(
if (data_source.config().chrome_config().privacy_filtering_enabled()) { if (data_source.config().chrome_config().privacy_filtering_enabled()) {
privacy_filtering_enabled_ = true; privacy_filtering_enabled_ = true;
} }
if (data_source.config().chrome_config().convert_to_legacy_json()) {
convert_to_legacy_json_ = true;
}
} }
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
if (privacy_filtering_enabled_) { if (privacy_filtering_enabled_) {
...@@ -194,7 +197,25 @@ ConsumerHost::TracingSession::TracingSession( ...@@ -194,7 +197,25 @@ ConsumerHost::TracingSession::TracingSession(
base::EraseIf(*pending_enable_tracing_ack_pids_, base::EraseIf(*pending_enable_tracing_ack_pids_,
[this](base::ProcessId pid) { return !IsExpectedPid(pid); }); [this](base::ProcessId pid) { return !IsExpectedPid(pid); });
host_->consumer_endpoint()->EnableTracing(trace_config); perfetto::TraceConfig effective_config(trace_config);
// If we're going to convert the data to JSON, don't enable privacy filtering
// at the data source level since it will be performed at conversion time
// (otherwise there's nothing to pass through the allowlist).
if (convert_to_legacy_json_ && privacy_filtering_enabled_) {
for (auto& data_source : *effective_config.mutable_data_sources()) {
auto* chrome_config =
data_source.mutable_config()->mutable_chrome_config();
chrome_config->set_privacy_filtering_enabled(false);
// Argument filtering should still be enabled together with privacy
// filtering to ensure, for example, that only the expected metadata gets
// written.
base::trace_event::TraceConfig base_config(chrome_config->trace_config());
base_config.EnableArgumentFilter();
chrome_config->set_trace_config(base_config.ToString());
}
}
host_->consumer_endpoint()->EnableTracing(effective_config);
MaybeSendEnableTracingAck(); MaybeSendEnableTracingAck();
if (pending_enable_tracing_ack_pids_) { if (pending_enable_tracing_ack_pids_) {
...@@ -356,6 +377,7 @@ void ConsumerHost::TracingSession::OnConsumerClientDisconnected() { ...@@ -356,6 +377,7 @@ void ConsumerHost::TracingSession::OnConsumerClientDisconnected() {
void ConsumerHost::TracingSession::ReadBuffers( void ConsumerHost::TracingSession::ReadBuffers(
mojo::ScopedDataPipeProducerHandle stream, mojo::ScopedDataPipeProducerHandle stream,
ReadBuffersCallback callback) { ReadBuffersCallback callback) {
DCHECK(!convert_to_legacy_json_);
read_buffers_stream_writer_ = base::SequenceBound<StreamWriter>( read_buffers_stream_writer_ = base::SequenceBound<StreamWriter>(
StreamWriter::CreateTaskRunner(), std::move(stream), std::move(callback), StreamWriter::CreateTaskRunner(), std::move(stream), std::move(callback),
base::BindOnce(&TracingSession::OnConsumerClientDisconnected, base::BindOnce(&TracingSession::OnConsumerClientDisconnected,
...@@ -393,7 +415,7 @@ void ConsumerHost::TracingSession::DisableTracingAndEmitJson( ...@@ -393,7 +415,7 @@ void ConsumerHost::TracingSession::DisableTracingAndEmitJson(
// For filtering/allowlisting to be possible at JSON export time, // For filtering/allowlisting to be possible at JSON export time,
// filtering must not have been enabled during proto emission time // filtering must not have been enabled during proto emission time
// (or there's nothing to pass through the allowlist). // (or there's nothing to pass through the allowlist).
DCHECK(!privacy_filtering_enabled_); DCHECK(!privacy_filtering_enabled_ || convert_to_legacy_json_);
privacy_filtering_enabled_ = true; privacy_filtering_enabled_ = true;
} }
......
...@@ -94,6 +94,7 @@ class ConsumerHost : public perfetto::Consumer, public mojom::ConsumerHost { ...@@ -94,6 +94,7 @@ class ConsumerHost : public perfetto::Consumer, public mojom::ConsumerHost {
mojo::Remote<mojom::TracingSessionClient> tracing_session_client_; mojo::Remote<mojom::TracingSessionClient> tracing_session_client_;
mojo::Receiver<mojom::TracingSessionHost> receiver_; mojo::Receiver<mojom::TracingSessionHost> receiver_;
bool privacy_filtering_enabled_ = false; bool privacy_filtering_enabled_ = false;
bool convert_to_legacy_json_ = false;
base::SequenceBound<StreamWriter> read_buffers_stream_writer_; base::SequenceBound<StreamWriter> read_buffers_stream_writer_;
RequestBufferUsageCallback request_buffer_usage_callback_; RequestBufferUsageCallback request_buffer_usage_callback_;
std::unique_ptr<perfetto::trace_processor::TraceProcessorStorage> std::unique_ptr<perfetto::trace_processor::TraceProcessorStorage>
......
...@@ -392,7 +392,8 @@ class TracingConsumerTest : public testing::Test, ...@@ -392,7 +392,8 @@ class TracingConsumerTest : public testing::Test,
} }
void EnableTracingWithDataSourceName(const std::string& data_source_name, void EnableTracingWithDataSourceName(const std::string& data_source_name,
bool enable_privacy_filtering = false) { bool enable_privacy_filtering = false,
bool convert_to_legacy_json = false) {
perfetto::TraceConfig config = GetDefaultTraceConfig(data_source_name); perfetto::TraceConfig config = GetDefaultTraceConfig(data_source_name);
if (enable_privacy_filtering) { if (enable_privacy_filtering) {
for (auto& source : *config.mutable_data_sources()) { for (auto& source : *config.mutable_data_sources()) {
...@@ -401,6 +402,13 @@ class TracingConsumerTest : public testing::Test, ...@@ -401,6 +402,13 @@ class TracingConsumerTest : public testing::Test,
->set_privacy_filtering_enabled(true); ->set_privacy_filtering_enabled(true);
} }
} }
if (convert_to_legacy_json) {
for (auto& source : *config.mutable_data_sources()) {
source.mutable_config()
->mutable_chrome_config()
->set_convert_to_legacy_json(true);
}
}
threaded_service_->EnableTracingWithConfig(config); threaded_service_->EnableTracingWithConfig(config);
} }
...@@ -623,7 +631,8 @@ TEST_F(TracingConsumerTest, ...@@ -623,7 +631,8 @@ TEST_F(TracingConsumerTest,
TEST_F(TracingConsumerTest, PrivacyFilterConfig) { TEST_F(TracingConsumerTest, PrivacyFilterConfig) {
EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName, EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName,
/* enable_privacy_filtering =*/true); /* enable_privacy_filtering =*/true,
/* convert_to_legacy_json =*/false);
base::RunLoop wait_for_tracing_start; base::RunLoop wait_for_tracing_start;
threaded_perfetto_service()->CreateProducer( threaded_perfetto_service()->CreateProducer(
...@@ -635,11 +644,40 @@ TEST_F(TracingConsumerTest, PrivacyFilterConfig) { ...@@ -635,11 +644,40 @@ TEST_F(TracingConsumerTest, PrivacyFilterConfig) {
->GetProducerClientConfig() ->GetProducerClientConfig()
.chrome_config() .chrome_config()
.privacy_filtering_enabled()); .privacy_filtering_enabled());
base::trace_event::TraceConfig base_config(threaded_perfetto_service()
->GetProducerClientConfig()
.chrome_config()
.trace_config());
EXPECT_FALSE(base_config.IsArgumentFilterEnabled());
}
TEST_F(TracingConsumerTest, NoPrivacyFilterWithJsonConversion) {
EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName,
/* enable_privacy_filtering =*/false,
/* convert_to_legacy_json =*/true);
base::RunLoop wait_for_tracing_start;
threaded_perfetto_service()->CreateProducer(
mojom::kTraceEventDataSourceName, 10u,
wait_for_tracing_start.QuitClosure());
wait_for_tracing_start.Run();
EXPECT_FALSE(threaded_perfetto_service()
->GetProducerClientConfig()
.chrome_config()
.privacy_filtering_enabled());
base::trace_event::TraceConfig base_config(threaded_perfetto_service()
->GetProducerClientConfig()
.chrome_config()
.trace_config());
EXPECT_FALSE(base_config.IsArgumentFilterEnabled());
} }
TEST_F(TracingConsumerTest, PrivacyFilterConfigInJson) { TEST_F(TracingConsumerTest, PrivacyFilterConfigInJson) {
EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName, EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName,
/* enable_privacy_filtering =*/false); /* enable_privacy_filtering =*/true,
/* convert_to_legacy_json =*/true);
base::RunLoop wait_for_tracing_start; base::RunLoop wait_for_tracing_start;
threaded_perfetto_service()->CreateProducer( threaded_perfetto_service()->CreateProducer(
...@@ -652,6 +690,11 @@ TEST_F(TracingConsumerTest, PrivacyFilterConfigInJson) { ...@@ -652,6 +690,11 @@ TEST_F(TracingConsumerTest, PrivacyFilterConfigInJson) {
->GetProducerClientConfig() ->GetProducerClientConfig()
.chrome_config() .chrome_config()
.privacy_filtering_enabled()); .privacy_filtering_enabled());
base::trace_event::TraceConfig base_config(threaded_perfetto_service()
->GetProducerClientConfig()
.chrome_config()
.trace_config());
EXPECT_TRUE(base_config.IsArgumentFilterEnabled());
base::RunLoop no_more_data; base::RunLoop no_more_data;
ExpectPackets("\"trace_processor_stats\":\"__stripped__\"", ExpectPackets("\"trace_processor_stats\":\"__stripped__\"",
...@@ -721,7 +764,6 @@ class MockConsumerHost : public mojom::TracingSessionClient { ...@@ -721,7 +764,6 @@ class MockConsumerHost : public mojom::TracingSessionClient {
}; };
TEST_F(TracingConsumerTest, TestConsumerPriority) { TEST_F(TracingConsumerTest, TestConsumerPriority) {
// auto perfetto_service = std::make_unique<PerfettoService>(nullptr);
PerfettoService::GetInstance()->SetActiveServicePidsInitialized(); PerfettoService::GetInstance()->SetActiveServicePidsInitialized();
auto trace_config = GetDefaultTraceConfig(mojom::kTraceEventDataSourceName); auto trace_config = GetDefaultTraceConfig(mojom::kTraceEventDataSourceName);
......
...@@ -444,7 +444,7 @@ class ConsumerEndpoint : public perfetto::ConsumerEndpoint, ...@@ -444,7 +444,7 @@ class ConsumerEndpoint : public perfetto::ConsumerEndpoint,
data_source.config().chrome_config().convert_to_legacy_json()) { data_source.config().chrome_config().convert_to_legacy_json()) {
tracing_session_host_->DisableTracingAndEmitJson( tracing_session_host_->DisableTracingAndEmitJson(
/*agent_label_filter=*/"", std::move(producer_handle), /*agent_label_filter=*/"", std::move(producer_handle),
/*privacy_filter_enabled=*/false, data_source.config().chrome_config().privacy_filtering_enabled(),
base::BindOnce(&ConsumerEndpoint::OnReadBuffersComplete, base::BindOnce(&ConsumerEndpoint::OnReadBuffersComplete,
base::Unretained(this))); base::Unretained(this)));
return; return;
......
...@@ -171,6 +171,7 @@ void TraceEventMetadataSource::AddGeneratorFunction( ...@@ -171,6 +171,7 @@ void TraceEventMetadataSource::AddGeneratorFunction(
std::unique_ptr<base::DictionaryValue> std::unique_ptr<base::DictionaryValue>
TraceEventMetadataSource::GenerateTraceConfigMetadataDict() { TraceEventMetadataSource::GenerateTraceConfigMetadataDict() {
AutoLockWithDeferredTaskPosting lock(lock_);
if (chrome_config_.empty()) { if (chrome_config_.empty()) {
return nullptr; return nullptr;
} }
......
...@@ -18,6 +18,7 @@ bool StructTraits< ...@@ -18,6 +18,7 @@ bool StructTraits<
} }
out->set_trace_config(std::move(config)); out->set_trace_config(std::move(config));
out->set_privacy_filtering_enabled(data.privacy_filtering_enabled()); out->set_privacy_filtering_enabled(data.privacy_filtering_enabled());
out->set_convert_to_legacy_json(data.convert_to_legacy_json());
return true; return true;
} }
} // namespace mojo } // namespace mojo
...@@ -27,6 +27,10 @@ class StructTraits<tracing::mojom::ChromeConfigDataView, ...@@ -27,6 +27,10 @@ class StructTraits<tracing::mojom::ChromeConfigDataView,
return src.privacy_filtering_enabled(); return src.privacy_filtering_enabled();
} }
static bool convert_to_legacy_json(const perfetto::ChromeConfig& src) {
return src.convert_to_legacy_json();
}
static bool Read(tracing::mojom::ChromeConfigDataView data, static bool Read(tracing::mojom::ChromeConfigDataView data,
perfetto::ChromeConfig* out); perfetto::ChromeConfig* out);
}; };
......
...@@ -85,6 +85,10 @@ struct ChromeConfig { ...@@ -85,6 +85,10 @@ struct ChromeConfig {
// When enabled the data source is supposed to only emit fields in the output // When enabled the data source is supposed to only emit fields in the output
// proto that are guaranteed to not contain any sensitive data. // proto that are guaranteed to not contain any sensitive data.
bool privacy_filtering_enabled; bool privacy_filtering_enabled;
// Whether the final tracing result will be converted to the legacy JSON
// format.
bool convert_to_legacy_json;
}; };
struct DataSourceConfig { struct DataSourceConfig {
......
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