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

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: 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
OLDNEW
(Empty)
1 // Copyright 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/json/json_string_value_serializer.h"
9 #include "base/lazy_instance.h"
10 #include "base/memory/singleton.h"
11 #include "base/strings/stringprintf.h"
12 #include "content/public/browser/browser_thread.h"
13
14 namespace content {
15
16 namespace {
17
18 const int kEtwBufferSizeInKBytes = 16;
19 const int kEtwBufferFlushTimeoutInSeconds = 1;
20
21 std::string GuidToString(const GUID& guid) {
22 return base::StringPrintf("%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
23 guid.Data1, guid.Data2, guid.Data3,
24 guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
25 guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
26 }
27
28 } // namespace
29
30 EtwSystemEventConsumer::EtwSystemEventConsumer()
31 : thread_("EtwConsumerThread") {
32 }
33
34 EtwSystemEventConsumer::~EtwSystemEventConsumer() {
35 }
36
37 bool EtwSystemEventConsumer::StartSystemTracing() {
38 // Activate kernel tracing.
39 if (!StartKernelSessionTracing())
40 return false;
41
42 // Create the events buffer.
43 events_.reset(new base::ListValue());
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 bool EtwSystemEventConsumer::StopSystemTracing(const OutputCallback& callback) {
56 // Deactivate kernel tracing.
57 if (!StopKernelSessionTracing())
nduca 2014/02/21 05:23:43 little worried about this... if the kernel session
etienneb 2014/02/24 14:59:33 I agree. It can only happen if someone is playing
58 return false;
59
60 // Stop consuming and flush events.
61 OutputCallback on_stop_system_tracing_done_callback =
62 base::Bind(&EtwSystemEventConsumer::OnStopSystemTracingDone,
63 base::Unretained(this),
64 callback);
65 thread_.message_loop()->PostTask(FROM_HERE,
66 base::Bind(&EtwSystemEventConsumer::FlushOnThread,
67 base::Unretained(this), on_stop_system_tracing_done_callback));
68
69 return true;
70 }
71
72 void EtwSystemEventConsumer::OnStopSystemTracingDone(
73 const OutputCallback& callback,
74 const scoped_refptr<base::RefCountedString>& result) {
75
76 // Stop the consumer thread.
77 thread_.Stop();
78
79 // Pass the serialized events.
80 callback.Run(result);
81 }
82
83 bool EtwSystemEventConsumer::StartKernelSessionTracing() {
84 // Enabled flags (tracing facilities).
85 uint32 enabled_flags = EVENT_TRACE_FLAG_IMAGE_LOAD |
86 EVENT_TRACE_FLAG_PROCESS |
87 EVENT_TRACE_FLAG_THREAD |
88 EVENT_TRACE_FLAG_CSWITCH;
89
90 EVENT_TRACE_PROPERTIES& p = *properties_.get();
91 p.LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
92 p.FlushTimer = kEtwBufferFlushTimeoutInSeconds;
93 p.BufferSize = kEtwBufferSizeInKBytes;
94 p.LogFileNameOffset = 0;
95 p.EnableFlags = enabled_flags;
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::AppendEventToBuffer(EVENT_TRACE* event) {
124 using base::FundamentalValue;
125 using base::StringPrintf;
126
127 scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
128
129 // Add header fields to the event.
130 value->Set("ts", new base::StringValue(
131 StringPrintf("%08X%08X",
132 event->Header.TimeStamp.HighPart,
133 event->Header.TimeStamp.LowPart)));
134
135 value->Set("guid", new base::StringValue(GuidToString(event->Header.Guid)));
136
137 value->Set("op", new FundamentalValue(event->Header.Class.Type));
138 value->Set("ver", new FundamentalValue(event->Header.Class.Version));
139 value->Set("pid",
140 new FundamentalValue(static_cast<int>(event->Header.ProcessId)));
141 value->Set("tid",
142 new FundamentalValue(static_cast<int>(event->Header.ThreadId)));
143 value->Set("cpu", new FundamentalValue(event->BufferContext.ProcessorNumber));
144
145 // Base64 encode the payload bytes.
146 base::StringPiece buffer(static_cast<const char*>(event->MofData),
147 event->MofLength);
148 std::string payload;
149 base::Base64Encode(buffer, &payload);
150 value->Set("payload", new base::StringValue(payload));
151
152 // Append it to the events buffer.
153 events_->Append(value.release());
154 }
155
156 void EtwSystemEventConsumer::TraceAndConsumeOnThread() {
157 HRESULT hr = OpenRealtimeSession(KERNEL_LOGGER_NAME);
158 if (FAILED(hr))
159 return;
160 Consume();
161 Close();
162 }
163
164 void EtwSystemEventConsumer::FlushOnThread(const OutputCallback& callback) {
165 // Add the header information to the stream.
166 scoped_ptr<base::DictionaryValue> header(new base::DictionaryValue());
167 header->Set("name", base::Value::CreateStringValue("ETW"));
168 header->Set("content", events_.release());
169
170 // Serialize the results as a JSon string.
171 std::string output;
172 JSONStringValueSerializer serializer(&output);
173 serializer.set_pretty_print(true);
174 serializer.Serialize(*header.get());
175
176 // Pass the result to the UI Thread.
177 scoped_refptr<base::RefCountedString> result =
178 base::RefCountedString::TakeString(&output);
179 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
180 base::Bind(callback, result));
181 }
182
183 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698