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

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

Issue 171143002: Implements Windows system tracing. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@tracing
Patch Set: fix android build Created 6 years, 9 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
(Empty)
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/tracing/etw_system_event_consumer_win.h"
6
7 #include "base/base64.h"
8 #include "base/debug/trace_event_impl.h"
9 #include "base/json/json_string_value_serializer.h"
10 #include "base/lazy_instance.h"
11 #include "base/memory/singleton.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/time/time.h"
14 #include "content/public/browser/browser_thread.h"
15
16 namespace content {
17
18 namespace {
19
20 const int kEtwBufferSizeInKBytes = 16;
21 const int kEtwBufferFlushTimeoutInSeconds = 1;
22
23 std::string GuidToString(const GUID& guid) {
24 return base::StringPrintf("%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
25 guid.Data1, guid.Data2, guid.Data3,
26 guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
27 guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
28 }
29
30 } // namespace
31
32 EtwSystemEventConsumer::EtwSystemEventConsumer()
33 : thread_("EtwConsumerThread") {
34 }
35
36 EtwSystemEventConsumer::~EtwSystemEventConsumer() {
37 }
38
39 bool EtwSystemEventConsumer::StartSystemTracing() {
40
41 // Activate kernel tracing.
42 if (!StartKernelSessionTracing())
43 return false;
44
45 // Start the consumer thread and start consuming events.
46 thread_.Start();
47 thread_.message_loop()->PostTask(
48 FROM_HERE,
49 base::Bind(&EtwSystemEventConsumer::TraceAndConsumeOnThread,
50 base::Unretained(this)));
51
52 return true;
53 }
54
55 void EtwSystemEventConsumer::StopSystemTracing(const OutputCallback& callback) {
56 // Deactivate kernel tracing.
57 if (!StopKernelSessionTracing()) {
58 LOG(FATAL) << "Could not stop system tracing.";
59 }
60
61 // Stop consuming and flush events.
62 OutputCallback on_stop_system_tracing_done_callback =
63 base::Bind(&EtwSystemEventConsumer::OnStopSystemTracingDone,
64 base::Unretained(this),
65 callback);
66 thread_.message_loop()->PostTask(FROM_HERE,
67 base::Bind(&EtwSystemEventConsumer::FlushOnThread,
68 base::Unretained(this), on_stop_system_tracing_done_callback));
69 }
70
71 void EtwSystemEventConsumer::OnStopSystemTracingDone(
72 const OutputCallback& callback,
73 const scoped_refptr<base::RefCountedString>& result) {
74
75 // Stop the consumer thread.
76 thread_.Stop();
77
78 // Pass the serialized events.
79 callback.Run(result);
80 }
81
82 bool EtwSystemEventConsumer::StartKernelSessionTracing() {
83 // Enabled flags (tracing facilities).
84 uint32 enabled_flags = EVENT_TRACE_FLAG_IMAGE_LOAD |
85 EVENT_TRACE_FLAG_PROCESS |
86 EVENT_TRACE_FLAG_THREAD |
87 EVENT_TRACE_FLAG_CSWITCH;
88
89 EVENT_TRACE_PROPERTIES& p = *properties_.get();
90 p.LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
91 p.FlushTimer = kEtwBufferFlushTimeoutInSeconds;
92 p.BufferSize = kEtwBufferSizeInKBytes;
93 p.LogFileNameOffset = 0;
94 p.EnableFlags = enabled_flags;
95 p.Wnode.ClientContext = 1; // QPC timer accuracy.
96
97 HRESULT hr = base::win::EtwTraceController::Start(
98 KERNEL_LOGGER_NAME, &properties_, &session_handle_);
99 if (FAILED(hr)) {
100 VLOG(1) << "StartRealtimeSession() failed with " << hr << ".";
101 return false;
102 }
103
104 return true;
105 }
106
107 bool EtwSystemEventConsumer::StopKernelSessionTracing() {
108 HRESULT hr = base::win::EtwTraceController::Stop(
109 KERNEL_LOGGER_NAME, &properties_);
110 return SUCCEEDED(hr);
111 }
112
113 // static
114 EtwSystemEventConsumer* EtwSystemEventConsumer::GetInstance() {
115 return Singleton<EtwSystemEventConsumer>::get();
116 }
117
118 // static
119 void EtwSystemEventConsumer::ProcessEvent(EVENT_TRACE* event) {
120 EtwSystemEventConsumer::GetInstance()->AppendEventToBuffer(event);
121 }
122
123 void EtwSystemEventConsumer::AddSyncEventToBuffer() {
124 // Sync the clocks.
125 base::Time walltime = base::Time::NowFromSystemTime();
126 base::TimeTicks now = base::TimeTicks::NowFromSystemTraceTime();
127
128 LARGE_INTEGER walltime_in_us;
129 walltime_in_us.QuadPart = walltime.ToInternalValue();
130 LARGE_INTEGER now_in_us;
131 now_in_us.QuadPart = now.ToInternalValue();
132
133 // Add fields to the event.
134 scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
135 value->Set("guid", new base::StringValue("ClockSync"));
136 value->Set("walltime", new base::StringValue(
137 base::StringPrintf("%08X%08X",
138 walltime_in_us.HighPart,
139 walltime_in_us.LowPart)));
140 value->Set("tick", new base::StringValue(
141 base::StringPrintf("%08X%08X",
142 now_in_us.HighPart,
143 now_in_us.LowPart)));
144
145 // Append it to the events buffer.
146 events_->Append(value.release());
147 }
148
149 void EtwSystemEventConsumer::AppendEventToBuffer(EVENT_TRACE* event) {
150 using base::FundamentalValue;
151
152 scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
153
154 // Add header fields to the event.
155 LARGE_INTEGER ts_us;
156 ts_us.QuadPart = event->Header.TimeStamp.QuadPart / 10;
157 value->Set("ts", new base::StringValue(
158 base::StringPrintf("%08X%08X", ts_us.HighPart, ts_us.LowPart)));
159
160 value->Set("guid", new base::StringValue(GuidToString(event->Header.Guid)));
161
162 value->Set("op", new FundamentalValue(event->Header.Class.Type));
163 value->Set("ver", new FundamentalValue(event->Header.Class.Version));
164 value->Set("pid",
165 new FundamentalValue(static_cast<int>(event->Header.ProcessId)));
166 value->Set("tid",
167 new FundamentalValue(static_cast<int>(event->Header.ThreadId)));
168 value->Set("cpu", new FundamentalValue(event->BufferContext.ProcessorNumber));
169
170 // Base64 encode the payload bytes.
171 base::StringPiece buffer(static_cast<const char*>(event->MofData),
172 event->MofLength);
173 std::string payload;
174 base::Base64Encode(buffer, &payload);
175 value->Set("payload", new base::StringValue(payload));
176
177 // Append it to the events buffer.
178 events_->Append(value.release());
179 }
180
181 void EtwSystemEventConsumer::TraceAndConsumeOnThread() {
182 // Create the events buffer.
183 events_.reset(new base::ListValue());
184
185 // Output a clock sync event.
186 AddSyncEventToBuffer();
187
188 HRESULT hr = OpenRealtimeSession(KERNEL_LOGGER_NAME);
189 if (FAILED(hr))
190 return;
191 Consume();
192 Close();
193 }
194
195 void EtwSystemEventConsumer::FlushOnThread(const OutputCallback& callback) {
196 // Add the header information to the stream.
197 scoped_ptr<base::DictionaryValue> header(new base::DictionaryValue());
198 header->Set("name", base::Value::CreateStringValue("ETW"));
199
200 // Release and pass the events buffer.
201 header->Set("content", events_.release());
202
203 // Serialize the results as a JSon string.
204 std::string output;
205 JSONStringValueSerializer serializer(&output);
206 serializer.Serialize(*header.get());
207
208 // Pass the result to the UI Thread.
209 scoped_refptr<base::RefCountedString> result =
210 base::RefCountedString::TakeString(&output);
211 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
212 base::Bind(callback, result));
213 }
214
215 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/tracing/etw_system_event_consumer_win.h ('k') | content/browser/tracing/tracing_controller_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698