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

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

Issue 171143002: Implements Windows system tracing. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@tracing
Patch Set: nits Created 6 years, 10 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
« no previous file with comments | « content/browser/tracing/tracing_controller_impl.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 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 4
5 #include "content/browser/tracing/tracing_controller_impl.h" 5 #include "content/browser/tracing/tracing_controller_impl.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/debug/trace_event.h" 8 #include "base/debug/trace_event.h"
9 #include "base/file_util.h" 9 #include "base/file_util.h"
10 #include "base/json/string_escape.h" 10 #include "base/json/string_escape.h"
11 #include "base/strings/string_number_conversions.h" 11 #include "base/strings/string_number_conversions.h"
12 #include "content/browser/tracing/trace_message_filter.h" 12 #include "content/browser/tracing/trace_message_filter.h"
13 #include "content/browser/tracing/tracing_ui.h" 13 #include "content/browser/tracing/tracing_ui.h"
14 #include "content/common/child_process_messages.h" 14 #include "content/common/child_process_messages.h"
15 #include "content/public/browser/browser_message_filter.h" 15 #include "content/public/browser/browser_message_filter.h"
16 #include "content/public/common/content_switches.h" 16 #include "content/public/common/content_switches.h"
17 17
18 #if defined(OS_CHROMEOS) 18 #if defined(OS_CHROMEOS)
19 #include "chromeos/dbus/dbus_thread_manager.h" 19 #include "chromeos/dbus/dbus_thread_manager.h"
20 #include "chromeos/dbus/debug_daemon_client.h" 20 #include "chromeos/dbus/debug_daemon_client.h"
21 #endif 21 #endif
22 22
23 #if defined(OS_WIN)
24 #include "base/values.h"
25 #include "base/json/json_string_value_serializer.h"
26 #include "base/win/event_trace_controller.h"
27 #include "base/win/event_trace_consumer.h"
28 #endif
29
23 using base::debug::TraceLog; 30 using base::debug::TraceLog;
24 31
25 namespace content { 32 namespace content {
26 33
27 namespace { 34 namespace {
28 35
29 base::LazyInstance<TracingControllerImpl>::Leaky g_controller = 36 base::LazyInstance<TracingControllerImpl>::Leaky g_controller =
30 LAZY_INSTANCE_INITIALIZER; 37 LAZY_INSTANCE_INITIALIZER;
31 38
39 #if defined(OS_WIN)
40
41 std::string GuidToString(const GUID& guid) {
42 return base::StringPrintf("%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
43 guid.Data1, guid.Data2, guid.Data3,
44 guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
45 guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
46 }
47
48 class EtwSystemEventConsumer :
49 public base::win::EtwTraceConsumerBase<EtwSystemEventConsumer> {
50 public:
51 typedef base::Callback<void(const scoped_refptr<base::RefCountedString>&)>
52 OutputCallback;
53
54 EtwSystemEventConsumer() : thread_("EtwConsumerThread") {
55 thread_.Start();
56 }
57
58 void RequestStartSystemTracing() {
59 events_.reset(new base::ListValue());
60 thread_.message_loop()->PostTask(
61 FROM_HERE,
62 base::Bind(&EtwSystemEventConsumer::TraceAndConsumeOnThread,
63 base::Unretained(this)));
64 }
65
66 void RequestStopSystemTracing(const OutputCallback& callback) {
67 thread_.message_loop()->PostTask(FROM_HERE,
68 base::Bind(&EtwSystemEventConsumer::StopSystemTracingOnThread,
69 base::Unretained(this), callback));
70 }
71
72 void AppendEventToBuffer(EVENT_TRACE* event) {
fdoray 2014/02/19 16:18:08 Should be private.
etienneb 2014/02/19 17:14:52 Done.
73 using base::Value;
74 using base::StringPrintf;
75
76 scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
77
78 // Add header fields to the event.
79 value->Set("ts", base::Value::CreateStringValue(
80 StringPrintf("%08X%08X",
81 event->Header.TimeStamp.HighPart,
82 event->Header.TimeStamp.LowPart)));
83
84 value->Set("guid", base::Value::CreateStringValue(
85 GuidToString(event->Header.Guid)));
86
87 // TODO(etienneb): CreateIntegerValue are deprecated.
88 value->Set("op", Value::CreateIntegerValue(event->Header.Class.Type));
89 value->Set("ver", Value::CreateIntegerValue(event->Header.Class.Version));
90 value->Set("pid", Value::CreateIntegerValue(event->Header.ProcessId));
91 value->Set("tid", Value::CreateIntegerValue(event->Header.ProcessId));
92 value->Set("cpu", Value::CreateIntegerValue(
93 event->BufferContext.ProcessorNumber));
94
95 // TODO(etienneb): fix it!!!!!
96 value->Set("is64", Value::CreateIntegerValue(1));
97
98 // Encode the payload bytes in hexadecimal.
99 std::string payload =
100 StringToLowerASCII(base::HexEncode(event->MofData, event->MofLength));
fdoray 2014/02/19 16:18:08 Too much indentation. Should be 4 spaces.
etienneb 2014/02/19 17:14:52 Done.
101 value->Set("payload", base::Value::CreateStringValue(payload));
nduca 2014/02/18 22:17:46 oh also should base64 encode?
etienneb 2014/02/19 17:14:52 Done.
102
103 // Append it to the events buffer.
104 events_->Append(value.release());
105 }
106
107 static void ProcessEvent(EVENT_TRACE* event);
108 static EtwSystemEventConsumer* Get();
109
110 bool StartNTKernelSessionTracing() {
111 // Enabled flags (tracing facilities).
112 uint32 enabled_flags = EVENT_TRACE_FLAG_IMAGE_LOAD |
113 EVENT_TRACE_FLAG_PROCESS |
114 EVENT_TRACE_FLAG_THREAD |
115 EVENT_TRACE_FLAG_CSWITCH;
116
117 EVENT_TRACE_PROPERTIES& p = *properties_.get();
118 p.LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
119 p.FlushTimer = 1; // flush every second.
120 p.BufferSize = 16; // 16 K buffers.
dsinclair 2014/02/19 16:29:39 Should these be moved to constants instead of havi
etienneb 2014/02/19 17:14:52 Done.
121 p.LogFileNameOffset = 0;
122 p.EnableFlags = enabled_flags;
123
124 HRESULT hr = base::win::EtwTraceController::Start(
125 KERNEL_LOGGER_NAME, &properties_, &session_handle_);
126 if (FAILED(hr)) {
127 VLOG(1) << "StartRealtimeSession() failed with " << hr << ".";
128 return false;
129 }
130
131 return true;
132 }
133
134 bool StopNTKernelSessionTracing() {
135 HRESULT hr = base::win::EtwTraceController::Stop(
136 KERNEL_LOGGER_NAME, &properties_);
137 return SUCCEEDED(hr);
138 }
139
140 private:
141
fdoray 2014/02/19 16:18:08 No empty line.
etienneb 2014/02/19 17:14:52 Done.
142 void TraceAndConsumeOnThread() {
143 HRESULT hr = OpenRealtimeSession(KERNEL_LOGGER_NAME);
144 if (FAILED(hr))
145 return;
146 Consume();
147 Close();
148 }
149
150 void StopSystemTracingOnThread(const OutputCallback& callback) {
151 // Add the header information to the stream.
152 scoped_ptr<base::DictionaryValue> header(new base::DictionaryValue());
153 header->Set("name", base::Value::CreateStringValue("ETW"));
154 header->Set("content", events_.release());
155
156 // Serialize the results as a JSon string.
157 std::string output;
158 JSONStringValueSerializer serializer(&output);
159 serializer.set_pretty_print(true);
160 serializer.Serialize(*header.get());
161
162 // Pass the result to the UI Thread.
163 scoped_refptr<base::RefCountedString> result =
164 base::RefCountedString::TakeString(&output);
165 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
166 base::Bind(callback, result));
167 }
168
169 scoped_ptr<base::ListValue> events_;
170 base::Thread thread_;
171 TRACEHANDLE session_handle_;
172 base::win::EtwTraceProperties properties_;
173 };
174
175 base::LazyInstance<EtwSystemEventConsumer>::Leaky g_etw_consumer =
176 LAZY_INSTANCE_INITIALIZER;
177
178 EtwSystemEventConsumer* EtwSystemEventConsumer::Get() {
179 return g_etw_consumer.Pointer();
180 }
181
182 void EtwSystemEventConsumer::ProcessEvent(EVENT_TRACE* event) {
183 EtwSystemEventConsumer::Get()->AppendEventToBuffer(event);
184 }
185
186 #endif // OS_WIN
187
32 } // namespace 188 } // namespace
33 189
34 TracingController* TracingController::GetInstance() { 190 TracingController* TracingController::GetInstance() {
35 return TracingControllerImpl::GetInstance(); 191 return TracingControllerImpl::GetInstance();
36 } 192 }
37 193
38 class TracingControllerImpl::ResultFile { 194 class TracingControllerImpl::ResultFile {
39 public: 195 public:
40 explicit ResultFile(const base::FilePath& path); 196 explicit ResultFile(const base::FilePath& path);
41 void Write(const scoped_refptr<base::RefCountedString>& events_str_ptr) { 197 void Write(const scoped_refptr<base::RefCountedString>& events_str_ptr) {
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 void TracingControllerImpl::ResultFile::CloseTask( 278 void TracingControllerImpl::ResultFile::CloseTask(
123 const base::Closure& callback) { 279 const base::Closure& callback) {
124 if (!file_) 280 if (!file_)
125 return; 281 return;
126 282
127 const char* trailevents = "]"; 283 const char* trailevents = "]";
128 size_t written = fwrite(trailevents, strlen(trailevents), 1, file_); 284 size_t written = fwrite(trailevents, strlen(trailevents), 1, file_);
129 DCHECK(written == 1); 285 DCHECK(written == 1);
130 286
131 if (system_trace_) { 287 if (system_trace_) {
288 #if defined(OS_WIN)
289 // TODO(etienneb): This is ugly patch on windows. We should keep Value for
290 // all OS instead of String to represent system traces.
291 std::string json_string = system_trace_->data();
292 #else
132 std::string json_string = base::GetQuotedJSONString(system_trace_->data()); 293 std::string json_string = base::GetQuotedJSONString(system_trace_->data());
294 #endif
133 295
134 const char* systemTraceHead = ", \"systemTraceEvents\": "; 296 const char* systemTraceHead = ",\n\"systemTraceEvents\": ";
135 written = fwrite(systemTraceHead, strlen(systemTraceHead), 1, file_); 297 written = fwrite(systemTraceHead, strlen(systemTraceHead), 1, file_);
136 DCHECK(written == 1); 298 DCHECK(written == 1);
137 299
138 written = fwrite(json_string.data(), json_string.size(), 1, file_); 300 written = fwrite(json_string.data(), json_string.size(), 1, file_);
139 DCHECK(written == 1); 301 DCHECK(written == 1);
140 302
141 system_trace_ = NULL; 303 system_trace_ = NULL;
142 } 304 }
143 305
144 const char* trailout = "}"; 306 const char* trailout = "}";
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 if (pending_get_categories_done_callback_.is_null()) 391 if (pending_get_categories_done_callback_.is_null())
230 TraceLog::GetInstance()->AddClockSyncMetadataEvent(); 392 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
231 #endif 393 #endif
232 394
233 options_ = options; 395 options_ = options;
234 int trace_options = (options & RECORD_CONTINUOUSLY) ? 396 int trace_options = (options & RECORD_CONTINUOUSLY) ?
235 TraceLog::RECORD_CONTINUOUSLY : TraceLog::RECORD_UNTIL_FULL; 397 TraceLog::RECORD_CONTINUOUSLY : TraceLog::RECORD_UNTIL_FULL;
236 if (options & ENABLE_SAMPLING) { 398 if (options & ENABLE_SAMPLING) {
237 trace_options |= TraceLog::ENABLE_SAMPLING; 399 trace_options |= TraceLog::ENABLE_SAMPLING;
238 } 400 }
401
239 #if defined(OS_CHROMEOS) 402 #if defined(OS_CHROMEOS)
240 if (options & ENABLE_SYSTRACE) { 403 if (options & ENABLE_SYSTRACE) {
241 DCHECK(!is_system_tracing_); 404 DCHECK(!is_system_tracing_);
242 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()-> 405 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->
243 StartSystemTracing(); 406 StartSystemTracing();
244 is_system_tracing_ = true; 407 is_system_tracing_ = true;
245 } 408 }
246 #endif 409 #endif
247 410
248 #if defined(OS_WIN) 411 #if defined(OS_WIN)
249 if (options & ENABLE_SYSTRACE) { 412 if (options & ENABLE_SYSTRACE) {
250 DCHECK(!is_system_tracing_); 413 DCHECK(!is_system_tracing_);
251 is_system_tracing_ = true; 414 is_system_tracing_ =
415 EtwSystemEventConsumer::Get()->StartNTKernelSessionTracing();
416 EtwSystemEventConsumer::Get()->RequestStartSystemTracing();
252 } 417 }
253 #endif 418 #endif
254 419
255 base::Closure on_enable_recording_done_callback = 420 base::Closure on_enable_recording_done_callback =
256 base::Bind(&TracingControllerImpl::OnEnableRecordingDone, 421 base::Bind(&TracingControllerImpl::OnEnableRecordingDone,
257 base::Unretained(this), 422 base::Unretained(this),
258 category_filter, trace_options, callback); 423 category_filter, trace_options, callback);
259 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 424 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
260 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread, 425 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread,
261 base::Unretained(this), 426 base::Unretained(this),
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after
685 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()-> 850 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->
686 RequestStopSystemTracing( 851 RequestStopSystemTracing(
687 base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked, 852 base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked,
688 base::Unretained(this))); 853 base::Unretained(this)));
689 return; 854 return;
690 } 855 }
691 #endif 856 #endif
692 857
693 #if defined(OS_WIN) 858 #if defined(OS_WIN)
694 if (is_system_tracing_) { 859 if (is_system_tracing_) {
860 // Disable system tracing.
861 EtwSystemEventConsumer::Get()->StopNTKernelSessionTracing();
695 is_system_tracing_ = false; 862 is_system_tracing_ = false;
863
864 // Request events to be flushed.
865 EtwSystemEventConsumer::Get()->RequestStopSystemTracing(
866 base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked,
867 base::Unretained(this)));
868 return;
696 } 869 }
697 #endif 870 #endif
698 871
699 // Trigger callback if one is set. 872 // Trigger callback if one is set.
700 if (!pending_get_categories_done_callback_.is_null()) { 873 if (!pending_get_categories_done_callback_.is_null()) {
701 pending_get_categories_done_callback_.Run(known_category_groups_); 874 pending_get_categories_done_callback_.Run(known_category_groups_);
702 pending_get_categories_done_callback_.Reset(); 875 pending_get_categories_done_callback_.Reset();
703 } else if (result_file_) { 876 } else if (result_file_) {
704 result_file_->Close( 877 result_file_->Close(
705 base::Bind(&TracingControllerImpl::OnResultFileClosed, 878 base::Bind(&TracingControllerImpl::OnResultFileClosed,
706 base::Unretained(this))); 879 base::Unretained(this)));
707 } 880 }
708 } 881 }
709 882
710 void TracingControllerImpl::OnResultFileClosed() { 883 void TracingControllerImpl::OnResultFileClosed() {
711 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 884 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
712 885
713 if (!result_file_) 886 if (!result_file_)
714 return; 887 return;
715 888
716 if (!pending_disable_recording_done_callback_.is_null()) { 889 if (!pending_disable_recording_done_callback_.is_null()) {
717 pending_disable_recording_done_callback_.Run(result_file_->path()); 890 pending_disable_recording_done_callback_.Run(result_file_->path());
718 pending_disable_recording_done_callback_.Reset(); 891 pending_disable_recording_done_callback_.Reset();
719 } 892 }
720 result_file_.reset(); 893 result_file_.reset();
721 } 894 }
722 895
723 #if defined(OS_CHROMEOS) 896 #if defined(OS_CHROMEOS) || defined(OS_WIN)
724 void TracingControllerImpl::OnEndSystemTracingAcked( 897 void TracingControllerImpl::OnEndSystemTracingAcked(
725 const scoped_refptr<base::RefCountedString>& events_str_ptr) { 898 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
726 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 899 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
727 900
728 if (result_file_) 901 if (result_file_)
729 result_file_->WriteSystemTrace(events_str_ptr); 902 result_file_->WriteSystemTrace(events_str_ptr);
730 903
731 DCHECK(!is_system_tracing_); 904 DCHECK(!is_system_tracing_);
732 OnDisableRecordingComplete(); 905 OnDisableRecordingComplete();
733 } 906 }
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
904 is_monitoring_ = is_monitoring; 1077 is_monitoring_ = is_monitoring;
905 #if !defined(OS_ANDROID) 1078 #if !defined(OS_ANDROID)
906 for (std::set<TracingUI*>::iterator it = tracing_uis_.begin(); 1079 for (std::set<TracingUI*>::iterator it = tracing_uis_.begin();
907 it != tracing_uis_.end(); it++) { 1080 it != tracing_uis_.end(); it++) {
908 (*it)->OnMonitoringStateChanged(is_monitoring); 1081 (*it)->OnMonitoringStateChanged(is_monitoring);
909 } 1082 }
910 #endif 1083 #endif
911 } 1084 }
912 1085
913 } // namespace content 1086 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/tracing/tracing_controller_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698