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

Side by Side Diff: base/debug/trace_event.cc

Issue 6862002: Merge gpu_trace_event back into base/debug/trace_event (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: merge to r83717 Created 9 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "base/debug/trace_event.h" 5 #include "base/debug/trace_event.h"
6 6
7 #if defined(OS_WIN)
8 #include "base/debug/trace_event_win.h"
9 #endif
7 #include "base/format_macros.h" 10 #include "base/format_macros.h"
8 #include "base/file_path.h"
9 #include "base/file_util.h"
10 #include "base/path_service.h"
11 #include "base/process_util.h" 11 #include "base/process_util.h"
12 #include "base/stringprintf.h" 12 #include "base/stringprintf.h"
13 #include "base/threading/platform_thread.h"
14 #include "base/utf_string_conversions.h" 13 #include "base/utf_string_conversions.h"
15 #include "base/time.h" 14 #include "base/time.h"
16 15
17 #define USE_UNRELIABLE_NOW 16 #define USE_UNRELIABLE_NOW
18 17
19 namespace base { 18 namespace base {
20 namespace debug { 19 namespace debug {
21 20
22 static const char* kEventTypeNames[] = { 21 // Controls the number of trace events we will buffer in-memory
23 "BEGIN", 22 // before throwing them away.
24 "END", 23 #define TRACE_EVENT_BUFFER_SIZE 500000
25 "INSTANT" 24 #define TRACE_EVENT_BATCH_SIZE 1000
26 }; 25
27 26 #define TRACE_EVENT_MAX_CATEGORIES 42
28 static const FilePath::CharType* kLogFileName = 27
29 FILE_PATH_LITERAL("trace_%d.log"); 28 static TraceCategory g_categories[TRACE_EVENT_MAX_CATEGORIES];
Sigurður Ásgeirsson 2011/05/02 19:28:41 This will unfortunately not work, and will not pas
scheib 2011/05/04 02:14:15 Converted to POD.
29 static int g_category_index = 0;
30
31 ////////////////////////////////////////////////////////////////////////////////
32 //
33 // TraceLog::Category
34 //
35 ////////////////////////////////////////////////////////////////////////////////
36 TraceCategory::TraceCategory()
37 : enabled_(false), name_(NULL) {
38 }
39
40 TraceCategory::~TraceCategory() {
41 enabled_ = false;
42 }
43
44 ////////////////////////////////////////////////////////////////////////////////
45 //
46 // TraceValue
47 //
48 ////////////////////////////////////////////////////////////////////////////////
49
50 void TraceValue::Destroy() {
51 if (type_ == TRACE_TYPE_STRING) {
52 free(value_.as_string);
Sigurður Ásgeirsson 2011/05/02 19:28:41 Per http://codesearch.google.com/codesearch/p?hl=e
scheib 2011/05/04 02:14:15 Done.
53 value_.as_string = NULL;
54 }
55 type_ = TRACE_TYPE_UNDEFINED;
56 value_.as_uint = 0ull;
57 }
58
59 TraceValue& TraceValue::operator=(const TraceValue& rhs) {
60 DCHECK(sizeof(value_) == sizeof(uint64));
Sigurður Ásgeirsson 2011/05/02 19:28:41 COMPILE_ASSERT?
scheib 2011/05/04 02:14:15 Refactored, assert not needed.
61 Destroy();
62 type_ = rhs.type_;
63 if (rhs.type_ == TRACE_TYPE_STRING) {
64 value_.as_string = base::strdup(rhs.value_.as_string);
65 } else {
66 // Copy all 64 bits for all other types.
Sigurður Ásgeirsson 2011/05/02 19:28:41 Move the assert from above here, by way of documen
scheib 2011/05/04 02:14:15 Refactored, assert not needed.
67 value_.as_uint = rhs.value_.as_uint;
68 }
69 return *this;
70 }
71
72 bool TraceValue::operator==(const TraceValue& rhs) const {
73 if (type_ != rhs.type())
74 return false;
75 if (rhs.type_ == TRACE_TYPE_STRING) {
76 return (strcmp(value_.as_string, rhs.value_.as_string) == 0);
77 } else {
78 // Compare all 64 bits for all other types. Unused bits are set to zero
79 // by the constructors of types that may be less than 64 bits.
80 return (value_.as_uint == rhs.value_.as_uint);
Sigurður Ásgeirsson 2011/05/02 19:28:41 mmmm, are you sure that doubles have a canonical r
scheib 2011/05/04 02:14:15 Refactored, assert not needed.
81 }
82 }
83
84 void TraceValue::AppendAsJSON(std::string* out) const {
85 char temp_string[128];
86 std::string::size_type start_pos;
87 switch (type_) {
88 case TRACE_TYPE_BOOL:
89 *out += as_bool()? "true" : "false";
90 break;
91 case TRACE_TYPE_UINT:
92 base::snprintf(temp_string, sizeof(temp_string), "%llu",
Sigurður Ásgeirsson 2011/05/02 19:28:41 nit: sizeof->arraysize
scheib 2011/05/04 02:14:15 Done.
93 static_cast<unsigned long long>(as_uint()));
94 *out += temp_string;
95 break;
96 case TRACE_TYPE_INT:
97 base::snprintf(temp_string, sizeof(temp_string), "%lld",
98 static_cast<long long>(as_int()));
99 *out += temp_string;
100 break;
101 case TRACE_TYPE_DOUBLE:
102 base::snprintf(temp_string, sizeof(temp_string), "%f", as_double());
103 *out += temp_string;
104 break;
105 case TRACE_TYPE_POINTER:
106 base::snprintf(temp_string, sizeof(temp_string), "%llu",
107 static_cast<unsigned long long>(
108 reinterpret_cast<intptr_t>(
109 as_pointer())));
110 *out += temp_string;
111 break;
112 case TRACE_TYPE_STRING:
113 *out += "\"";
114 start_pos = out->size();
115 *out += as_string();
116 // replace " character with '
117 while ((start_pos = out->find_first_of('\"', start_pos)) !=
118 std::string::npos)
119 (*out)[start_pos] = '\'';
120 *out += "\"";
121 break;
122 default:
123 break;
124 }
125 }
126
127 ////////////////////////////////////////////////////////////////////////////////
128 //
129 // TraceEvent
130 //
131 ////////////////////////////////////////////////////////////////////////////////
132
133 namespace {
134
135 const char* GetPhaseStr(TraceEventPhase phase) {
136 switch(phase) {
137 case TRACE_EVENT_PHASE_BEGIN:
Sigurður Ásgeirsson 2011/05/02 19:28:41 nit: see style guide for indentation: http://googl
scheib 2011/05/04 02:14:15 Done.
138 return "B";
139 case TRACE_EVENT_PHASE_INSTANT:
140 return "I";
141 case TRACE_EVENT_PHASE_END:
142 return "E";
143 default:
144 DCHECK(false);
Sigurður Ásgeirsson 2011/05/02 19:28:41 NOTREACHED() << "Some comment";?
scheib 2011/05/04 02:14:15 Done.
145 return "?";
146 }
147 }
148
149 } // namespace
150
151 TraceEvent::TraceEvent()
152 : process_id(0),
153 thread_id(0),
154 phase(TRACE_EVENT_PHASE_BEGIN),
155 category(NULL),
156 name(NULL) {
157 memset(&arg_names, 0, sizeof(arg_names));
158 }
159
160 TraceEvent::~TraceEvent() {
161 }
162
Sigurður Ásgeirsson 2011/05/02 19:28:41 nit: spurious line.
scheib 2011/05/04 02:14:15 Done.
163
164 void TraceEvent::AppendEventsAsJSON(const std::vector<TraceEvent>& events,
165 size_t start,
Sigurður Ásgeirsson 2011/05/02 19:28:41 nit: align to bracket.
scheib 2011/05/04 02:14:15 Done.
166 size_t count,
167 std::string* out) {
168 *out += "[";
169 for (size_t i = 0; i < count && start + i < events.size(); ++i) {
170 if (i > 0)
171 *out += ",";
172 events[i + start].AppendAsJSON(out);
173 }
174 *out += "]";
175 }
176
177 void TraceEvent::AppendAsJSON(std::string* out) const {
178 const char* phase_str = GetPhaseStr(phase);
179 int64 time_int64 = timestamp.ToInternalValue();
180 StringAppendF(out,
181 "{\"cat\":\"%s\",\"pid\":%i,\"tid\":%i,\"ts\":%lld,"
Sigurður Ásgeirsson 2011/05/02 19:28:41 nit: the JSON won't be well-formed if any of the s
scheib 2011/05/04 02:14:15 Done.
182 "\"ph\":\"%s\",\"name\":\"%s\",\"args\":{",
183 category->name(),
184 static_cast<int>(process_id),
185 static_cast<int>(thread_id),
186 static_cast<long long>(time_int64),
187 phase_str,
188 name);
189
190 // Output argument names and values, stop at first NULL argument name.
191 for (int i = 0; i < TRACE_MAX_NUM_ARGS && arg_names[i]; ++i) {
192 if (i > 0)
193 *out += ",";
194 *out += "\"";
195 *out += arg_names[i];
196 *out += "\":";
197 arg_values[i].AppendAsJSON(out);
198 }
199 *out += "}}";
200 }
201
202 ////////////////////////////////////////////////////////////////////////////////
203 //
204 // TraceLog
205 //
206 ////////////////////////////////////////////////////////////////////////////////
30 207
31 // static 208 // static
32 TraceLog* TraceLog::GetInstance() { 209 TraceLog* TraceLog::GetInstance() {
33 return Singleton<TraceLog, DefaultSingletonTraits<TraceLog> >::get(); 210 return Singleton<TraceLog, StaticMemorySingletonTraits<TraceLog> >::get();
34 } 211 }
35 212
36 // static 213 TraceLog::TraceLog()
37 bool TraceLog::IsTracing() { 214 : enabled_(false) {
38 return TraceLog::GetInstance()->enabled_; 215 logged_events_.reserve(1024);
39 } 216 }
40 217
41 // static 218 TraceLog::~TraceLog() {
42 bool TraceLog::StartTracing() { 219 }
43 return TraceLog::GetInstance()->Start(); 220
44 } 221 TraceCategory* TraceLog::GetCategory(const char* name) {
45 222 TraceLog* tracelog = GetInstance();
46 // static 223 if (!tracelog){
47 void TraceLog::StopTracing() { 224 static TraceCategory false_category_after_shutdown = TraceCategory();
48 return TraceLog::GetInstance()->Stop(); 225 return &false_category_after_shutdown;
49 } 226 }
50 227 return tracelog->GetCategoryInternal(name);
51 void TraceLog::Trace(const std::string& name, 228 }
52 EventType type, 229
53 const void* id, 230 TraceCategory* TraceLog::GetCategoryInternal(const char* name) {
54 const std::wstring& extra, 231 AutoLock lock(lock_);
55 const char* file, 232 for (int i = 0; i < g_category_index; i++) {
56 int line) { 233 if (strcmp(g_categories[i].name(), name) == 0)
57 if (!enabled_) 234 return &g_categories[i];
235 }
236 CHECK(g_category_index < TRACE_EVENT_MAX_CATEGORIES) <<
Sigurður Ásgeirsson 2011/05/02 19:28:41 This seems quite severe for release builds. Assumi
scheib 2011/05/04 02:14:15 Done. Two special case categories added for post
237 "must increase TRACE_EVENT_MAX_CATEGORIES";
238 int new_index = g_category_index++;
239 g_categories[new_index].set(name, enabled_);
240 return &g_categories[new_index];
241 }
242
243 void TraceLog::SetEnabled(bool enabled) {
244 {
245 AutoLock lock(lock_);
246 if (enabled == enabled_)
247 return;
248 enabled_ = enabled;
249 for (int i = 0; i < g_category_index; i++) {
250 g_categories[i].enabled_ = enabled;
251 }
252 }
253 if (!enabled)
254 Flush();
255 }
256
257 float TraceLog::GetBufferPercentFull() const {
258 return (float)((double)logged_events_.size()/(double)TRACE_EVENT_BUFFER_SIZE);
259 }
260
261 void TraceLog::SetOutputCallback(TraceLog::OutputCallback* cb) {
262 Flush();
263 AutoLock lock(lock_);
264 output_callback_.reset(cb);
265 }
266
267 void TraceLog::SetBufferFullCallback(TraceLog::BufferFullCallback* cb) {
268 AutoLock lock(lock_);
269 buffer_full_callback_.reset(cb);
270 }
271
272 void TraceLog::AddRemotelyCollectedData(const std::string& json_events) {
273 AutoLock lock(lock_);
274 if (output_callback_.get())
275 output_callback_->Run(json_events);
276 }
277
278 void TraceLog::Flush() {
279 std::vector<TraceEvent> previous_logged_events;
280 {
281 AutoLock lock(lock_);
282 previous_logged_events.swap(logged_events_);
283 }
284
285 for (size_t i = 0;
286 i < previous_logged_events.size();
287 i += TRACE_EVENT_BATCH_SIZE) {
288 std::string json_events;
289 TraceEvent::AppendEventsAsJSON(previous_logged_events,
290 i,
291 TRACE_EVENT_BATCH_SIZE,
292 &json_events);
293 {
294 AutoLock lock(lock_);
295 output_callback_->Run(json_events);
Sigurður Ásgeirsson 2011/05/02 19:28:41 You're still calling out of module here with the l
scheib 2011/05/04 02:14:15 This was an error and I've removed the lock. The c
296 }
297 }
298 }
299
300 void TraceLog::AddTraceEvent(TraceEventPhase phase,
301 const char* file, int line,
302 TraceCategory* category,
303 const char* name,
304 const char* arg1_name, TraceValue arg1_val,
305 const char* arg2_name, TraceValue arg2_val) {
306 DCHECK(file && name);
307 #ifdef USE_UNRELIABLE_NOW
308 TimeTicks now = TimeTicks::HighResNow();
309 #else
310 TimeTicks now = TimeTicks::Now();
311 #endif
312 AutoLock lock(lock_);
313 if (!enabled_ || !category->enabled_)
58 return; 314 return;
59 Trace(name, type, id, WideToUTF8(extra), file, line); 315 if (logged_events_.size() >= TRACE_EVENT_BUFFER_SIZE)
60 }
61
62 void TraceLog::Trace(const std::string& name,
63 EventType type,
64 const void* id,
65 const std::string& extra,
66 const char* file,
67 int line) {
68 if (!enabled_)
69 return; 316 return;
70 317 logged_events_.push_back(TraceEvent());
71 #ifdef USE_UNRELIABLE_NOW 318 TraceEvent& event = logged_events_.back();
72 TimeTicks tick = TimeTicks::HighResNow(); 319 event.process_id = static_cast<unsigned long>(base::GetCurrentProcId());
73 #else 320 event.thread_id = PlatformThread::CurrentId();
74 TimeTicks tick = TimeTicks::Now(); 321 event.timestamp = now;
322 event.phase = phase;
323 event.category = category;
324 event.name = name;
325 event.arg_names[0] = arg1_name;
326 event.arg_values[0] = arg1_val;
327 event.arg_names[1] = arg2_name;
328 event.arg_values[1] = arg2_val;
329 COMPILE_ASSERT(TRACE_MAX_NUM_ARGS == 2, TraceEvent_arc_count_out_of_sync);
330 if (logged_events_.size() == TRACE_EVENT_BUFFER_SIZE &&
331 buffer_full_callback_.get())
332 buffer_full_callback_->Run();
Sigurður Ásgeirsson 2011/05/02 19:28:41 you're calling out of module here under a lock als
scheib 2011/05/04 02:14:15 Fixed.
333 }
334
335 void TraceLog::AddTraceEventEtw(TraceEventPhase phase,
336 const char* file, int line,
337 const char* name,
338 const void* id,
339 const char* extra) {
340 // Legacy trace points on windows called to ETW
341 #if defined(OS_WIN)
342 TraceEventETWProvider::Trace(name, phase, id, extra);
75 #endif 343 #endif
76 TimeDelta delta = tick - trace_start_time_; 344
77 int64 usec = delta.InMicroseconds(); 345 // Also add new trace event behavior
78 std::string msg = 346 static TraceCategory* category = GetCategory("ETW Trace Event");
79 StringPrintf("{'pid':'0x%lx', 'tid':'0x%lx', 'type':'%s', " 347 if (category->enabled_) {
80 "'name':'%s', 'id':'%p', 'extra':'%s', 'file':'%s', " 348 TraceLog* tracelog = TraceLog::GetInstance();
81 "'line_number':'%d', 'usec_begin': %" PRId64 "},\n", 349 if (!tracelog)
82 static_cast<unsigned long>(base::GetCurrentProcId()), 350 return;
83 static_cast<unsigned long>(PlatformThread::CurrentId()), 351 tracelog->AddTraceEvent(phase, file, line, category, name,
84 kEventTypeNames[type], 352 "id", StringPrintf("%p", id).c_str(),
Sigurður Ásgeirsson 2011/05/02 19:28:41 nit: wonky indent.
scheib 2011/05/04 02:14:15 Done.
85 name.c_str(), 353 "extra", extra ? extra : "");
86 id, 354 }
87 extra.c_str(), 355 }
88 file, 356
89 line, 357 void TraceLog::Resurrect() {
90 usec); 358 StaticMemorySingletonTraits<TraceLog>::Resurrect();
91
92 Log(msg);
93 }
94
95 TraceLog::TraceLog() : enabled_(false), log_file_(NULL) {
96 base::ProcessHandle proc = base::GetCurrentProcessHandle();
97 #if !defined(OS_MACOSX)
98 process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(proc));
99 #else
100 // The default port provider is sufficient to get data for the current
101 // process.
102 process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(proc,
103 NULL));
104 #endif
105 }
106
107 TraceLog::~TraceLog() {
108 Stop();
109 }
110
111 bool TraceLog::OpenLogFile() {
112 FilePath::StringType pid_filename =
113 StringPrintf(kLogFileName, base::GetCurrentProcId());
114 FilePath log_file_path;
115 if (!PathService::Get(base::DIR_EXE, &log_file_path))
116 return false;
117 log_file_path = log_file_path.Append(pid_filename);
118 log_file_ = file_util::OpenFile(log_file_path, "a");
119 if (!log_file_) {
120 // try the current directory
121 log_file_ = file_util::OpenFile(FilePath(pid_filename), "a");
122 if (!log_file_) {
123 return false;
124 }
125 }
126 return true;
127 }
128
129 void TraceLog::CloseLogFile() {
130 if (log_file_) {
131 file_util::CloseFile(log_file_);
132 }
133 }
134
135 bool TraceLog::Start() {
136 if (enabled_)
137 return true;
138 enabled_ = OpenLogFile();
139 if (enabled_) {
140 Log("var raw_trace_events = [\n");
141 trace_start_time_ = TimeTicks::Now();
142 timer_.Start(TimeDelta::FromMilliseconds(250), this, &TraceLog::Heartbeat);
143 }
144 return enabled_;
145 }
146
147 void TraceLog::Stop() {
148 if (enabled_) {
149 enabled_ = false;
150 Log("];\n");
151 CloseLogFile();
152 timer_.Stop();
153 }
154 }
155
156 void TraceLog::Heartbeat() {
157 std::string cpu = StringPrintf("%.0f", process_metrics_->GetCPUUsage());
158 TRACE_EVENT_INSTANT("heartbeat.cpu", 0, cpu);
159 }
160
161 void TraceLog::Log(const std::string& msg) {
162 AutoLock lock(file_lock_);
163
164 fprintf(log_file_, "%s", msg.c_str());
165 } 359 }
166 360
167 } // namespace debug 361 } // namespace debug
168 } // namespace base 362 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698