| Index: content/browser/tracing/tracing_controller_impl.cc
|
| diff --git a/content/browser/tracing/tracing_controller_impl.cc b/content/browser/tracing/tracing_controller_impl.cc
|
| index d17c1226d839ad347a476c91ecd8fce0b401de9b..9ed3c03f2597aa037d38a71245e39060b16cc31e 100644
|
| --- a/content/browser/tracing/tracing_controller_impl.cc
|
| +++ b/content/browser/tracing/tracing_controller_impl.cc
|
| @@ -10,6 +10,8 @@
|
| #include "base/macros.h"
|
| #include "base/strings/string_number_conversions.h"
|
| #include "base/sys_info.h"
|
| +#include "base/thread_task_runner_handle.h"
|
| +#include "base/time/time.h"
|
| #include "base/trace_event/trace_event.h"
|
| #include "build/build_config.h"
|
| #include "components/tracing/process_metrics_memory_dump_provider.h"
|
| @@ -51,7 +53,9 @@ const char kChromeTracingAgentName[] = "chrome";
|
| const char kETWTracingAgentName[] = "etw";
|
| const char kChromeTraceLabel[] = "traceEvents";
|
|
|
| +const int kStartTracingTimeoutSeconds = 30;
|
| const int kIssueClockSyncTimeoutSeconds = 30;
|
| +const int kStopTracingRetryTimeMilliseconds = 100;
|
|
|
| std::string GetNetworkTypeString() {
|
| switch (net::NetworkChangeNotifier::GetConnectionType()) {
|
| @@ -145,7 +149,8 @@ TracingController* TracingController::GetInstance() {
|
| }
|
|
|
| TracingControllerImpl::TracingControllerImpl()
|
| - : pending_stop_tracing_ack_count_(0),
|
| + : pending_start_tracing_ack_count_(0),
|
| + pending_stop_tracing_ack_count_(0),
|
| pending_capture_monitoring_snapshot_ack_count_(0),
|
| pending_trace_log_status_ack_count_(0),
|
| maximum_trace_buffer_usage_(0),
|
| @@ -219,6 +224,9 @@ bool TracingControllerImpl::StartTracing(
|
| return false;
|
| is_tracing_ = true;
|
| start_tracing_done_callback_ = callback;
|
| + start_tracing_trace_config_.reset(
|
| + new base::trace_event::TraceConfig(trace_config));
|
| + pending_start_tracing_ack_count_ = 0;
|
|
|
| #if defined(OS_ANDROID)
|
| if (pending_get_categories_done_callback_.is_null())
|
| @@ -226,57 +234,88 @@ bool TracingControllerImpl::StartTracing(
|
| #endif
|
|
|
| if (trace_config.IsSystraceEnabled()) {
|
| - if (PowerTracingAgent::GetInstance()->StartAgentTracing(trace_config))
|
| - additional_tracing_agents_.push_back(PowerTracingAgent::GetInstance());
|
| + PowerTracingAgent::GetInstance()->StartAgentTracing(
|
| + trace_config,
|
| + base::Bind(&TracingControllerImpl::OnStartAgentTracingAcked,
|
| + base::Unretained(this)));
|
| + ++pending_start_tracing_ack_count_;
|
| +
|
| #if defined(OS_CHROMEOS)
|
| chromeos::DebugDaemonClient* debug_daemon =
|
| chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
|
| - if (debug_daemon && debug_daemon->StartAgentTracing(trace_config)) {
|
| - debug_daemon->SetStopAgentTracingTaskRunner(
|
| - BrowserThread::GetBlockingPool());
|
| - additional_tracing_agents_.push_back(
|
| - chromeos::DBusThreadManager::Get()->GetDebugDaemonClient());
|
| + if (debug_daemon) {
|
| + debug_daemon->StartAgentTracing(
|
| + trace_config,
|
| + base::Bind(&TracingControllerImpl::OnStartAgentTracingAcked,
|
| + base::Unretained(this)));
|
| + ++pending_start_tracing_ack_count_;
|
| }
|
| #elif defined(OS_WIN)
|
| - if (EtwSystemEventConsumer::GetInstance()->StartAgentTracing(
|
| - trace_config)) {
|
| - additional_tracing_agents_.push_back(
|
| - EtwSystemEventConsumer::GetInstance());
|
| - }
|
| + EtwSystemEventConsumer::GetInstance()->StartAgentTracing(
|
| + trace_config,
|
| + base::Bind(&TracingControllerImpl::OnStartAgentTracingAcked,
|
| + base::Unretained(this)));
|
| + ++pending_start_tracing_ack_count_;
|
| #endif
|
| }
|
|
|
| // TraceLog may have been enabled in startup tracing before threads are ready.
|
| if (TraceLog::GetInstance()->IsEnabled())
|
| return true;
|
| - return StartAgentTracing(trace_config);
|
| +
|
| + StartAgentTracing(trace_config,
|
| + base::Bind(&TracingControllerImpl::OnStartAgentTracingAcked,
|
| + base::Unretained(this)));
|
| + ++pending_start_tracing_ack_count_;
|
| +
|
| + // Set a deadline to ensure all agents ack within a reasonable time frame.
|
| + start_tracing_timer_.Start(
|
| + FROM_HERE, base::TimeDelta::FromSeconds(kStartTracingTimeoutSeconds),
|
| + base::Bind(&TracingControllerImpl::OnAllTracingAgentsStarted,
|
| + base::Unretained(this)));
|
| +
|
| + return true;
|
| }
|
|
|
| -void TracingControllerImpl::OnStartAgentTracingDone(
|
| - const TraceConfig& trace_config) {
|
| +void TracingControllerImpl::OnAllTracingAgentsStarted() {
|
| DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
| TRACE_EVENT_API_ADD_METADATA_EVENT("IsTimeTicksHighResolution", "value",
|
| base::TimeTicks::IsHighResolution());
|
| - TRACE_EVENT_API_ADD_METADATA_EVENT("TraceConfig", "value",
|
| - trace_config.AsConvertableToTraceFormat());
|
| + TRACE_EVENT_API_ADD_METADATA_EVENT(
|
| + "TraceConfig", "value",
|
| + start_tracing_trace_config_->AsConvertableToTraceFormat());
|
|
|
| // Notify all child processes.
|
| for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
|
| it != trace_message_filters_.end(); ++it) {
|
| - it->get()->SendBeginTracing(trace_config);
|
| + it->get()->SendBeginTracing(*start_tracing_trace_config_);
|
| }
|
|
|
| - if (!start_tracing_done_callback_.is_null()) {
|
| + if (!start_tracing_done_callback_.is_null())
|
| start_tracing_done_callback_.Run();
|
| - start_tracing_done_callback_.Reset();
|
| - }
|
| +
|
| + start_tracing_done_callback_.Reset();
|
| + start_tracing_trace_config_.reset();
|
| }
|
|
|
| bool TracingControllerImpl::StopTracing(
|
| const scoped_refptr<TraceDataSink>& trace_data_sink) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
| + if (!can_stop_tracing())
|
| + return false;
|
| +
|
| + // If we're still waiting to start tracing, try again after a delay.
|
| + if (start_tracing_timer_.IsRunning()) {
|
| + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
|
| + FROM_HERE,
|
| + base::Bind(base::IgnoreResult(&TracingControllerImpl::StopTracing),
|
| + base::Unretained(this), trace_data_sink),
|
| + base::TimeDelta::FromMilliseconds(kStopTracingRetryTimeMilliseconds));
|
| + return true;
|
| + }
|
| +
|
| if (trace_data_sink) {
|
| if (TraceLog::GetInstance()->GetCurrentTraceConfig()
|
| .IsArgumentFilterEnabled()) {
|
| @@ -290,9 +329,6 @@ bool TracingControllerImpl::StopTracing(
|
| trace_data_sink->AddMetadata(*GenerateTracingMetadataDict().get());
|
| }
|
|
|
| - if (!can_stop_tracing())
|
| - return false;
|
| -
|
| trace_data_sink_ = trace_data_sink;
|
|
|
| // Issue clock sync marker before actually stopping tracing.
|
| @@ -649,6 +685,51 @@ void TracingControllerImpl::RemoveTraceMessageFilter(
|
| trace_message_filters_.erase(trace_message_filter);
|
| }
|
|
|
| +void TracingControllerImpl::AddTracingAgent(const std::string& agent_name) {
|
| +#if defined(OS_CHROMEOS)
|
| + auto debug_daemon =
|
| + chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
|
| + if (agent_name == debug_daemon->GetTracingAgentName()) {
|
| + additional_tracing_agents_.push_back(debug_daemon);
|
| + debug_daemon->SetStopAgentTracingTaskRunner(
|
| + BrowserThread::GetBlockingPool());
|
| + return;
|
| + }
|
| +#elif defined(OS_WIN)
|
| + auto etw_agent = EtwSystemEventConsumer::GetInstance();
|
| + if (agent_name == etw_agent->GetTracingAgentName()) {
|
| + additional_tracing_agents_.push_back(etw_agent);
|
| + return;
|
| + }
|
| +#endif
|
| +
|
| + auto power_agent = PowerTracingAgent::GetInstance();
|
| + if (agent_name == power_agent->GetTracingAgentName()) {
|
| + additional_tracing_agents_.push_back(power_agent);
|
| + return;
|
| + }
|
| +
|
| + DCHECK(agent_name == kChromeTracingAgentName);
|
| +}
|
| +
|
| +void TracingControllerImpl::OnStartAgentTracingAcked(
|
| + const std::string& agent_name,
|
| + bool success) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| +
|
| + // Don't taken any further action if the ack came after the deadline.
|
| + if (!start_tracing_timer_.IsRunning())
|
| + return;
|
| +
|
| + if (success)
|
| + AddTracingAgent(agent_name);
|
| +
|
| + if (--pending_start_tracing_ack_count_ == 0) {
|
| + start_tracing_timer_.Stop();
|
| + OnAllTracingAgentsStarted();
|
| + }
|
| +}
|
| +
|
| void TracingControllerImpl::OnStopTracingAcked(
|
| TraceMessageFilter* trace_message_filter,
|
| const std::vector<std::string>& known_category_groups) {
|
| @@ -890,28 +971,25 @@ std::string TracingControllerImpl::GetTraceEventLabel() {
|
| return kChromeTraceLabel;
|
| }
|
|
|
| -bool TracingControllerImpl::StartAgentTracing(
|
| - const base::trace_event::TraceConfig& trace_config) {
|
| +void TracingControllerImpl::StartAgentTracing(
|
| + const base::trace_event::TraceConfig& trace_config,
|
| + const StartAgentTracingCallback& callback) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
| - base::Closure on_start_tracing_done_callback =
|
| - base::Bind(&TracingControllerImpl::OnStartAgentTracingDone,
|
| - base::Unretained(this), trace_config);
|
| + base::Closure on_agent_started =
|
| + base::Bind(callback, kChromeTracingAgentName, true);
|
| if (!BrowserThread::PostTask(
|
| BrowserThread::FILE, FROM_HERE,
|
| base::Bind(&TracingControllerImpl::SetEnabledOnFileThread,
|
| base::Unretained(this), trace_config,
|
| base::trace_event::TraceLog::RECORDING_MODE,
|
| - on_start_tracing_done_callback))) {
|
| + on_agent_started))) {
|
| // BrowserThread::PostTask fails if the threads haven't been created yet,
|
| // so it should be safe to just use TraceLog::SetEnabled directly.
|
| base::trace_event::TraceLog::GetInstance()->SetEnabled(
|
| trace_config, base::trace_event::TraceLog::RECORDING_MODE);
|
| - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
| - on_start_tracing_done_callback);
|
| + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, on_agent_started);
|
| }
|
| -
|
| - return true;
|
| }
|
|
|
| void TracingControllerImpl::StopAgentTracing(
|
|
|