Commit 47281893 authored by Jakub Chyłkowski's avatar Jakub Chyłkowski Committed by Chromium LUCI CQ

Add support for perfetto::TraceConfig in tracing

Currently, the TraceConfig JSON object passed to the DevTools method to
start tracing only supports configuration of the Chrome-internal trace
event data source.

This commit provides additional parameters in DevTools:

- base64-encoded serialized protobuf message which takes precedence
  over other parameters,

- backend selection.

In order to handle new parameters, convert
base::trace_event::TraceConfig to perfetto::TraceConfig before passing
it and add support for the new perfettoConfig protocol param.

Add test to handle Command to run new test:
out/Default/content_browsertests --gtest_filter=DevToolsProtocolTest.TracingWithPerfettoConfig

Bug: chromium:1141381, chromium:1141386
Change-Id: I35e436487b2526bb3bf17bac34b9741712fb5319
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2560581
Commit-Queue: Eric Seckler <eseckler@chromium.org>
Reviewed-by: default avatarAndrey Kosyakov <caseq@chromium.org>
Reviewed-by: default avatarEric Seckler <eseckler@chromium.org>
Cr-Commit-Position: refs/heads/master@{#836082}
parent f997361d
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/security_style_explanations.h" #include "content/public/browser/security_style_explanations.h"
#include "content/public/browser/ssl_status.h" #include "content/public/browser/ssl_status.h"
#include "content/public/browser/tracing_controller.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h" #include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h" #include "content/public/common/url_constants.h"
...@@ -55,6 +56,7 @@ ...@@ -55,6 +56,7 @@
#include "content/shell/browser/shell_browser_context.h" #include "content/shell/browser/shell_browser_context.h"
#include "content/shell/browser/shell_content_browser_client.h" #include "content/shell/browser/shell_content_browser_client.h"
#include "content/shell/browser/shell_download_manager_delegate.h" #include "content/shell/browser/shell_download_manager_delegate.h"
#include "services/tracing/public/cpp/perfetto/perfetto_config.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkColor.h"
...@@ -2683,4 +2685,33 @@ IN_PROC_BROWSER_TEST_F(DevToolsDownloadContentTest, DISABLED_MultiDownload) { ...@@ -2683,4 +2685,33 @@ IN_PROC_BROWSER_TEST_F(DevToolsDownloadContentTest, DISABLED_MultiDownload) {
file2, GetTestFilePath("download", "download-test.lib"))); file2, GetTestFilePath("download", "download-test.lib")));
} }
#endif // !defined(ANDROID) #endif // !defined(ANDROID)
IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, TracingWithPerfettoConfig) {
std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
base::trace_event::TraceConfig chrome_config;
base::DictionaryValue* command_result;
perfetto::TraceConfig perfetto_config;
std::string perfetto_config_encoded;
chrome_config = base::trace_event::TraceConfig();
perfetto_config = tracing::GetDefaultPerfettoConfig(
chrome_config,
/*privacy_filtering_enabled=*/false,
/*convert_to_legacy_json=*/false,
perfetto::protos::gen::ChromeConfig::USER_INITIATED);
base::Base64Encode(perfetto_config.SerializeAsString(),
&perfetto_config_encoded);
params->SetKey("perfettoConfig", base::Value(perfetto_config_encoded));
NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
Attach();
command_result = SendCommand("Tracing.start", std::move(params), true);
ASSERT_NE(command_result, nullptr);
command_result = SendCommand("Tracing.end", nullptr, true);
ASSERT_NE(command_result, nullptr);
WaitForNotification("Tracing.tracingComplete", true);
}
} // namespace content } // namespace content
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "base/json/json_writer.h" #include "base/json/json_writer.h"
#include "base/memory/ref_counted_memory.h" #include "base/memory/ref_counted_memory.h"
#include "base/optional.h" #include "base/optional.h"
#include "base/strings/strcat.h"
#include "base/strings/string_split.h" #include "base/strings/string_split.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/time/time.h" #include "base/time/time.h"
...@@ -220,6 +221,22 @@ StringToMemoryDumpLevelOfDetail(const std::string& str) { ...@@ -220,6 +221,22 @@ StringToMemoryDumpLevelOfDetail(const std::string& str) {
return {}; return {};
} }
void AddPidsToProcessFilter(
const std::unordered_set<base::ProcessId>& included_process_ids,
perfetto::TraceConfig& trace_config) {
for (auto& data_source : *(trace_config.mutable_data_sources())) {
auto* source_config = data_source.mutable_config();
if (source_config->name() == tracing::mojom::kTraceEventDataSourceName) {
for (auto& enabled_pid : included_process_ids) {
*data_source.add_producer_name_filter() = base::StrCat(
{tracing::mojom::kPerfettoProducerNamePrefix,
base::NumberToString(static_cast<uint32_t>(enabled_pid))});
}
break;
}
}
}
// We currently don't support concurrent tracing sessions, but are planning to. // We currently don't support concurrent tracing sessions, but are planning to.
// For the time being, we're using this flag as a workaround to prevent devtools // For the time being, we're using this flag as a workaround to prevent devtools
// users from accidentally starting two concurrent sessions. // users from accidentally starting two concurrent sessions.
...@@ -235,11 +252,12 @@ class TracingHandler::TracingSession { ...@@ -235,11 +252,12 @@ class TracingHandler::TracingSession {
virtual ~TracingSession() = default; virtual ~TracingSession() = default;
virtual void EnableTracing( virtual void EnableTracing(
const base::trace_event::TraceConfig& chrome_config, const perfetto::TraceConfig& perfetto_config,
base::OnceClosure on_recording_enabled_callback) = 0; base::OnceClosure on_recording_enabled_callback) = 0;
virtual void AdoptStartupTracingSession() = 0; virtual void AdoptStartupTracingSession(
const perfetto::TraceConfig& perfetto_config) = 0;
virtual void ChangeTraceConfig( virtual void ChangeTraceConfig(
const base::trace_event::TraceConfig& chrome_config) = 0; const perfetto::TraceConfig& perfetto_config) = 0;
virtual void DisableTracing( virtual void DisableTracing(
bool use_proto_format, bool use_proto_format,
const std::string& agent_label, const std::string& agent_label,
...@@ -263,7 +281,7 @@ class TracingHandler::PerfettoTracingSession ...@@ -263,7 +281,7 @@ class TracingHandler::PerfettoTracingSession
~PerfettoTracingSession() override { DCHECK(!tracing_active_); } ~PerfettoTracingSession() override { DCHECK(!tracing_active_); }
// TracingHandler::TracingSession implementation: // TracingHandler::TracingSession implementation:
void EnableTracing(const base::trace_event::TraceConfig& chrome_config, void EnableTracing(const perfetto::TraceConfig& perfetto_config,
base::OnceClosure on_recording_enabled_callback) override { base::OnceClosure on_recording_enabled_callback) override {
DCHECK(!tracing_session_host_); DCHECK(!tracing_session_host_);
DCHECK(!tracing_active_); DCHECK(!tracing_active_);
...@@ -272,10 +290,14 @@ class TracingHandler::PerfettoTracingSession ...@@ -272,10 +290,14 @@ class TracingHandler::PerfettoTracingSession
GetTracingService().BindConsumerHost( GetTracingService().BindConsumerHost(
consumer_host_.BindNewPipeAndPassReceiver()); consumer_host_.BindNewPipeAndPassReceiver());
perfetto::TraceConfig perfetto_config =
CreatePerfettoConfiguration(chrome_config);
on_recording_enabled_callback_ = std::move(on_recording_enabled_callback); on_recording_enabled_callback_ = std::move(on_recording_enabled_callback);
#if DCHECK_IS_ON()
last_perfetto_config_ = perfetto_config;
for (auto& data_source : *(last_perfetto_config_.mutable_data_sources())) {
data_source.clear_producer_name_filter();
}
#endif
consumer_host_->EnableTracing( consumer_host_->EnableTracing(
tracing_session_host_.BindNewPipeAndPassReceiver(), tracing_session_host_.BindNewPipeAndPassReceiver(),
receiver_.BindNewPipeAndPassRemote(), std::move(perfetto_config)); receiver_.BindNewPipeAndPassRemote(), std::move(perfetto_config));
...@@ -288,21 +310,33 @@ class TracingHandler::PerfettoTracingSession ...@@ -288,21 +310,33 @@ class TracingHandler::PerfettoTracingSession
base::Unretained(this))); base::Unretained(this)));
} }
void AdoptStartupTracingSession() override { void AdoptStartupTracingSession(
const perfetto::TraceConfig& perfetto_config) override {
// Start a perfetto tracing session, which will claim startup tracing data. // Start a perfetto tracing session, which will claim startup tracing data.
DCHECK(!TracingController::GetInstance()->IsTracing()); DCHECK(!TracingController::GetInstance()->IsTracing());
waiting_for_startup_tracing_enabled_ = true; waiting_for_startup_tracing_enabled_ = true;
EnableTracing( EnableTracing(
tracing::TraceStartupConfig::GetInstance()->GetTraceConfig(), perfetto_config,
base::BindOnce(&PerfettoTracingSession::OnStartupTracingEnabled, base::BindOnce(&PerfettoTracingSession::OnStartupTracingEnabled,
base::Unretained(this))); base::Unretained(this)));
} }
void ChangeTraceConfig( void ChangeTraceConfig(
const base::trace_event::TraceConfig& chrome_config) override { const perfetto::TraceConfig& perfetto_config) override {
if (!tracing_session_host_) if (!tracing_session_host_)
return; return;
auto perfetto_config = CreatePerfettoConfiguration(chrome_config);
#if DCHECK_IS_ON()
// Ensure that the process filter is the only thing that gets changed
// in a configuration during a tracing session.
perfetto::TraceConfig config_without_filters = perfetto_config;
for (auto& data_source : *(config_without_filters.mutable_data_sources())) {
data_source.clear_producer_name_filter();
}
DCHECK(config_without_filters == last_perfetto_config_);
last_perfetto_config_ = std::move(config_without_filters);
#endif
tracing_session_host_->ChangeTraceConfig(perfetto_config); tracing_session_host_->ChangeTraceConfig(perfetto_config);
} }
...@@ -410,29 +444,6 @@ class TracingHandler::PerfettoTracingSession ...@@ -410,29 +444,6 @@ class TracingHandler::PerfettoTracingSession
} }
private: private:
perfetto::TraceConfig CreatePerfettoConfiguration(
const base::trace_event::TraceConfig& chrome_config) {
#if DCHECK_IS_ON()
base::trace_event::TraceConfig processfilter_stripped_config(chrome_config);
processfilter_stripped_config.SetProcessFilterConfig(
base::trace_event::TraceConfig::ProcessFilterConfig());
// Ensure that the process filter is the only thing that gets changed
// in a configuration during a tracing session.
DCHECK((last_config_for_perfetto_.ToString() ==
base::trace_event::TraceConfig().ToString()) ||
(last_config_for_perfetto_.ToString() ==
processfilter_stripped_config.ToString()));
last_config_for_perfetto_ = std::move(processfilter_stripped_config);
#endif
return tracing::GetDefaultPerfettoConfig(
chrome_config,
/*privacy_filtering_enabled=*/false,
/*convert_to_legacy_json=*/false,
perfetto::protos::gen::ChromeConfig::USER_INITIATED);
}
void OnStartupTracingEnabled() { void OnStartupTracingEnabled() {
waiting_for_startup_tracing_enabled_ = false; waiting_for_startup_tracing_enabled_ = false;
if (pending_disable_tracing_task_) if (pending_disable_tracing_task_)
...@@ -521,7 +532,7 @@ class TracingHandler::PerfettoTracingSession ...@@ -521,7 +532,7 @@ class TracingHandler::PerfettoTracingSession
bool data_loss_ = false; bool data_loss_ = false;
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
base::trace_event::TraceConfig last_config_for_perfetto_; perfetto::TraceConfig last_perfetto_config_;
#endif #endif
}; };
...@@ -556,7 +567,11 @@ TracingHandler::TracingHandler(FrameTreeNode* frame_tree_node, ...@@ -556,7 +567,11 @@ TracingHandler::TracingHandler(FrameTreeNode* frame_tree_node,
} }
session_ = std::make_unique<PerfettoTracingSession>(); session_ = std::make_unique<PerfettoTracingSession>();
session_->AdoptStartupTracingSession(); base::trace_event::TraceConfig browser_config =
tracing::TraceStartupConfig::GetInstance()->GetTraceConfig();
perfetto::TraceConfig perfetto_config =
CreatePerfettoConfiguration(browser_config);
session_->AdoptStartupTracingSession(perfetto_config);
g_any_agent_tracing = true; g_any_agent_tracing = true;
} }
...@@ -716,6 +731,7 @@ void TracingHandler::Start(Maybe<std::string> categories, ...@@ -716,6 +731,7 @@ void TracingHandler::Start(Maybe<std::string> categories,
Maybe<std::string> transfer_format, Maybe<std::string> transfer_format,
Maybe<std::string> transfer_compression, Maybe<std::string> transfer_compression,
Maybe<Tracing::TraceConfig> config, Maybe<Tracing::TraceConfig> config,
Maybe<Binary> perfetto_config,
std::unique_ptr<StartCallback> callback) { std::unique_ptr<StartCallback> callback) {
bool return_as_stream = transfer_mode.fromMaybe("") == bool return_as_stream = transfer_mode.fromMaybe("") ==
Tracing::Start::TransferModeEnum::ReturnAsStream; Tracing::Start::TransferModeEnum::ReturnAsStream;
...@@ -758,20 +774,32 @@ void TracingHandler::Start(Maybe<std::string> categories, ...@@ -758,20 +774,32 @@ void TracingHandler::Start(Maybe<std::string> categories,
buffer_usage_reporting_interval_ = buffer_usage_reporting_interval_ =
buffer_usage_reporting_interval.fromMaybe(0); buffer_usage_reporting_interval.fromMaybe(0);
trace_config_ = base::trace_event::TraceConfig(); if (perfetto_config.isJust()) {
if (config.isJust()) { bool parsed = trace_config_.ParseFromArray(
std::unique_ptr<base::Value> value = protocol::toBaseValue( perfetto_config.fromJust().data(), perfetto_config.fromJust().size());
protocol::ValueTypeConverter<Tracing::TraceConfig>::ToValue( if (!parsed) {
*config.fromJust()) callback->sendFailure(Response::InvalidParams(
.get(), "Couldn't parse the supplied perfettoConfig."));
1000); return;
if (value && value->is_dict()) { }
trace_config_ = GetTraceConfigFromDevToolsConfig( } else {
*static_cast<base::DictionaryValue*>(value.get())); base::trace_event::TraceConfig browser_config =
base::trace_event::TraceConfig();
if (config.isJust()) {
std::unique_ptr<base::Value> value = protocol::toBaseValue(
protocol::ValueTypeConverter<Tracing::TraceConfig>::ToValue(
*config.fromJust())
.get(),
1000);
if (value && value->is_dict()) {
browser_config = GetTraceConfigFromDevToolsConfig(
*static_cast<base::DictionaryValue*>(value.get()));
}
} else if (categories.isJust() || options.isJust()) {
browser_config = base::trace_event::TraceConfig(categories.fromMaybe(""),
options.fromMaybe(""));
} }
} else if (categories.isJust() || options.isJust()) { trace_config_ = CreatePerfettoConfiguration(browser_config);
trace_config_ = base::trace_event::TraceConfig(categories.fromMaybe(""),
options.fromMaybe(""));
} }
// GPU process id can only be retrieved on IO thread. Do some thread hopping. // GPU process id can only be retrieved on IO thread. Do some thread hopping.
...@@ -807,6 +835,15 @@ void TracingHandler::StartTracingWithGpuPid( ...@@ -807,6 +835,15 @@ void TracingHandler::StartTracingWithGpuPid(
g_any_agent_tracing = true; g_any_agent_tracing = true;
} }
perfetto::TraceConfig TracingHandler::CreatePerfettoConfiguration(
const base::trace_event::TraceConfig& browser_config) {
return tracing::GetDefaultPerfettoConfig(
browser_config,
/*privacy_filtering_enabled=*/false,
/*convert_to_legacy_json=*/false,
perfetto::protos::gen::ChromeConfig::USER_INITIATED);
}
void TracingHandler::SetupProcessFilter( void TracingHandler::SetupProcessFilter(
base::ProcessId gpu_pid, base::ProcessId gpu_pid,
RenderFrameHost* new_render_frame_host) { RenderFrameHost* new_render_frame_host) {
...@@ -828,9 +865,8 @@ void TracingHandler::SetupProcessFilter( ...@@ -828,9 +865,8 @@ void TracingHandler::SetupProcessFilter(
if (frame_host) if (frame_host)
AppendProcessId(frame_host, &included_process_ids); AppendProcessId(frame_host, &included_process_ids);
} }
trace_config_.SetProcessFilterConfig(
base::trace_event::TraceConfig::ProcessFilterConfig( AddPidsToProcessFilter(included_process_ids, trace_config_);
included_process_ids));
} }
void TracingHandler::AppendProcessId( void TracingHandler::AppendProcessId(
...@@ -851,9 +887,8 @@ void TracingHandler::OnProcessReady(RenderProcessHost* process_host) { ...@@ -851,9 +887,8 @@ void TracingHandler::OnProcessReady(RenderProcessHost* process_host) {
return; return;
std::unordered_set<base::ProcessId> included_process_ids( std::unordered_set<base::ProcessId> included_process_ids(
{process_host->GetProcess().Pid()}); {process_host->GetProcess().Pid()});
trace_config_.SetProcessFilterConfig(
base::trace_event::TraceConfig::ProcessFilterConfig( AddPidsToProcessFilter(included_process_ids, trace_config_);
included_process_ids));
session_->ChangeTraceConfig(trace_config_); session_->ChangeTraceConfig(trace_config_);
} }
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "content/browser/devtools/protocol/tracing.h" #include "content/browser/devtools/protocol/tracing.h"
#include "content/common/content_export.h" #include "content/common/content_export.h"
#include "content/public/browser/tracing_controller.h" #include "content/public/browser/tracing_controller.h"
#include "services/tracing/public/cpp/perfetto/perfetto_config.h"
namespace base { namespace base {
class RepeatingTimer; class RepeatingTimer;
...@@ -69,6 +70,7 @@ class TracingHandler : public DevToolsDomainHandler, public Tracing::Backend { ...@@ -69,6 +70,7 @@ class TracingHandler : public DevToolsDomainHandler, public Tracing::Backend {
Maybe<std::string> transfer_format, Maybe<std::string> transfer_format,
Maybe<std::string> transfer_compression, Maybe<std::string> transfer_compression,
Maybe<Tracing::TraceConfig> config, Maybe<Tracing::TraceConfig> config,
Maybe<Binary> perfetto_config,
std::unique_ptr<StartCallback> callback) override; std::unique_ptr<StartCallback> callback) override;
Response End() override; Response End() override;
void GetCategories(std::unique_ptr<GetCategoriesCallback> callback) override; void GetCategories(std::unique_ptr<GetCategoriesCallback> callback) override;
...@@ -124,6 +126,8 @@ class TracingHandler : public DevToolsDomainHandler, public Tracing::Backend { ...@@ -124,6 +126,8 @@ class TracingHandler : public DevToolsDomainHandler, public Tracing::Backend {
CONTENT_EXPORT static base::trace_event::TraceConfig CONTENT_EXPORT static base::trace_event::TraceConfig
GetTraceConfigFromDevToolsConfig( GetTraceConfigFromDevToolsConfig(
const base::DictionaryValue& devtools_config); const base::DictionaryValue& devtools_config);
perfetto::TraceConfig CreatePerfettoConfiguration(
const base::trace_event::TraceConfig& browser_config);
void SetupProcessFilter(base::ProcessId gpu_pid, RenderFrameHost*); void SetupProcessFilter(base::ProcessId gpu_pid, RenderFrameHost*);
void StartTracingWithGpuPid(std::unique_ptr<StartCallback>, void StartTracingWithGpuPid(std::unique_ptr<StartCallback>,
base::ProcessId gpu_pid); base::ProcessId gpu_pid);
...@@ -144,7 +148,7 @@ class TracingHandler : public DevToolsDomainHandler, public Tracing::Backend { ...@@ -144,7 +148,7 @@ class TracingHandler : public DevToolsDomainHandler, public Tracing::Backend {
TraceDataBufferState trace_data_buffer_state_; TraceDataBufferState trace_data_buffer_state_;
std::unique_ptr<DevToolsVideoConsumer> video_consumer_; std::unique_ptr<DevToolsVideoConsumer> video_consumer_;
int number_of_screenshots_from_video_consumer_ = 0; int number_of_screenshots_from_video_consumer_ = 0;
base::trace_event::TraceConfig trace_config_; perfetto::TraceConfig trace_config_;
std::unique_ptr<TracingSession> session_; std::unique_ptr<TracingSession> session_;
base::WeakPtrFactory<TracingHandler> weak_factory_{this}; base::WeakPtrFactory<TracingHandler> weak_factory_{this};
......
...@@ -8078,6 +8078,10 @@ experimental domain Tracing ...@@ -8078,6 +8078,10 @@ experimental domain Tracing
# transfer mode (defaults to `none`) # transfer mode (defaults to `none`)
optional StreamCompression streamCompression optional StreamCompression streamCompression
optional TraceConfig traceConfig optional TraceConfig traceConfig
# Base64-encoded serialized perfetto.protos.TraceConfig protobuf message
# When specified, the parameters `categories`, `options`, `traceConfig`
# are ignored.
optional binary perfettoConfig
event bufferUsage event bufferUsage
parameters parameters
......
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