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

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

Issue 7495031: trace_event support for thread names (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Handle thread id repeats, fix locking, clarify name lifetime. Created 9 years, 4 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
« no previous file with comments | « base/debug/trace_event.h ('k') | base/debug/trace_event_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 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) 7 #if defined(OS_WIN)
8 #include "base/debug/trace_event_win.h" 8 #include "base/debug/trace_event_win.h"
9 #endif 9 #endif
10 #include "base/format_macros.h" 10 #include "base/format_macros.h"
11 #include "base/memory/ref_counted_memory.h" 11 #include "base/memory/ref_counted_memory.h"
12 #include "base/process_util.h" 12 #include "base/process_util.h"
13 #include "base/stringprintf.h" 13 #include "base/stringprintf.h"
14 #include "base/threading/thread_local.h"
14 #include "base/utf_string_conversions.h" 15 #include "base/utf_string_conversions.h"
15 #include "base/stl_util.h" 16 #include "base/stl_util.h"
16 #include "base/time.h" 17 #include "base/time.h"
17 18
18 #define USE_UNRELIABLE_NOW 19 #define USE_UNRELIABLE_NOW
19 20
20 namespace base { 21 namespace base {
21 namespace debug { 22 namespace debug {
22 23
23 // Controls the number of trace events we will buffer in-memory 24 // Controls the number of trace events we will buffer in-memory
24 // before throwing them away. 25 // before throwing them away.
25 const size_t kTraceEventBufferSize = 500000; 26 const size_t kTraceEventBufferSize = 500000;
26 const size_t kTraceEventBatchSize = 1000; 27 const size_t kTraceEventBatchSize = 1000;
27 28
28 #define TRACE_EVENT_MAX_CATEGORIES 42 29 #define TRACE_EVENT_MAX_CATEGORIES 42
29 30
30 static TraceCategory g_categories[TRACE_EVENT_MAX_CATEGORIES] = { 31 static TraceCategory g_categories[TRACE_EVENT_MAX_CATEGORIES] = {
31 { "tracing already shutdown", false }, 32 { "tracing already shutdown", false },
32 { "tracing categories exhausted; must increase TRACE_EVENT_MAX_CATEGORIES", 33 { "tracing categories exhausted; must increase TRACE_EVENT_MAX_CATEGORIES",
33 false } 34 false }
34 }; 35 };
35 static const TraceCategory* const g_category_already_shutdown = 36 static const TraceCategory* const g_category_already_shutdown =
36 &g_categories[0]; 37 &g_categories[0];
37 static const TraceCategory* const g_category_categories_exhausted = 38 static const TraceCategory* const g_category_categories_exhausted =
38 &g_categories[1]; 39 &g_categories[1];
39 static int g_category_index = 2; // skip initial 2 error categories 40 static int g_category_index = 2; // skip initial 2 error categories
40 41
42 // Flag to indicate whether we captured the current thread name
43 static ThreadLocalBoolean g_current_thread_name_captured;
44
41 //////////////////////////////////////////////////////////////////////////////// 45 ////////////////////////////////////////////////////////////////////////////////
42 // 46 //
43 // TraceValue 47 // TraceValue
44 // 48 //
45 //////////////////////////////////////////////////////////////////////////////// 49 ////////////////////////////////////////////////////////////////////////////////
46 50
47 void TraceValue::AppendAsJSON(std::string* out) const { 51 void TraceValue::AppendAsJSON(std::string* out) const {
48 char temp_string[128]; 52 char temp_string[128];
49 std::string::size_type start_pos; 53 std::string::size_type start_pos;
50 switch (type_) { 54 switch (type_) {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 namespace { 101 namespace {
98 102
99 const char* GetPhaseStr(TraceEventPhase phase) { 103 const char* GetPhaseStr(TraceEventPhase phase) {
100 switch(phase) { 104 switch(phase) {
101 case TRACE_EVENT_PHASE_BEGIN: 105 case TRACE_EVENT_PHASE_BEGIN:
102 return "B"; 106 return "B";
103 case TRACE_EVENT_PHASE_INSTANT: 107 case TRACE_EVENT_PHASE_INSTANT:
104 return "I"; 108 return "I";
105 case TRACE_EVENT_PHASE_END: 109 case TRACE_EVENT_PHASE_END:
106 return "E"; 110 return "E";
111 case TRACE_EVENT_PHASE_METADATA:
112 return "M";
107 default: 113 default:
108 NOTREACHED() << "Invalid phase argument"; 114 NOTREACHED() << "Invalid phase argument";
109 return "?"; 115 return "?";
110 } 116 }
111 } 117 }
112 118
113 size_t GetAllocLength(const char* str) { return str ? strlen(str) + 1 : 0; } 119 size_t GetAllocLength(const char* str) { return str ? strlen(str) + 1 : 0; }
114 120
115 // Copies |*member| into |*buffer|, sets |*member| to point to this new 121 // Copies |*member| into |*buffer|, sets |*member| to point to this new
116 // location, and then advances |*buffer| by the amount written. 122 // location, and then advances |*buffer| by the amount written.
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 AutoLock lock(lock_); 293 AutoLock lock(lock_);
288 if (enabled == enabled_) 294 if (enabled == enabled_)
289 return; 295 return;
290 logged_events_.reserve(1024); 296 logged_events_.reserve(1024);
291 enabled_ = enabled; 297 enabled_ = enabled;
292 for (int i = 0; i < g_category_index; i++) { 298 for (int i = 0; i < g_category_index; i++) {
293 //TODO(scheib): If changed to enable specific categories instead of all 299 //TODO(scheib): If changed to enable specific categories instead of all
294 // check GetCategoryInternal creation code that users TraceLog::enabled_ 300 // check GetCategoryInternal creation code that users TraceLog::enabled_
295 g_categories[i].enabled = enabled; 301 g_categories[i].enabled = enabled;
296 } 302 }
303
304 if (!enabled)
305 AddCurrentMetadataEvents();
297 } // release lock 306 } // release lock
298 if (!enabled) 307 if (!enabled) {
299 Flush(); 308 Flush();
309 }
300 } 310 }
301 311
302 float TraceLog::GetBufferPercentFull() const { 312 float TraceLog::GetBufferPercentFull() const {
303 return (float)((double)logged_events_.size()/(double)kTraceEventBufferSize); 313 return (float)((double)logged_events_.size()/(double)kTraceEventBufferSize);
304 } 314 }
305 315
306 void TraceLog::SetOutputCallback(const TraceLog::OutputCallback& cb) { 316 void TraceLog::SetOutputCallback(const TraceLog::OutputCallback& cb) {
307 AutoLock lock(lock_); 317 AutoLock lock(lock_);
308 output_callback_ = cb; 318 output_callback_ = cb;
309 logged_events_.clear(); 319 logged_events_.clear();
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
354 TimeTicks now = TimeTicks::Now(); 364 TimeTicks now = TimeTicks::Now();
355 #endif 365 #endif
356 BufferFullCallback buffer_full_callback_copy; 366 BufferFullCallback buffer_full_callback_copy;
357 int ret_begin_id = -1; 367 int ret_begin_id = -1;
358 { 368 {
359 AutoLock lock(lock_); 369 AutoLock lock(lock_);
360 if (!enabled_ || !category->enabled) 370 if (!enabled_ || !category->enabled)
361 return -1; 371 return -1;
362 if (logged_events_.size() >= kTraceEventBufferSize) 372 if (logged_events_.size() >= kTraceEventBufferSize)
363 return -1; 373 return -1;
374
375 PlatformThreadId thread_id = PlatformThread::CurrentId();
376
377 // Record the name of the calling thread, if not done already.
378 if (!g_current_thread_name_captured.Get()) {
379 const char* cur_name = PlatformThread::GetName();
380 base::hash_map<PlatformThreadId, std::string>::iterator existing_name =
381 thread_names_.find(thread_id);
382 if (existing_name == thread_names_.end()) {
383 // This is a new thread id, and a new name.
384 thread_names_[thread_id] = cur_name ? cur_name : "";
385 } else if(cur_name != NULL) {
386 // This is a thread id that we've seen before, but potentially with a
Sigurður Ásgeirsson 2011/08/04 20:07:05 so, you want to keep all names you've seen?
387 // new name.
388 std::vector<std::string> existing_names;
389 Tokenize(existing_name->second, std::string(","), &existing_names);
390 bool found = false;
391 for (size_t i = 0; i < existing_names.size(); ++i) {
Sigurður Ásgeirsson 2011/08/04 20:07:05 nit: to the naked eye this looks equivalent to bo
392 if(existing_names[i] == cur_name) {
393 found = true;
394 break;
395 }
396 }
397 if (!found) {
398 existing_names.push_back(cur_name);
399 thread_names_[thread_id] =
400 JoinString(existing_names, ',');
401 }
402 }
403 }
404
364 if (threshold_begin_id > -1) { 405 if (threshold_begin_id > -1) {
365 DCHECK(phase == base::debug::TRACE_EVENT_PHASE_END); 406 DCHECK(phase == base::debug::TRACE_EVENT_PHASE_END);
366 size_t begin_i = static_cast<size_t>(threshold_begin_id); 407 size_t begin_i = static_cast<size_t>(threshold_begin_id);
367 // Return now if there has been a flush since the begin event was posted. 408 // Return now if there has been a flush since the begin event was posted.
368 if (begin_i >= logged_events_.size()) 409 if (begin_i >= logged_events_.size())
369 return -1; 410 return -1;
370 // Determine whether to drop the begin/end pair. 411 // Determine whether to drop the begin/end pair.
371 TimeDelta elapsed = now - logged_events_[begin_i].timestamp(); 412 TimeDelta elapsed = now - logged_events_[begin_i].timestamp();
372 if (elapsed < TimeDelta::FromMicroseconds(threshold)) { 413 if (elapsed < TimeDelta::FromMicroseconds(threshold)) {
373 // Remove begin event and do not add end event. 414 // Remove begin event and do not add end event.
374 // This will be expensive if there have been other events in the 415 // This will be expensive if there have been other events in the
375 // mean time (should be rare). 416 // mean time (should be rare).
376 logged_events_.erase(logged_events_.begin() + begin_i); 417 logged_events_.erase(logged_events_.begin() + begin_i);
377 return -1; 418 return -1;
378 } 419 }
379 } 420 }
380 ret_begin_id = static_cast<int>(logged_events_.size()); 421 ret_begin_id = static_cast<int>(logged_events_.size());
381 logged_events_.push_back( 422 logged_events_.push_back(
382 TraceEvent(static_cast<unsigned long>(base::GetCurrentProcId()), 423 TraceEvent(static_cast<unsigned long>(base::GetCurrentProcId()),
383 PlatformThread::CurrentId(), 424 thread_id,
384 now, phase, category, name, 425 now, phase, category, name,
385 arg1_name, arg1_val, 426 arg1_name, arg1_val,
386 arg2_name, arg2_val, 427 arg2_name, arg2_val,
387 copy)); 428 copy));
388 429
389 if (logged_events_.size() == kTraceEventBufferSize) { 430 if (logged_events_.size() == kTraceEventBufferSize) {
390 buffer_full_callback_copy = buffer_full_callback_; 431 buffer_full_callback_copy = buffer_full_callback_;
391 } 432 }
392 } // release lock 433 } // release lock
393 434
(...skipping 18 matching lines...) Expand all
412 TraceLog* tracelog = TraceLog::GetInstance(); 453 TraceLog* tracelog = TraceLog::GetInstance();
413 if (!tracelog) 454 if (!tracelog)
414 return; 455 return;
415 tracelog->AddTraceEvent(phase, category, name, 456 tracelog->AddTraceEvent(phase, category, name,
416 "id", id, 457 "id", id,
417 "extra", extra ? extra : "", 458 "extra", extra ? extra : "",
418 -1, 0, false); 459 -1, 0, false);
419 } 460 }
420 } 461 }
421 462
463 void TraceLog::AddCurrentMetadataEvents() {
464 lock_.AssertAcquired();
465 static const TraceCategory* metadata_category =
466 GetCategoryInternal("__metadata");
467 for(base::hash_map<PlatformThreadId, std::string>::iterator it =
468 thread_names_.begin();
469 it != thread_names_.end();
470 it++) {
471 if (!it->second.empty())
472 logged_events_.push_back(
473 TraceEvent(static_cast<unsigned long>(base::GetCurrentProcId()),
474 it->first,
475 TimeTicks(), base::debug::TRACE_EVENT_PHASE_METADATA,
476 metadata_category, "thread_name",
477 "name", it->second.c_str(),
478 NULL, 0,
479 false));
480 }
481 }
482
422 void TraceLog::Resurrect() { 483 void TraceLog::Resurrect() {
423 StaticMemorySingletonTraits<TraceLog>::Resurrect(); 484 StaticMemorySingletonTraits<TraceLog>::Resurrect();
424 } 485 }
425 486
426 namespace internal { 487 namespace internal {
427 488
428 void TraceEndOnScopeClose::Initialize(const TraceCategory* category, 489 void TraceEndOnScopeClose::Initialize(const TraceCategory* category,
429 const char* name) { 490 const char* name) {
430 data_.category = category; 491 data_.category = category;
431 data_.name = name; 492 data_.name = name;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
464 p_data_->name, 525 p_data_->name,
465 NULL, 0, NULL, 0, 526 NULL, 0, NULL, 0,
466 p_data_->threshold_begin_id, p_data_->threshold, false); 527 p_data_->threshold_begin_id, p_data_->threshold, false);
467 } 528 }
468 } 529 }
469 530
470 } // namespace internal 531 } // namespace internal
471 532
472 } // namespace debug 533 } // namespace debug
473 } // namespace base 534 } // namespace base
OLDNEW
« no previous file with comments | « base/debug/trace_event.h ('k') | base/debug/trace_event_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698