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
......@@ -14,7 +14,6 @@
#include "content/browser/tracing/tracing_controller_impl.h"
#include "content/public/browser/background_tracing_manager.h"
#include "services/tracing/public/cpp/perfetto/trace_event_data_source.h"
#include "services/tracing/public/mojom/perfetto_service.mojom.h"
namespace content {
......@@ -49,9 +48,9 @@ class BackgroundTracingActiveScenario {
const BackgroundTracingRule* triggered_rule,
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>);
// 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);
// Called when the finalized trace data has been uploaded/transferred away
......
......@@ -167,6 +167,9 @@ ConsumerHost::TracingSession::TracingSession(
if (data_source.config().chrome_config().privacy_filtering_enabled()) {
privacy_filtering_enabled_ = true;
}
if (data_source.config().chrome_config().convert_to_legacy_json()) {
convert_to_legacy_json_ = true;
}
}
#if DCHECK_IS_ON()
if (privacy_filtering_enabled_) {
......@@ -194,7 +197,25 @@ ConsumerHost::TracingSession::TracingSession(
base::EraseIf(*pending_enable_tracing_ack_pids_,
[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();
if (pending_enable_tracing_ack_pids_) {
......@@ -356,6 +377,7 @@ void ConsumerHost::TracingSession::OnConsumerClientDisconnected() {
void ConsumerHost::TracingSession::ReadBuffers(
mojo::ScopedDataPipeProducerHandle stream,
ReadBuffersCallback callback) {
DCHECK(!convert_to_legacy_json_);
read_buffers_stream_writer_ = base::SequenceBound<StreamWriter>(
StreamWriter::CreateTaskRunner(), std::move(stream), std::move(callback),
base::BindOnce(&TracingSession::OnConsumerClientDisconnected,
......@@ -393,7 +415,7 @@ void ConsumerHost::TracingSession::DisableTracingAndEmitJson(
// For filtering/allowlisting to be possible at JSON export time,
// filtering must not have been enabled during proto emission time
// (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;
}
......
......@@ -94,6 +94,7 @@ class ConsumerHost : public perfetto::Consumer, public mojom::ConsumerHost {
mojo::Remote<mojom::TracingSessionClient> tracing_session_client_;
mojo::Receiver<mojom::TracingSessionHost> receiver_;
bool privacy_filtering_enabled_ = false;
bool convert_to_legacy_json_ = false;
base::SequenceBound<StreamWriter> read_buffers_stream_writer_;
RequestBufferUsageCallback request_buffer_usage_callback_;
std::unique_ptr<perfetto::trace_processor::TraceProcessorStorage>
......
......@@ -392,7 +392,8 @@ class TracingConsumerTest : public testing::Test,
}
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);
if (enable_privacy_filtering) {
for (auto& source : *config.mutable_data_sources()) {
......@@ -401,6 +402,13 @@ class TracingConsumerTest : public testing::Test,
->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);
}
......@@ -623,7 +631,8 @@ TEST_F(TracingConsumerTest,
TEST_F(TracingConsumerTest, PrivacyFilterConfig) {
EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName,
/* enable_privacy_filtering =*/true);
/* enable_privacy_filtering =*/true,
/* convert_to_legacy_json =*/false);
base::RunLoop wait_for_tracing_start;
threaded_perfetto_service()->CreateProducer(
......@@ -635,11 +644,40 @@ TEST_F(TracingConsumerTest, PrivacyFilterConfig) {
->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, 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) {
EnableTracingWithDataSourceName(mojom::kTraceEventDataSourceName,
/* enable_privacy_filtering =*/false);
/* enable_privacy_filtering =*/true,
/* convert_to_legacy_json =*/true);
base::RunLoop wait_for_tracing_start;
threaded_perfetto_service()->CreateProducer(
......@@ -652,6 +690,11 @@ TEST_F(TracingConsumerTest, PrivacyFilterConfigInJson) {
->GetProducerClientConfig()
.chrome_config()
.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;
ExpectPackets("\"trace_processor_stats\":\"__stripped__\"",
......@@ -721,7 +764,6 @@ class MockConsumerHost : public mojom::TracingSessionClient {
};
TEST_F(TracingConsumerTest, TestConsumerPriority) {
// auto perfetto_service = std::make_unique<PerfettoService>(nullptr);
PerfettoService::GetInstance()->SetActiveServicePidsInitialized();
auto trace_config = GetDefaultTraceConfig(mojom::kTraceEventDataSourceName);
......
......@@ -444,7 +444,7 @@ class ConsumerEndpoint : public perfetto::ConsumerEndpoint,
data_source.config().chrome_config().convert_to_legacy_json()) {
tracing_session_host_->DisableTracingAndEmitJson(
/*agent_label_filter=*/"", std::move(producer_handle),
/*privacy_filter_enabled=*/false,
data_source.config().chrome_config().privacy_filtering_enabled(),
base::BindOnce(&ConsumerEndpoint::OnReadBuffersComplete,
base::Unretained(this)));
return;
......
......@@ -171,6 +171,7 @@ void TraceEventMetadataSource::AddGeneratorFunction(
std::unique_ptr<base::DictionaryValue>
TraceEventMetadataSource::GenerateTraceConfigMetadataDict() {
AutoLockWithDeferredTaskPosting lock(lock_);
if (chrome_config_.empty()) {
return nullptr;
}
......
......@@ -18,6 +18,7 @@ bool StructTraits<
}
out->set_trace_config(std::move(config));
out->set_privacy_filtering_enabled(data.privacy_filtering_enabled());
out->set_convert_to_legacy_json(data.convert_to_legacy_json());
return true;
}
} // namespace mojo
......@@ -27,6 +27,10 @@ class StructTraits<tracing::mojom::ChromeConfigDataView,
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,
perfetto::ChromeConfig* out);
};
......
......@@ -85,6 +85,10 @@ struct ChromeConfig {
// When enabled the data source is supposed to only emit fields in the output
// proto that are guaranteed to not contain any sensitive data.
bool privacy_filtering_enabled;
// Whether the final tracing result will be converted to the legacy JSON
// format.
bool convert_to_legacy_json;
};
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