Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(282)

Side by Side Diff: content/browser/tracing/tracing_controller_impl.cc

Issue 2833873003: WIP: The tracing service prototype
Patch Set: sync Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 #include "content/browser/tracing/tracing_controller_impl.h" 4 #include "content/browser/tracing/tracing_controller_impl.h"
5 5
6 #include <algorithm> 6 #include <algorithm>
7 #include <memory> 7 #include <memory>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/command_line.h" 11 #include "base/command_line.h"
12 #include "base/cpu.h" 12 #include "base/cpu.h"
13 #include "base/files/file_util.h" 13 #include "base/files/file_util.h"
14 #include "base/guid.h" 14 #include "base/guid.h"
15 #include "base/json/string_escape.h" 15 #include "base/json/string_escape.h"
16 #include "base/macros.h" 16 #include "base/macros.h"
17 #include "base/memory/ref_counted_memory.h" 17 #include "base/memory/ref_counted_memory.h"
18 #include "base/strings/string_number_conversions.h" 18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_split.h"
19 #include "base/sys_info.h" 20 #include "base/sys_info.h"
20 #include "base/threading/sequenced_worker_pool.h" 21 #include "base/threading/sequenced_worker_pool.h"
21 #include "base/threading/thread_task_runner_handle.h" 22 #include "base/threading/thread_task_runner_handle.h"
22 #include "base/time/time.h" 23 #include "base/time/time.h"
23 #include "base/trace_event/trace_event.h" 24 #include "base/trace_event/trace_event.h"
24 #include "build/build_config.h" 25 #include "build/build_config.h"
25 #include "components/tracing/common/process_metrics_memory_dump_provider.h" 26 #include "components/tracing/common/process_metrics_memory_dump_provider.h"
26 #include "content/browser/tracing/file_tracing_provider_impl.h" 27 #include "content/browser/tracing/file_tracing_provider_impl.h"
27 #include "content/browser/tracing/trace_message_filter.h" 28 #include "content/browser/tracing/trace_message_filter.h"
28 #include "content/browser/tracing/tracing_ui.h" 29 #include "content/browser/tracing/tracing_ui.h"
29 #include "content/common/child_process_messages.h" 30 #include "content/common/child_process_messages.h"
30 #include "content/public/browser/browser_message_filter.h" 31 #include "content/public/browser/browser_message_filter.h"
31 #include "content/public/browser/content_browser_client.h" 32 #include "content/public/browser/content_browser_client.h"
32 #include "content/public/browser/gpu_data_manager.h" 33 #include "content/public/browser/gpu_data_manager.h"
33 #include "content/public/browser/tracing_delegate.h" 34 #include "content/public/browser/tracing_delegate.h"
34 #include "content/public/common/child_process_host.h" 35 #include "content/public/common/child_process_host.h"
35 #include "content/public/common/content_client.h" 36 #include "content/public/common/content_client.h"
36 #include "content/public/common/content_switches.h" 37 #include "content/public/common/content_switches.h"
37 #include "gpu/config/gpu_info.h" 38 #include "gpu/config/gpu_info.h"
38 #include "net/base/network_change_notifier.h" 39 #include "net/base/network_change_notifier.h"
40 #include "services/resource_coordinator/tracing/coordinator_impl.h"
41 #include "services/service_manager/public/cpp/connector.h"
39 #include "v8/include/v8-version-string.h" 42 #include "v8/include/v8-version-string.h"
40 43
41 #if (defined(OS_POSIX) && defined(USE_UDEV)) || defined(OS_WIN) || \ 44 #if (defined(OS_POSIX) && defined(USE_UDEV)) || defined(OS_WIN) || \
42 defined(OS_MACOSX) 45 defined(OS_MACOSX)
43 #define ENABLE_POWER_TRACING 46 #define ENABLE_POWER_TRACING
44 #endif 47 #endif
45 48
46 #if defined(ENABLE_POWER_TRACING) 49 #if defined(ENABLE_POWER_TRACING)
47 #include "content/browser/tracing/power_tracing_agent.h" 50 #include "content/browser/tracing/power_tracing_agent.h"
48 #endif 51 #endif
(...skipping 11 matching lines...) Expand all
60 using base::trace_event::TraceLog; 63 using base::trace_event::TraceLog;
61 using base::trace_event::TraceConfig; 64 using base::trace_event::TraceConfig;
62 65
63 namespace content { 66 namespace content {
64 67
65 namespace { 68 namespace {
66 69
67 base::LazyInstance<TracingControllerImpl>::Leaky g_controller = 70 base::LazyInstance<TracingControllerImpl>::Leaky g_controller =
68 LAZY_INSTANCE_INITIALIZER; 71 LAZY_INSTANCE_INITIALIZER;
69 72
70 const char kChromeTracingAgentName[] = "chrome";
71 const char kETWTracingAgentName[] = "etw";
72 const char kArcTracingAgentName[] = "arc";
73 const char kChromeTraceLabel[] = "traceEvents";
74
75 const int kStartTracingTimeoutSeconds = 30;
76 const int kIssueClockSyncTimeoutSeconds = 30;
77 const int kStopTracingRetryTimeMilliseconds = 100;
78
79 std::string GetNetworkTypeString() {
80 switch (net::NetworkChangeNotifier::GetConnectionType()) {
81 case net::NetworkChangeNotifier::CONNECTION_ETHERNET:
82 return "Ethernet";
83 case net::NetworkChangeNotifier::CONNECTION_WIFI:
84 return "WiFi";
85 case net::NetworkChangeNotifier::CONNECTION_2G:
86 return "2G";
87 case net::NetworkChangeNotifier::CONNECTION_3G:
88 return "3G";
89 case net::NetworkChangeNotifier::CONNECTION_4G:
90 return "4G";
91 case net::NetworkChangeNotifier::CONNECTION_NONE:
92 return "None";
93 case net::NetworkChangeNotifier::CONNECTION_BLUETOOTH:
94 return "Bluetooth";
95 case net::NetworkChangeNotifier::CONNECTION_UNKNOWN:
96 default:
97 break;
98 }
99 return "Unknown";
100 }
101
102 std::string GetClockString() {
103 switch (base::TimeTicks::GetClock()) {
104 case base::TimeTicks::Clock::LINUX_CLOCK_MONOTONIC:
105 return "LINUX_CLOCK_MONOTONIC";
106 case base::TimeTicks::Clock::IOS_CF_ABSOLUTE_TIME_MINUS_KERN_BOOTTIME:
107 return "IOS_CF_ABSOLUTE_TIME_MINUS_KERN_BOOTTIME";
108 case base::TimeTicks::Clock::MAC_MACH_ABSOLUTE_TIME:
109 return "MAC_MACH_ABSOLUTE_TIME";
110 case base::TimeTicks::Clock::WIN_QPC:
111 return "WIN_QPC";
112 case base::TimeTicks::Clock::WIN_ROLLOVER_PROTECTED_TIME_GET_TIME:
113 return "WIN_ROLLOVER_PROTECTED_TIME_GET_TIME";
114 }
115
116 NOTREACHED();
117 return std::string();
118 }
119
120 } // namespace 73 } // namespace
121 74
122 TracingController* TracingController::GetInstance() { 75 TracingController* TracingController::GetInstance() {
123 return TracingControllerImpl::GetInstance(); 76 return TracingControllerImpl::GetInstance();
124 } 77 }
125 78
126 TracingControllerImpl::TracingControllerImpl() 79 TracingControllerImpl::TracingControllerImpl() {
127 : pending_start_tracing_ack_count_(0),
128 pending_stop_tracing_ack_count_(0),
129 pending_trace_log_status_ack_count_(0),
130 maximum_trace_buffer_usage_(0),
131 approximate_event_count_(0),
132 pending_clock_sync_ack_count_(0),
133 enabled_tracing_modes_(0) {
134 // Deliberately leaked, like this class. 80 // Deliberately leaked, like this class.
135 base::FileTracing::SetProvider(new FileTracingProviderImpl); 81 base::FileTracing::SetProvider(new FileTracingProviderImpl);
136 } 82 }
137 83
84 void TracingControllerImpl::Initialize(service_manager::Connector* connector) {
85 if (connector) {
86 connector->BindInterface("tracing", &coordinator_);
87 return;
88 }
89 // If connector is null, the coordinator must be running in this process.
90 resource_coordinator::tracing::CoordinatorImpl* coordinator =
91 resource_coordinator::tracing::CoordinatorImpl::GetInstance();
92 DCHECK(coordinator);
93 coordinator->BindCoordinatorRequest(mojo::MakeRequest(&coordinator_));
94 }
95
138 TracingControllerImpl::~TracingControllerImpl() { 96 TracingControllerImpl::~TracingControllerImpl() {
139 // This is a Leaky instance. 97 // This is a Leaky instance.
140 NOTREACHED(); 98 NOTREACHED();
141 } 99 }
142 100
143 TracingControllerImpl* TracingControllerImpl::GetInstance() { 101 TracingControllerImpl* TracingControllerImpl::GetInstance() {
144 return g_controller.Pointer(); 102 return g_controller.Pointer();
145 } 103 }
146 104
147 bool TracingControllerImpl::GetCategories( 105 bool TracingControllerImpl::GetCategories(
148 const GetCategoriesDoneCallback& callback) { 106 const GetCategoriesDoneCallback& callback) {
149 DCHECK_CURRENTLY_ON(BrowserThread::UI); 107 DCHECK_CURRENTLY_ON(BrowserThread::UI);
150 108
151 // Known categories come back from child processes with the EndTracingAck 109 coordinator_->GetCategories(
152 // message. So to get known categories, just begin and end tracing immediately 110 base::BindRepeating(&TracingControllerImpl::GetCategoriesDone,
153 // afterwards. This will ping all the child processes for categories. 111 base::Unretained(this), callback));
154 pending_get_categories_done_callback_ = callback;
155 if (!StartTracing(TraceConfig("*", ""), StartTracingDoneCallback())) {
156 pending_get_categories_done_callback_.Reset();
157 return false;
158 }
159
160 bool ok = StopTracing(NULL);
161 DCHECK(ok);
162 return true; 112 return true;
163 } 113 }
164 114
165 void TracingControllerImpl::SetEnabledOnFileThread( 115 void TracingControllerImpl::GetCategoriesDone(
166 const TraceConfig& trace_config, 116 const GetCategoriesDoneCallback& callback,
167 const base::Closure& callback) { 117 const std::string& categories) {
168 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 118 const std::vector<std::string> split = base::SplitString(
169 119 categories, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
170 TraceLog::GetInstance()->SetEnabled(trace_config, enabled_tracing_modes_); 120 std::set<std::string> category_set;
171 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback); 121 for (const auto& category : split) {
172 } 122 category_set.insert(category);
173 123 }
174 void TracingControllerImpl::SetDisabledOnFileThread( 124 callback.Run(category_set);
175 const base::Closure& callback) {
176 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
177
178 DCHECK(enabled_tracing_modes_);
179 TraceLog::GetInstance()->SetDisabled(enabled_tracing_modes_);
180 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
181 } 125 }
182 126
183 bool TracingControllerImpl::StartTracing( 127 bool TracingControllerImpl::StartTracing(
184 const TraceConfig& trace_config, 128 const TraceConfig& trace_config,
185 const StartTracingDoneCallback& callback) { 129 const StartTracingDoneCallback& callback) {
186 DCHECK_CURRENTLY_ON(BrowserThread::UI); 130 DCHECK_CURRENTLY_ON(BrowserThread::UI);
187 DCHECK(additional_tracing_agents_.empty());
188 131
189 // TODO(ssid): Introduce a priority for tracing agents to handle multiple 132 is_tracing_ = true;
190 // start and stop requests, crbug.com/705087. 133 mojo::DataPipe data_pipe;
191 if (!can_start_tracing()) 134 coordinator_->StartTracing(std::move(data_pipe.producer_handle),
192 return false; 135 trace_config.ToString());
193 start_tracing_done_callback_ = callback; 136 drainer_.reset(new mojo::common::DataPipeDrainer(
194 trace_config_.reset(new base::trace_event::TraceConfig(trace_config)); 137 this, std::move(data_pipe.consumer_handle)));
195 enabled_tracing_modes_ = TraceLog::RECORDING_MODE; 138 if (!callback.is_null())
196 if (!trace_config_->event_filters().empty()) 139 callback.Run();
197 enabled_tracing_modes_ |= TraceLog::FILTERING_MODE;
198 metadata_.reset(new base::DictionaryValue());
199 pending_start_tracing_ack_count_ = 0;
200
201 #if defined(OS_ANDROID)
202 if (pending_get_categories_done_callback_.is_null())
203 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
204 #endif
205
206 if (trace_config.IsSystraceEnabled()) {
207 #if defined(ENABLE_POWER_TRACING)
208 PowerTracingAgent::GetInstance()->StartAgentTracing(
209 trace_config,
210 base::Bind(&TracingControllerImpl::OnStartAgentTracingAcked,
211 base::Unretained(this)));
212 ++pending_start_tracing_ack_count_;
213 #endif
214
215 #if defined(OS_CHROMEOS)
216 chromeos::DebugDaemonClient* debug_daemon =
217 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
218 if (debug_daemon) {
219 debug_daemon->StartAgentTracing(
220 trace_config,
221 base::Bind(&TracingControllerImpl::OnStartAgentTracingAcked,
222 base::Unretained(this)));
223 ++pending_start_tracing_ack_count_;
224 }
225
226 ArcTracingAgent::GetInstance()->StartAgentTracing(
227 trace_config,
228 base::Bind(&TracingControllerImpl::OnStartAgentTracingAcked,
229 base::Unretained(this)));
230 ++pending_start_tracing_ack_count_;
231 #elif defined(OS_WIN)
232 EtwTracingAgent::GetInstance()->StartAgentTracing(
233 trace_config,
234 base::Bind(&TracingControllerImpl::OnStartAgentTracingAcked,
235 base::Unretained(this)));
236 ++pending_start_tracing_ack_count_;
237 #endif
238 }
239
240 // TraceLog may have been enabled in startup tracing before threads are ready.
241 if (TraceLog::GetInstance()->IsEnabled())
242 return true;
243
244 StartAgentTracing(trace_config,
245 base::Bind(&TracingControllerImpl::OnStartAgentTracingAcked,
246 base::Unretained(this)));
247 ++pending_start_tracing_ack_count_;
248
249 // Set a deadline to ensure all agents ack within a reasonable time frame.
250 start_tracing_timer_.Start(
251 FROM_HERE, base::TimeDelta::FromSeconds(kStartTracingTimeoutSeconds),
252 base::Bind(&TracingControllerImpl::OnAllTracingAgentsStarted,
253 base::Unretained(this)));
254
255 return true; 140 return true;
256 } 141 }
257 142
258 void TracingControllerImpl::OnAllTracingAgentsStarted() {
259 DCHECK_CURRENTLY_ON(BrowserThread::UI);
260
261 TRACE_EVENT_API_ADD_METADATA_EVENT(
262 TraceLog::GetCategoryGroupEnabled("__metadata"),
263 "IsTimeTicksHighResolution", "value",
264 base::TimeTicks::IsHighResolution());
265
266 // Notify all child processes.
267 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
268 it != trace_message_filters_.end(); ++it) {
269 it->get()->SendBeginTracing(*trace_config_);
270 }
271
272 if (!start_tracing_done_callback_.is_null())
273 start_tracing_done_callback_.Run();
274
275 start_tracing_done_callback_.Reset();
276 }
277
278 void TracingControllerImpl::AddMetadata(const base::DictionaryValue& data) {
279 if (metadata_)
280 metadata_->MergeDictionary(&data);
281 }
282
283 bool TracingControllerImpl::StopTracing( 143 bool TracingControllerImpl::StopTracing(
284 const scoped_refptr<TraceDataSink>& trace_data_sink) { 144 const scoped_refptr<TraceDataSink>& trace_data_sink) {
285 DCHECK_CURRENTLY_ON(BrowserThread::UI); 145 DCHECK_CURRENTLY_ON(BrowserThread::UI);
286 146
287 if (!can_stop_tracing())
288 return false;
289
290 // If we're still waiting to start tracing, try again after a delay.
291 if (start_tracing_timer_.IsRunning()) {
292 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
293 FROM_HERE,
294 base::Bind(base::IgnoreResult(&TracingControllerImpl::StopTracing),
295 base::Unretained(this), trace_data_sink),
296 base::TimeDelta::FromMilliseconds(kStopTracingRetryTimeMilliseconds));
297 return true;
298 }
299
300 if (trace_data_sink) {
301 MetadataFilterPredicate metadata_filter;
302 if (TraceLog::GetInstance()->GetCurrentTraceConfig()
303 .IsArgumentFilterEnabled()) {
304 std::unique_ptr<TracingDelegate> delegate(
305 GetContentClient()->browser()->GetTracingDelegate());
306 if (delegate)
307 metadata_filter = delegate->GetMetadataFilterPredicate();
308 }
309 AddFilteredMetadata(trace_data_sink.get(), GenerateTracingMetadataDict(),
310 metadata_filter);
311 AddFilteredMetadata(trace_data_sink.get(), std::move(metadata_),
312 metadata_filter);
313 } else {
314 metadata_.reset();
315 }
316
317 trace_data_sink_ = trace_data_sink; 147 trace_data_sink_ = trace_data_sink;
318 trace_config_.reset(); 148 coordinator_->StopAndFlush();
319
320 // Issue clock sync marker before actually stopping tracing.
321 // StopTracingAfterClockSync() will be called after clock sync is done.
322 IssueClockSyncMarker();
323
324 return true; 149 return true;
325 } 150 }
326 151
327 void TracingControllerImpl::StopTracingAfterClockSync() {
328 DCHECK_CURRENTLY_ON(BrowserThread::UI);
329
330 // |pending_clock_sync_ack_count_| could be non-zero if clock sync times out.
331 pending_clock_sync_ack_count_ = 0;
332
333 // Disable local trace early to avoid traces during end-tracing process from
334 // interfering with the process.
335 base::Closure on_stop_tracing_done_callback = base::Bind(
336 &TracingControllerImpl::OnStopTracingDone, base::Unretained(this));
337 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
338 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread,
339 base::Unretained(this),
340 on_stop_tracing_done_callback));
341 }
342
343 void TracingControllerImpl::OnStopTracingDone() {
344 DCHECK_CURRENTLY_ON(BrowserThread::UI);
345
346 #if defined(OS_ANDROID)
347 if (pending_get_categories_done_callback_.is_null())
348 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
349 #endif
350
351 // Count myself (local trace) in pending_stop_tracing_ack_count_,
352 // acked below.
353 pending_stop_tracing_ack_count_ = trace_message_filters_.size() + 1;
354 pending_stop_tracing_filters_ = trace_message_filters_;
355
356 pending_stop_tracing_ack_count_ += additional_tracing_agents_.size();
357 for (auto* it : additional_tracing_agents_) {
358 it->StopAgentTracing(
359 base::Bind(&TracingControllerImpl::OnEndAgentTracingAcked,
360 base::Unretained(this)));
361 }
362 additional_tracing_agents_.clear();
363
364 StopAgentTracing(StopAgentTracingCallback());
365 }
366
367 bool TracingControllerImpl::GetTraceBufferUsage( 152 bool TracingControllerImpl::GetTraceBufferUsage(
368 const GetTraceBufferUsageCallback& callback) { 153 const GetTraceBufferUsageCallback& callback) {
369 DCHECK_CURRENTLY_ON(BrowserThread::UI); 154 DCHECK_CURRENTLY_ON(BrowserThread::UI);
370 155
371 if (!can_get_trace_buffer_usage() || callback.is_null()) 156 coordinator_->RequestBufferUsage(
372 return false; 157 base::BindRepeating(&TracingControllerImpl::GetTraceBufferUsageDone,
373 158 base::Unretained(this), callback));
374 pending_trace_buffer_usage_callback_ = callback;
375
376 // Count myself in pending_trace_log_status_ack_count_, acked below.
377 pending_trace_log_status_ack_count_ = trace_message_filters_.size() + 1;
378 pending_trace_log_status_filters_ = trace_message_filters_;
379 maximum_trace_buffer_usage_ = 0;
380 approximate_event_count_ = 0;
381
382 base::trace_event::TraceLogStatus status =
383 TraceLog::GetInstance()->GetStatus();
384 // Call OnTraceLogStatusReply unconditionally for the browser process.
385 // This will result in immediate execution of the callback if there are no
386 // child processes.
387 BrowserThread::PostTask(
388 BrowserThread::UI, FROM_HERE,
389 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply,
390 base::Unretained(this), nullptr, status));
391
392 // Notify all child processes.
393 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
394 it != trace_message_filters_.end(); ++it) {
395 it->get()->SendGetTraceLogStatus();
396 }
397 return true; 159 return true;
398 } 160 }
399 161
162 void TracingControllerImpl::AddMetadata(const base::DictionaryValue& metadata) {
163 if (metadata_)
164 metadata_->MergeDictionary(&metadata);
165 }
166
400 bool TracingControllerImpl::IsTracing() const { 167 bool TracingControllerImpl::IsTracing() const {
401 return !!enabled_tracing_modes_; 168 return is_tracing_;
169 }
170
171 void TracingControllerImpl::GetTraceBufferUsageDone(
172 const GetTraceBufferUsageCallback& callback,
173 bool success,
174 float percent_full,
175 uint32_t approximate_count) {
176 callback.Run(percent_full, approximate_count);
402 } 177 }
403 178
404 void TracingControllerImpl::AddTraceMessageFilter( 179 void TracingControllerImpl::AddTraceMessageFilter(
405 TraceMessageFilter* trace_message_filter) { 180 TraceMessageFilter* trace_message_filter) {
406 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 181 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
407 BrowserThread::PostTask( 182 BrowserThread::PostTask(
408 BrowserThread::UI, FROM_HERE, 183 BrowserThread::UI, FROM_HERE,
409 base::Bind(&TracingControllerImpl::AddTraceMessageFilter, 184 base::Bind(&TracingControllerImpl::AddTraceMessageFilter,
410 base::Unretained(this), 185 base::Unretained(this),
411 base::RetainedRef(trace_message_filter))); 186 base::RetainedRef(trace_message_filter)));
412 return; 187 return;
413 } 188 }
414 189
415 #if defined(OS_LINUX) 190 #if defined(OS_LINUX)
416 // On Linux the browser process dumps process metrics for child process due to 191 // On Linux the browser process dumps process metrics for child process due to
417 // sandbox. 192 // sandbox.
418 tracing::ProcessMetricsMemoryDumpProvider::RegisterForProcess( 193 tracing::ProcessMetricsMemoryDumpProvider::RegisterForProcess(
419 trace_message_filter->peer_pid()); 194 trace_message_filter->peer_pid());
420 #endif 195 #endif
421 196
422 trace_message_filters_.insert(trace_message_filter); 197 trace_message_filters_.insert(trace_message_filter);
423 if (can_stop_tracing()) {
424 trace_message_filter->SendBeginTracing(
425 TraceLog::GetInstance()->GetCurrentTraceConfig());
426 }
427
428 for (auto& observer : trace_message_filter_observers_) 198 for (auto& observer : trace_message_filter_observers_)
429 observer.OnTraceMessageFilterAdded(trace_message_filter); 199 observer.OnTraceMessageFilterAdded(trace_message_filter);
430 } 200 }
431 201
432 void TracingControllerImpl::RemoveTraceMessageFilter( 202 void TracingControllerImpl::RemoveTraceMessageFilter(
433 TraceMessageFilter* trace_message_filter) { 203 TraceMessageFilter* trace_message_filter) {
434 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 204 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
435 BrowserThread::PostTask( 205 BrowserThread::PostTask(
436 BrowserThread::UI, FROM_HERE, 206 BrowserThread::UI, FROM_HERE,
437 base::Bind(&TracingControllerImpl::RemoveTraceMessageFilter, 207 base::Bind(&TracingControllerImpl::RemoveTraceMessageFilter,
438 base::Unretained(this), 208 base::Unretained(this),
439 base::RetainedRef(trace_message_filter))); 209 base::RetainedRef(trace_message_filter)));
440 return; 210 return;
441 } 211 }
442 212
443 #if defined(OS_LINUX) 213 #if defined(OS_LINUX)
444 tracing::ProcessMetricsMemoryDumpProvider::UnregisterForProcess( 214 tracing::ProcessMetricsMemoryDumpProvider::UnregisterForProcess(
445 trace_message_filter->peer_pid()); 215 trace_message_filter->peer_pid());
446 #endif 216 #endif
447 217
448 // If a filter is removed while a response from that filter is pending then
449 // simulate the response. Otherwise the response count will be wrong and the
450 // completion callback will never be executed.
451 if (pending_stop_tracing_ack_count_ > 0) {
452 TraceMessageFilterSet::const_iterator it =
453 pending_stop_tracing_filters_.find(trace_message_filter);
454 if (it != pending_stop_tracing_filters_.end()) {
455 BrowserThread::PostTask(
456 BrowserThread::UI, FROM_HERE,
457 base::Bind(&TracingControllerImpl::OnStopTracingAcked,
458 base::Unretained(this),
459 base::RetainedRef(trace_message_filter),
460 std::vector<std::string>()));
461 }
462 }
463 if (pending_trace_log_status_ack_count_ > 0) {
464 TraceMessageFilterSet::const_iterator it =
465 pending_trace_log_status_filters_.find(trace_message_filter);
466 if (it != pending_trace_log_status_filters_.end()) {
467 BrowserThread::PostTask(
468 BrowserThread::UI, FROM_HERE,
469 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply,
470 base::Unretained(this),
471 base::RetainedRef(trace_message_filter),
472 base::trace_event::TraceLogStatus()));
473 }
474 }
475 trace_message_filters_.erase(trace_message_filter); 218 trace_message_filters_.erase(trace_message_filter);
476 } 219 }
477 220
478 void TracingControllerImpl::AddTracingAgent(const std::string& agent_name) {
479 #if defined(OS_CHROMEOS)
480 auto* debug_daemon =
481 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
482 if (agent_name == debug_daemon->GetTracingAgentName()) {
483 additional_tracing_agents_.push_back(debug_daemon);
484 debug_daemon->SetStopAgentTracingTaskRunner(
485 BrowserThread::GetBlockingPool());
486 return;
487 }
488
489 if (agent_name == kArcTracingAgentName) {
490 additional_tracing_agents_.push_back(ArcTracingAgent::GetInstance());
491 return;
492 }
493 #elif defined(OS_WIN)
494 auto* etw_agent = EtwTracingAgent::GetInstance();
495 if (agent_name == etw_agent->GetTracingAgentName()) {
496 additional_tracing_agents_.push_back(etw_agent);
497 return;
498 }
499 #endif
500
501 #if defined(ENABLE_POWER_TRACING)
502 auto* power_agent = PowerTracingAgent::GetInstance();
503 if (agent_name == power_agent->GetTracingAgentName()) {
504 additional_tracing_agents_.push_back(power_agent);
505 return;
506 }
507 #endif
508
509 DCHECK(agent_name == kChromeTracingAgentName);
510 }
511
512 void TracingControllerImpl::OnStartAgentTracingAcked(
513 const std::string& agent_name,
514 bool success) {
515 DCHECK_CURRENTLY_ON(BrowserThread::UI);
516
517 // Don't taken any further action if the ack came after the deadline.
518 if (!start_tracing_timer_.IsRunning())
519 return;
520
521 if (success)
522 AddTracingAgent(agent_name);
523
524 if (--pending_start_tracing_ack_count_ == 0) {
525 start_tracing_timer_.Stop();
526 OnAllTracingAgentsStarted();
527 }
528 }
529
530 void TracingControllerImpl::OnStopTracingAcked(
531 TraceMessageFilter* trace_message_filter,
532 const std::vector<std::string>& known_category_groups) {
533 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
534 BrowserThread::PostTask(
535 BrowserThread::UI, FROM_HERE,
536 base::Bind(
537 &TracingControllerImpl::OnStopTracingAcked, base::Unretained(this),
538 base::RetainedRef(trace_message_filter), known_category_groups));
539 return;
540 }
541
542 // Merge known_category_groups with known_category_groups_
543 known_category_groups_.insert(known_category_groups.begin(),
544 known_category_groups.end());
545
546 if (pending_stop_tracing_ack_count_ == 0)
547 return;
548
549 if (trace_message_filter &&
550 !pending_stop_tracing_filters_.erase(trace_message_filter)) {
551 // The response from the specified message filter has already been received.
552 return;
553 }
554
555 if (--pending_stop_tracing_ack_count_ == 1) {
556 // All acks from subprocesses have been received. Now flush the local trace.
557 // During or after this call, our OnLocalTraceDataCollected will be
558 // called with the last of the local trace data.
559 if (trace_data_sink_) {
560 TraceLog::GetInstance()->Flush(
561 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected,
562 base::Unretained(this)),
563 true);
564 } else {
565 TraceLog::GetInstance()->CancelTracing(
566 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected,
567 base::Unretained(this)));
568 }
569 return;
570 }
571
572 if (pending_stop_tracing_ack_count_ != 0)
573 return;
574
575 // All acks (including from the subprocesses and the local trace) have been
576 // received.
577 enabled_tracing_modes_ = 0;
578
579 // Trigger callback if one is set.
580 if (!pending_get_categories_done_callback_.is_null()) {
581 pending_get_categories_done_callback_.Run(known_category_groups_);
582 pending_get_categories_done_callback_.Reset();
583 } else if (trace_data_sink_.get()) {
584 trace_data_sink_->Close();
585 trace_data_sink_ = NULL;
586 }
587 }
588
589 void TracingControllerImpl::OnEndAgentTracingAcked(
590 const std::string& agent_name,
591 const std::string& events_label,
592 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
593 DCHECK_CURRENTLY_ON(BrowserThread::UI);
594
595 if (trace_data_sink_.get() && events_str_ptr &&
596 !events_str_ptr->data().empty()) {
597 if (agent_name == kETWTracingAgentName) {
598 // The Windows kernel events are kept into a JSON format stored as string
599 // and must not be escaped.
600 trace_data_sink_->AddAgentTrace(events_label, events_str_ptr->data());
601 } else if (agent_name == kArcTracingAgentName) {
602 // The ARC events are kept into a JSON format stored as string
603 // and must not be escaped.
604 trace_data_sink_->AddTraceChunk(events_str_ptr->data());
605 } else {
606 trace_data_sink_->AddAgentTrace(
607 events_label, base::GetQuotedJSONString(events_str_ptr->data()));
608 }
609 }
610 std::vector<std::string> category_groups;
611 OnStopTracingAcked(NULL, category_groups);
612 }
613
614 void TracingControllerImpl::OnTraceDataCollected(
615 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
616 // OnTraceDataCollected may be called from any browser thread, either by the
617 // local event trace system or from child processes via TraceMessageFilter.
618 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
619 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
620 base::Bind(&TracingControllerImpl::OnTraceDataCollected,
621 base::Unretained(this), events_str_ptr));
622 return;
623 }
624
625 if (trace_data_sink_.get())
626 trace_data_sink_->AddTraceChunk(events_str_ptr->data());
627 }
628
629 void TracingControllerImpl::OnLocalTraceDataCollected(
630 const scoped_refptr<base::RefCountedString>& events_str_ptr,
631 bool has_more_events) {
632 if (events_str_ptr->data().size())
633 OnTraceDataCollected(events_str_ptr);
634
635 if (has_more_events)
636 return;
637
638 // Simulate an StopTracingAcked for the local trace.
639 std::vector<std::string> category_groups;
640 TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups);
641 OnStopTracingAcked(NULL, category_groups);
642 }
643
644 void TracingControllerImpl::OnTraceLogStatusReply(
645 TraceMessageFilter* trace_message_filter,
646 const base::trace_event::TraceLogStatus& status) {
647 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
648 BrowserThread::PostTask(
649 BrowserThread::UI, FROM_HERE,
650 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply,
651 base::Unretained(this),
652 base::RetainedRef(trace_message_filter), status));
653 return;
654 }
655
656 if (pending_trace_log_status_ack_count_ == 0)
657 return;
658
659 if (trace_message_filter &&
660 !pending_trace_log_status_filters_.erase(trace_message_filter)) {
661 // The response from the specified message filter has already been received.
662 return;
663 }
664
665 float percent_full = static_cast<float>(
666 static_cast<double>(status.event_count) / status.event_capacity);
667 maximum_trace_buffer_usage_ =
668 std::max(maximum_trace_buffer_usage_, percent_full);
669 approximate_event_count_ += status.event_count;
670
671 if (--pending_trace_log_status_ack_count_ == 0) {
672 // Trigger callback if one is set.
673 pending_trace_buffer_usage_callback_.Run(maximum_trace_buffer_usage_,
674 approximate_event_count_);
675 pending_trace_buffer_usage_callback_.Reset();
676 }
677 }
678
679 void TracingControllerImpl::RegisterTracingUI(TracingUI* tracing_ui) { 221 void TracingControllerImpl::RegisterTracingUI(TracingUI* tracing_ui) {
680 DCHECK(tracing_uis_.find(tracing_ui) == tracing_uis_.end()); 222 DCHECK(tracing_uis_.find(tracing_ui) == tracing_uis_.end());
681 tracing_uis_.insert(tracing_ui); 223 tracing_uis_.insert(tracing_ui);
682 } 224 }
683 225
684 void TracingControllerImpl::UnregisterTracingUI(TracingUI* tracing_ui) { 226 void TracingControllerImpl::UnregisterTracingUI(TracingUI* tracing_ui) {
685 std::set<TracingUI*>::iterator it = tracing_uis_.find(tracing_ui); 227 std::set<TracingUI*>::iterator it = tracing_uis_.find(tracing_ui);
686 DCHECK(it != tracing_uis_.end()); 228 DCHECK(it != tracing_uis_.end());
687 tracing_uis_.erase(it); 229 tracing_uis_.erase(it);
688 } 230 }
689 231
690 std::string TracingControllerImpl::GetTracingAgentName() {
691 return kChromeTracingAgentName;
692 }
693
694 std::string TracingControllerImpl::GetTraceEventLabel() {
695 return kChromeTraceLabel;
696 }
697
698 void TracingControllerImpl::StartAgentTracing(
699 const base::trace_event::TraceConfig& trace_config,
700 const StartAgentTracingCallback& callback) {
701 DCHECK_CURRENTLY_ON(BrowserThread::UI);
702
703 base::Closure on_agent_started =
704 base::Bind(callback, kChromeTracingAgentName, true);
705 if (!BrowserThread::PostTask(
706 BrowserThread::FILE, FROM_HERE,
707 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread,
708 base::Unretained(this), trace_config,
709 on_agent_started))) {
710 // BrowserThread::PostTask fails if the threads haven't been created yet,
711 // so it should be safe to just use TraceLog::SetEnabled directly.
712 TraceLog::GetInstance()->SetEnabled(trace_config, enabled_tracing_modes_);
713 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, on_agent_started);
714 }
715 }
716
717 void TracingControllerImpl::StopAgentTracing(
718 const StopAgentTracingCallback& callback) {
719 DCHECK_CURRENTLY_ON(BrowserThread::UI);
720 // Handle special case of zero child processes by immediately flushing the
721 // trace log. Once the flush has completed the caller will be notified that
722 // tracing has ended.
723 if (pending_stop_tracing_ack_count_ == 1) {
724 // Flush/cancel asynchronously now, because we don't have any children to
725 // wait for.
726 if (trace_data_sink_) {
727 TraceLog::GetInstance()->Flush(
728 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected,
729 base::Unretained(this)),
730 true);
731 } else {
732 TraceLog::GetInstance()->CancelTracing(
733 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected,
734 base::Unretained(this)));
735 }
736 }
737
738 // Notify all child processes.
739 for (auto it : trace_message_filters_) {
740 if (trace_data_sink_)
741 it->SendEndTracing();
742 else
743 it->SendCancelTracing();
744 }
745 }
746
747 bool TracingControllerImpl::SupportsExplicitClockSync() {
748 return true;
749 }
750
751 void TracingControllerImpl::RecordClockSyncMarker(
752 const std::string& sync_id,
753 const RecordClockSyncMarkerCallback& callback) {
754 DCHECK(SupportsExplicitClockSync());
755
756 TRACE_EVENT_CLOCK_SYNC_RECEIVER(sync_id);
757 }
758
759 void TracingControllerImpl::IssueClockSyncMarker() {
760 DCHECK_CURRENTLY_ON(BrowserThread::UI);
761 DCHECK_EQ(0, pending_clock_sync_ack_count_);
762
763 for (auto* it : additional_tracing_agents_) {
764 if (it->SupportsExplicitClockSync()) {
765 it->RecordClockSyncMarker(
766 base::GenerateGUID(),
767 base::Bind(&TracingControllerImpl::OnClockSyncMarkerRecordedByAgent,
768 base::Unretained(this)));
769 pending_clock_sync_ack_count_++;
770 }
771 }
772
773 // If no clock sync is needed, stop tracing right away. Otherwise, schedule
774 // to stop tracing after timeout.
775 if (pending_clock_sync_ack_count_ == 0) {
776 StopTracingAfterClockSync();
777 } else {
778 clock_sync_timer_.Start(
779 FROM_HERE, base::TimeDelta::FromSeconds(kIssueClockSyncTimeoutSeconds),
780 this, &TracingControllerImpl::StopTracingAfterClockSync);
781 }
782 }
783
784 void TracingControllerImpl::OnClockSyncMarkerRecordedByAgent(
785 const std::string& sync_id,
786 const base::TimeTicks& issue_ts,
787 const base::TimeTicks& issue_end_ts) {
788 DCHECK_CURRENTLY_ON(BrowserThread::UI);
789
790 // TODO(charliea): Change this function so that it can accept a boolean
791 // success indicator instead of having to rely on sentinel issue_ts and
792 // issue_end_ts values to signal failure.
793 if (!(issue_ts == base::TimeTicks() || issue_end_ts == base::TimeTicks()))
794 TRACE_EVENT_CLOCK_SYNC_ISSUER(sync_id, issue_ts, issue_end_ts);
795
796 // Timer is not running means that clock sync already timed out.
797 if (!clock_sync_timer_.IsRunning())
798 return;
799
800 // Stop tracing only if all agents report back.
801 if (--pending_clock_sync_ack_count_ == 0) {
802 clock_sync_timer_.Stop();
803 StopTracingAfterClockSync();
804 }
805 }
806
807 void TracingControllerImpl::AddFilteredMetadata(
808 TracingController::TraceDataSink* sink,
809 std::unique_ptr<base::DictionaryValue> metadata,
810 const MetadataFilterPredicate& filter) {
811 if (filter.is_null()) {
812 sink->AddMetadata(std::move(metadata));
813 return;
814 }
815 std::unique_ptr<base::DictionaryValue> filtered_metadata(
816 new base::DictionaryValue);
817 for (base::DictionaryValue::Iterator it(*metadata); !it.IsAtEnd();
818 it.Advance()) {
819 if (filter.Run(it.key()))
820 filtered_metadata->Set(it.key(), it.value().DeepCopy());
821 else
822 filtered_metadata->SetString(it.key(), "__stripped__");
823 }
824 sink->AddMetadata(std::move(filtered_metadata));
825 }
826
827 std::unique_ptr<base::DictionaryValue>
828 TracingControllerImpl::GenerateTracingMetadataDict() const {
829 // It's important that this function creates a new metadata dict and returns
830 // it rather than directly populating the metadata_ member, as the data may
831 // need filtering in some cases.
832 std::unique_ptr<base::DictionaryValue> metadata_dict(
833 new base::DictionaryValue());
834
835 metadata_dict->SetString("network-type", GetNetworkTypeString());
836 metadata_dict->SetString("product-version", GetContentClient()->GetProduct());
837 metadata_dict->SetString("v8-version", V8_VERSION_STRING);
838 metadata_dict->SetString("user-agent", GetContentClient()->GetUserAgent());
839
840 // OS
841 #if defined(OS_CHROMEOS)
842 metadata_dict->SetString("os-name", "CrOS");
843 int32_t major_version;
844 int32_t minor_version;
845 int32_t bugfix_version;
846 // OperatingSystemVersion only has a POSIX implementation which returns the
847 // wrong versions for CrOS.
848 base::SysInfo::OperatingSystemVersionNumbers(&major_version, &minor_version,
849 &bugfix_version);
850 metadata_dict->SetString(
851 "os-version", base::StringPrintf("%d.%d.%d", major_version, minor_version,
852 bugfix_version));
853 #else
854 metadata_dict->SetString("os-name", base::SysInfo::OperatingSystemName());
855 metadata_dict->SetString("os-version",
856 base::SysInfo::OperatingSystemVersion());
857 #endif
858 metadata_dict->SetString("os-arch",
859 base::SysInfo::OperatingSystemArchitecture());
860
861 // CPU
862 base::CPU cpu;
863 metadata_dict->SetInteger("cpu-family", cpu.family());
864 metadata_dict->SetInteger("cpu-model", cpu.model());
865 metadata_dict->SetInteger("cpu-stepping", cpu.stepping());
866 metadata_dict->SetInteger("num-cpus", base::SysInfo::NumberOfProcessors());
867 metadata_dict->SetInteger("physical-memory",
868 base::SysInfo::AmountOfPhysicalMemoryMB());
869
870 std::string cpu_brand = cpu.cpu_brand();
871 // Workaround for crbug.com/249713.
872 // TODO(oysteine): Remove workaround when bug is fixed.
873 size_t null_pos = cpu_brand.find('\0');
874 if (null_pos != std::string::npos)
875 cpu_brand.erase(null_pos);
876 metadata_dict->SetString("cpu-brand", cpu_brand);
877
878 // GPU
879 gpu::GPUInfo gpu_info = content::GpuDataManager::GetInstance()->GetGPUInfo();
880
881 #if !defined(OS_ANDROID)
882 metadata_dict->SetInteger("gpu-venid", gpu_info.gpu.vendor_id);
883 metadata_dict->SetInteger("gpu-devid", gpu_info.gpu.device_id);
884 #endif
885
886 metadata_dict->SetString("gpu-driver", gpu_info.driver_version);
887 metadata_dict->SetString("gpu-psver", gpu_info.pixel_shader_version);
888 metadata_dict->SetString("gpu-vsver", gpu_info.vertex_shader_version);
889
890 #if defined(OS_MACOSX)
891 metadata_dict->SetString("gpu-glver", gpu_info.gl_version);
892 #elif defined(OS_POSIX)
893 metadata_dict->SetString("gpu-gl-vendor", gpu_info.gl_vendor);
894 metadata_dict->SetString("gpu-gl-renderer", gpu_info.gl_renderer);
895 #endif
896
897 std::unique_ptr<TracingDelegate> delegate(
898 GetContentClient()->browser()->GetTracingDelegate());
899 if (delegate)
900 delegate->GenerateMetadataDict(metadata_dict.get());
901
902 metadata_dict->SetString("clock-domain", GetClockString());
903 metadata_dict->SetBoolean("highres-ticks",
904 base::TimeTicks::IsHighResolution());
905
906 metadata_dict->SetString("trace-config", trace_config_->ToString());
907
908 metadata_dict->SetString(
909 "command_line",
910 base::CommandLine::ForCurrentProcess()->GetCommandLineString());
911
912 base::Time::Exploded ctime;
913 base::Time::Now().UTCExplode(&ctime);
914 std::string time_string = base::StringPrintf(
915 "%u-%u-%u %d:%d:%d", ctime.year, ctime.month, ctime.day_of_month,
916 ctime.hour, ctime.minute, ctime.second);
917 metadata_dict->SetString("trace-capture-datetime", time_string);
918
919 return metadata_dict;
920 }
921
922 void TracingControllerImpl::AddTraceMessageFilterObserver( 232 void TracingControllerImpl::AddTraceMessageFilterObserver(
923 TraceMessageFilterObserver* observer) { 233 TraceMessageFilterObserver* observer) {
924 DCHECK_CURRENTLY_ON(BrowserThread::UI); 234 DCHECK_CURRENTLY_ON(BrowserThread::UI);
925 trace_message_filter_observers_.AddObserver(observer); 235 trace_message_filter_observers_.AddObserver(observer);
926 236
927 for (auto& filter : trace_message_filters_) 237 for (auto& filter : trace_message_filters_)
928 observer->OnTraceMessageFilterAdded(filter.get()); 238 observer->OnTraceMessageFilterAdded(filter.get());
929 } 239 }
930 240
931 void TracingControllerImpl::RemoveTraceMessageFilterObserver( 241 void TracingControllerImpl::RemoveTraceMessageFilterObserver(
932 TraceMessageFilterObserver* observer) { 242 TraceMessageFilterObserver* observer) {
933 DCHECK_CURRENTLY_ON(BrowserThread::UI); 243 DCHECK_CURRENTLY_ON(BrowserThread::UI);
934 trace_message_filter_observers_.RemoveObserver(observer); 244 trace_message_filter_observers_.RemoveObserver(observer);
935 245
936 for (auto& filter : trace_message_filters_) 246 for (auto& filter : trace_message_filters_)
937 observer->OnTraceMessageFilterRemoved(filter.get()); 247 observer->OnTraceMessageFilterRemoved(filter.get());
938 } 248 }
939 249
250 void TracingControllerImpl::OnDataAvailable(const void* data,
251 size_t num_bytes) {
252 if (trace_data_sink_.get()) {
253 const std::string chunk(static_cast<const char*>(data), num_bytes);
254 trace_data_sink_->AddTraceChunk(chunk);
255 }
256 }
257
258 void TracingControllerImpl::OnDataComplete() {
259 is_tracing_ = false;
260 if (trace_data_sink_.get()) {
261 trace_data_sink_->Close();
262 trace_data_sink_ = NULL;
263 }
264 }
265
940 } // namespace content 266 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/tracing/tracing_controller_impl.h ('k') | content/browser/tracing/tracing_controller_impl_data_sinks.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698