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

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

Issue 8590015: trace_event: distinguish between scoped begin/end and global start/finish events (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 1 month 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) 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 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/format_macros.h" 10 #include "base/format_macros.h"
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 65
66 } // namespace 66 } // namespace
67 67
68 //////////////////////////////////////////////////////////////////////////////// 68 ////////////////////////////////////////////////////////////////////////////////
69 // 69 //
70 // TraceValue 70 // TraceValue
71 // 71 //
72 //////////////////////////////////////////////////////////////////////////////// 72 ////////////////////////////////////////////////////////////////////////////////
73 73
74 void TraceValue::AppendAsJSON(std::string* out) const { 74 void TraceValue::AppendAsJSON(std::string* out) const {
75 char temp_string[128];
76 std::string::size_type start_pos; 75 std::string::size_type start_pos;
77 switch (type_) { 76 switch (type_) {
78 case TRACE_TYPE_BOOL: 77 case TRACE_TYPE_BOOL:
79 *out += as_bool() ? "true" : "false"; 78 *out += as_bool() ? "true" : "false";
80 break; 79 break;
81 case TRACE_TYPE_UINT: 80 case TRACE_TYPE_UINT:
82 base::snprintf(temp_string, arraysize(temp_string), "%llu", 81 StringAppendF(out, "%llu", static_cast<unsigned long long>(as_uint()));
jbates 2011/11/17 01:15:28 Cleanup to match other instances of StringAppendF
83 static_cast<unsigned long long>(as_uint()));
84 *out += temp_string;
85 break; 82 break;
86 case TRACE_TYPE_INT: 83 case TRACE_TYPE_INT:
87 base::snprintf(temp_string, arraysize(temp_string), "%lld", 84 StringAppendF(out, "%lld", static_cast<long long>(as_int()));
88 static_cast<long long>(as_int()));
89 *out += temp_string;
90 break; 85 break;
91 case TRACE_TYPE_DOUBLE: 86 case TRACE_TYPE_DOUBLE:
92 base::snprintf(temp_string, arraysize(temp_string), "%f", as_double()); 87 StringAppendF(out, "%f", as_double());
93 *out += temp_string;
94 break; 88 break;
95 case TRACE_TYPE_POINTER: 89 case TRACE_TYPE_POINTER:
96 base::snprintf(temp_string, arraysize(temp_string), "%llu", 90 // JSON only supports double and int numbers.
97 static_cast<unsigned long long>( 91 // So as not to lose bits from a 64-bit pointer, output as a hex string.
98 reinterpret_cast<intptr_t>( 92 StringAppendF(out, "\"%llx\"", static_cast<unsigned long long>(
jbates 2011/11/17 01:15:28 Storing the pointer as a string instead of an int,
99 as_pointer()))); 93 reinterpret_cast<intptr_t>(
100 *out += temp_string; 94 as_pointer())));
101 break; 95 break;
102 case TRACE_TYPE_STRING: 96 case TRACE_TYPE_STRING:
103 case TRACE_TYPE_STATIC_STRING: 97 case TRACE_TYPE_STATIC_STRING:
104 *out += "\""; 98 *out += "\"";
105 start_pos = out->size(); 99 start_pos = out->size();
106 *out += as_string() ? as_string() : "NULL"; 100 *out += as_string() ? as_string() : "NULL";
107 // insert backslash before special characters for proper json format. 101 // insert backslash before special characters for proper json format.
108 while ((start_pos = out->find_first_of("\\\"", start_pos)) != 102 while ((start_pos = out->find_first_of("\\\"", start_pos)) !=
109 std::string::npos) { 103 std::string::npos) {
110 out->insert(start_pos, 1, '\\'); 104 out->insert(start_pos, 1, '\\');
(...skipping 27 matching lines...) Expand all
138 size_t written = strlcpy(*buffer, *member, end - *buffer) + 1; 132 size_t written = strlcpy(*buffer, *member, end - *buffer) + 1;
139 DCHECK_LE(static_cast<int>(written), end - *buffer); 133 DCHECK_LE(static_cast<int>(written), end - *buffer);
140 *member = *buffer; 134 *member = *buffer;
141 *buffer += written; 135 *buffer += written;
142 } 136 }
143 } 137 }
144 138
145 } // namespace 139 } // namespace
146 140
147 TraceEvent::TraceEvent() 141 TraceEvent::TraceEvent()
148 : process_id_(0), 142 : extra_(0u),
143 category_(NULL),
144 name_(NULL),
149 thread_id_(0), 145 thread_id_(0),
150 phase_(TRACE_EVENT_PHASE_BEGIN), 146 phase_(TRACE_EVENT_PHASE_BEGIN) {
151 category_(NULL),
152 name_(NULL) {
153 arg_names_[0] = NULL; 147 arg_names_[0] = NULL;
154 arg_names_[1] = NULL; 148 arg_names_[1] = NULL;
155 } 149 }
156 150
157 TraceEvent::TraceEvent(unsigned long process_id, 151 TraceEvent::TraceEvent(int thread_id,
158 unsigned long thread_id,
159 TimeTicks timestamp, 152 TimeTicks timestamp,
160 TraceEventPhase phase, 153 TraceEventPhase phase,
161 const TraceCategory* category, 154 const TraceCategory* category,
162 const char* name, 155 const char* name,
156 uint64 extra,
163 const char* arg1_name, const TraceValue& arg1_val, 157 const char* arg1_name, const TraceValue& arg1_val,
164 const char* arg2_name, const TraceValue& arg2_val, 158 const char* arg2_name, const TraceValue& arg2_val,
165 bool copy) 159 bool copy)
166 : process_id_(process_id), 160 : timestamp_(timestamp),
161 extra_(extra),
162 category_(category),
163 name_(name),
167 thread_id_(thread_id), 164 thread_id_(thread_id),
168 timestamp_(timestamp), 165 phase_(phase) {
169 phase_(phase),
170 category_(category),
171 name_(name) {
172 COMPILE_ASSERT(kTraceMaxNumArgs == 2, TraceEvent_arg_count_out_of_sync); 166 COMPILE_ASSERT(kTraceMaxNumArgs == 2, TraceEvent_arg_count_out_of_sync);
173 arg_names_[0] = arg1_name; 167 arg_names_[0] = arg1_name;
174 arg_names_[1] = arg2_name; 168 arg_names_[1] = arg2_name;
175 arg_values_[0] = arg1_val; 169 arg_values_[0] = arg1_val;
176 arg_values_[1] = arg2_val; 170 arg_values_[1] = arg2_val;
177 171
178 size_t alloc_size = 0; 172 size_t alloc_size = 0;
179 if (copy) { 173 if (copy) {
180 alloc_size += GetAllocLength(name); 174 alloc_size += GetAllocLength(name);
181 alloc_size += GetAllocLength(arg1_name); 175 alloc_size += GetAllocLength(arg1_name);
(...skipping 28 matching lines...) Expand all
210 } 204 }
211 } 205 }
212 206
213 TraceEvent::~TraceEvent() { 207 TraceEvent::~TraceEvent() {
214 } 208 }
215 209
216 const char* TraceEvent::GetPhaseString(TraceEventPhase phase) { 210 const char* TraceEvent::GetPhaseString(TraceEventPhase phase) {
217 switch(phase) { 211 switch(phase) {
218 case TRACE_EVENT_PHASE_BEGIN: 212 case TRACE_EVENT_PHASE_BEGIN:
219 return "B"; 213 return "B";
214 case TRACE_EVENT_PHASE_END:
jbates 2011/11/17 01:15:28 Reordered these to match the order in the enum.
215 return "E";
220 case TRACE_EVENT_PHASE_INSTANT: 216 case TRACE_EVENT_PHASE_INSTANT:
221 return "I"; 217 return "I";
222 case TRACE_EVENT_PHASE_END: 218 case TRACE_EVENT_PHASE_START:
223 return "E"; 219 return "S";
220 case TRACE_EVENT_PHASE_FINISH:
221 return "F";
224 case TRACE_EVENT_PHASE_METADATA: 222 case TRACE_EVENT_PHASE_METADATA:
225 return "M"; 223 return "M";
226 default: 224 default:
227 NOTREACHED() << "Invalid phase argument"; 225 NOTREACHED() << "Invalid phase argument";
228 return "?"; 226 return "?";
229 } 227 }
230 } 228 }
231 229
232 TraceEventPhase TraceEvent::GetPhase(const char* phase) { 230 TraceEventPhase TraceEvent::GetPhase(const char* phase) {
233 switch(*phase) { 231 switch(*phase) {
234 case 'B': 232 case 'B':
235 return TRACE_EVENT_PHASE_BEGIN; 233 return TRACE_EVENT_PHASE_BEGIN;
234 case 'E':
235 return TRACE_EVENT_PHASE_END;
236 case 'I': 236 case 'I':
237 return TRACE_EVENT_PHASE_INSTANT; 237 return TRACE_EVENT_PHASE_INSTANT;
238 case 'E': 238 case 'S':
239 return TRACE_EVENT_PHASE_END; 239 return TRACE_EVENT_PHASE_START;
240 case 'F':
241 return TRACE_EVENT_PHASE_FINISH;
240 case 'M': 242 case 'M':
241 return TRACE_EVENT_PHASE_METADATA; 243 return TRACE_EVENT_PHASE_METADATA;
242 default: 244 default:
243 NOTREACHED() << "Invalid phase name"; 245 NOTREACHED() << "Invalid phase name";
244 return TRACE_EVENT_PHASE_METADATA; 246 return TRACE_EVENT_PHASE_METADATA;
245 } 247 }
246 } 248 }
247 249
248 void TraceEvent::AppendEventsAsJSON(const std::vector<TraceEvent>& events, 250 void TraceEvent::AppendEventsAsJSON(const std::vector<TraceEvent>& events,
249 size_t start, 251 size_t start,
250 size_t count, 252 size_t count,
251 std::string* out) { 253 std::string* out) {
252 for (size_t i = 0; i < count && start + i < events.size(); ++i) { 254 for (size_t i = 0; i < count && start + i < events.size(); ++i) {
253 if (i > 0) 255 if (i > 0)
254 *out += ","; 256 *out += ",";
255 events[i + start].AppendAsJSON(out); 257 events[i + start].AppendAsJSON(out);
256 } 258 }
257 } 259 }
258 260
259 void TraceEvent::AppendAsJSON(std::string* out) const { 261 void TraceEvent::AppendAsJSON(std::string* out) const {
260 const char* phase_str = GetPhaseString(phase_); 262 const char* phase_str = GetPhaseString(phase_);
261 int64 time_int64 = timestamp_.ToInternalValue(); 263 int64 time_int64 = timestamp_.ToInternalValue();
264 int process_id = static_cast<int>(base::GetCurrentProcId());
262 // Category name checked at category creation time. 265 // Category name checked at category creation time.
263 DCHECK(!strchr(name_, '"')); 266 DCHECK(!strchr(name_, '"'));
264 StringAppendF(out, 267 StringAppendF(out,
265 "{\"cat\":\"%s\",\"pid\":%i,\"tid\":%i,\"ts\":%lld," 268 "{\"cat\":\"%s\",\"pid\":%i,\"tid\":%i,\"ts\":%lld,"
266 "\"ph\":\"%s\",\"name\":\"%s\",\"args\":{", 269 "\"ph\":\"%s\",\"name\":\"%s\",\"args\":{",
267 category_->name, 270 category_->name,
268 static_cast<int>(process_id_), 271 process_id,
269 static_cast<int>(thread_id_), 272 thread_id_,
270 static_cast<long long>(time_int64), 273 static_cast<long long>(time_int64),
271 phase_str, 274 phase_str,
272 name_); 275 name_);
273 276
274 // Output argument names and values, stop at first NULL argument name. 277 // Output argument names and values, stop at first NULL argument name.
275 for (size_t i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) { 278 for (size_t i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) {
276 if (i > 0) 279 if (i > 0)
277 *out += ","; 280 *out += ",";
278 *out += "\""; 281 *out += "\"";
279 *out += arg_names_[i]; 282 *out += arg_names_[i];
280 *out += "\":"; 283 *out += "\":";
281 arg_values_[i].AppendAsJSON(out); 284 arg_values_[i].AppendAsJSON(out);
282 } 285 }
283 *out += "}}"; 286 *out += "}";
287
288 // If extra_ is non-zero, print it out as a hex string so we don't loose any
289 // bits (it might be a 64-bit pointer).
290 if (extra_ != 0ull)
291 StringAppendF(out, ",\"ext\":\"%llx\"",
292 static_cast<unsigned long long>(extra_));
293 *out += "}";
284 } 294 }
285 295
286 //////////////////////////////////////////////////////////////////////////////// 296 ////////////////////////////////////////////////////////////////////////////////
287 // 297 //
288 // TraceResultBuffer 298 // TraceResultBuffer
289 // 299 //
290 //////////////////////////////////////////////////////////////////////////////// 300 ////////////////////////////////////////////////////////////////////////////////
291 301
292 TraceResultBuffer::OutputCallback 302 TraceResultBuffer::OutputCallback
293 TraceResultBuffer::SimpleOutput::GetCallback() { 303 TraceResultBuffer::SimpleOutput::GetCallback() {
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 i, 532 i,
523 kTraceEventBatchSize, 533 kTraceEventBatchSize,
524 &(json_events_str_ptr->data)); 534 &(json_events_str_ptr->data));
525 output_callback_copy.Run(json_events_str_ptr); 535 output_callback_copy.Run(json_events_str_ptr);
526 } 536 }
527 } 537 }
528 538
529 int TraceLog::AddTraceEvent(TraceEventPhase phase, 539 int TraceLog::AddTraceEvent(TraceEventPhase phase,
530 const TraceCategory* category, 540 const TraceCategory* category,
531 const char* name, 541 const char* name,
542 uint64 extra,
532 const char* arg1_name, TraceValue arg1_val, 543 const char* arg1_name, TraceValue arg1_val,
533 const char* arg2_name, TraceValue arg2_val, 544 const char* arg2_name, TraceValue arg2_val,
534 int threshold_begin_id, 545 int threshold_begin_id,
535 int64 threshold, 546 int64 threshold,
536 EventFlags flags) { 547 EventFlags flags) {
537 DCHECK(name); 548 DCHECK(name);
538 TimeTicks now = TimeTicks::HighResNow(); 549 TimeTicks now = TimeTicks::HighResNow();
539 BufferFullCallback buffer_full_callback_copy; 550 BufferFullCallback buffer_full_callback_copy;
540 int ret_begin_id = -1; 551 int ret_begin_id = -1;
541 { 552 {
542 AutoLock lock(lock_); 553 AutoLock lock(lock_);
543 if (!category->enabled) 554 if (!category->enabled)
544 return -1; 555 return -1;
545 if (logged_events_.size() >= kTraceEventBufferSize) 556 if (logged_events_.size() >= kTraceEventBufferSize)
546 return -1; 557 return -1;
547 558
548 PlatformThreadId thread_id = PlatformThread::CurrentId(); 559 int thread_id = static_cast<int>(PlatformThread::CurrentId());
549 560
550 const char* new_name = PlatformThread::GetName(); 561 const char* new_name = PlatformThread::GetName();
551 // Check if the thread name has been set or changed since the previous 562 // Check if the thread name has been set or changed since the previous
552 // call (if any), but don't bother if the new name is empty. Note this will 563 // call (if any), but don't bother if the new name is empty. Note this will
553 // not detect a thread name change within the same char* buffer address: we 564 // not detect a thread name change within the same char* buffer address: we
554 // favor common case performance over corner case correctness. 565 // favor common case performance over corner case correctness.
555 if (new_name != g_current_thread_name.Get().Get() && 566 if (new_name != g_current_thread_name.Get().Get() &&
556 new_name && *new_name) { 567 new_name && *new_name) {
557 // Benign const cast. 568 // Benign const cast.
558 g_current_thread_name.Get().Set(const_cast<char*>(new_name)); 569 g_current_thread_name.Get().Set(const_cast<char*>(new_name));
(...skipping 28 matching lines...) Expand all
587 if (elapsed < TimeDelta::FromMicroseconds(threshold)) { 598 if (elapsed < TimeDelta::FromMicroseconds(threshold)) {
588 // Remove begin event and do not add end event. 599 // Remove begin event and do not add end event.
589 // This will be expensive if there have been other events in the 600 // This will be expensive if there have been other events in the
590 // mean time (should be rare). 601 // mean time (should be rare).
591 logged_events_.erase(logged_events_.begin() + begin_i); 602 logged_events_.erase(logged_events_.begin() + begin_i);
592 return -1; 603 return -1;
593 } 604 }
594 } 605 }
595 ret_begin_id = static_cast<int>(logged_events_.size()); 606 ret_begin_id = static_cast<int>(logged_events_.size());
596 logged_events_.push_back( 607 logged_events_.push_back(
597 TraceEvent(static_cast<unsigned long>(base::GetCurrentProcId()), 608 TraceEvent(thread_id,
598 thread_id, 609 now, phase, category, name, extra,
599 now, phase, category, name,
600 arg1_name, arg1_val, 610 arg1_name, arg1_val,
601 arg2_name, arg2_val, 611 arg2_name, arg2_val,
602 flags & EVENT_FLAG_COPY)); 612 flags & EVENT_FLAG_COPY));
603 613
604 if (logged_events_.size() == kTraceEventBufferSize) { 614 if (logged_events_.size() == kTraceEventBufferSize) {
605 buffer_full_callback_copy = buffer_full_callback_; 615 buffer_full_callback_copy = buffer_full_callback_;
606 } 616 }
607 } // release lock 617 } // release lock
608 618
609 if (!buffer_full_callback_copy.is_null()) 619 if (!buffer_full_callback_copy.is_null())
(...skipping 28 matching lines...) Expand all
638 } 648 }
639 649
640 void TraceLog::AddCurrentMetadataEvents() { 650 void TraceLog::AddCurrentMetadataEvents() {
641 lock_.AssertAcquired(); 651 lock_.AssertAcquired();
642 for(base::hash_map<PlatformThreadId, std::string>::iterator it = 652 for(base::hash_map<PlatformThreadId, std::string>::iterator it =
643 thread_names_.begin(); 653 thread_names_.begin();
644 it != thread_names_.end(); 654 it != thread_names_.end();
645 it++) { 655 it++) {
646 if (!it->second.empty()) 656 if (!it->second.empty())
647 logged_events_.push_back( 657 logged_events_.push_back(
648 TraceEvent(static_cast<unsigned long>(base::GetCurrentProcId()), 658 TraceEvent(it->first,
649 it->first,
650 TimeTicks(), base::debug::TRACE_EVENT_PHASE_METADATA, 659 TimeTicks(), base::debug::TRACE_EVENT_PHASE_METADATA,
651 g_category_metadata, "thread_name", 660 g_category_metadata, "thread_name", 0,
652 "name", it->second, 661 "name", it->second,
653 NULL, 0, 662 NULL, 0,
654 false)); 663 false));
655 } 664 }
656 } 665 }
657 666
658 void TraceLog::DeleteForTesting() { 667 void TraceLog::DeleteForTesting() {
659 DeleteTraceLogForTesting::Delete(); 668 DeleteTraceLogForTesting::Delete();
660 } 669 }
661 670
662 void TraceLog::Resurrect() { 671 void TraceLog::Resurrect() {
663 StaticMemorySingletonTraits<TraceLog>::Resurrect(); 672 StaticMemorySingletonTraits<TraceLog>::Resurrect();
664 } 673 }
665 674
666 namespace internal { 675 namespace internal {
667 676
668 void TraceEndOnScopeClose::Initialize(const TraceCategory* category, 677 void TraceEndOnScopeClose::Initialize(const TraceCategory* category,
669 const char* name) { 678 const char* name) {
670 data_.category = category; 679 data_.category = category;
671 data_.name = name; 680 data_.name = name;
672 p_data_ = &data_; 681 p_data_ = &data_;
673 } 682 }
674 683
675 void TraceEndOnScopeClose::AddEventIfEnabled() { 684 void TraceEndOnScopeClose::AddEventIfEnabled() {
676 // Only called when p_data_ is non-null. 685 // Only called when p_data_ is non-null.
677 if (p_data_->category->enabled) { 686 if (p_data_->category->enabled) {
678 base::debug::TraceLog::GetInstance()->AddTraceEvent( 687 base::debug::TraceLog::GetInstance()->AddTraceEvent(
679 base::debug::TRACE_EVENT_PHASE_END, 688 base::debug::TRACE_EVENT_PHASE_END,
680 p_data_->category, 689 p_data_->category,
681 p_data_->name, 690 p_data_->name, 0,
682 NULL, 0, NULL, 0, 691 NULL, 0, NULL, 0,
683 -1, 0, TraceLog::EVENT_FLAG_NONE); 692 -1, 0, TraceLog::EVENT_FLAG_NONE);
684 } 693 }
685 } 694 }
686 695
687 void TraceEndOnScopeCloseThreshold::Initialize(const TraceCategory* category, 696 void TraceEndOnScopeCloseThreshold::Initialize(const TraceCategory* category,
688 const char* name, 697 const char* name,
689 int threshold_begin_id, 698 int threshold_begin_id,
690 int64 threshold) { 699 int64 threshold) {
691 data_.category = category; 700 data_.category = category;
692 data_.name = name; 701 data_.name = name;
693 data_.threshold_begin_id = threshold_begin_id; 702 data_.threshold_begin_id = threshold_begin_id;
694 data_.threshold = threshold; 703 data_.threshold = threshold;
695 p_data_ = &data_; 704 p_data_ = &data_;
696 } 705 }
697 706
698 void TraceEndOnScopeCloseThreshold::AddEventIfEnabled() { 707 void TraceEndOnScopeCloseThreshold::AddEventIfEnabled() {
699 // Only called when p_data_ is non-null. 708 // Only called when p_data_ is non-null.
700 if (p_data_->category->enabled) { 709 if (p_data_->category->enabled) {
701 base::debug::TraceLog::GetInstance()->AddTraceEvent( 710 base::debug::TraceLog::GetInstance()->AddTraceEvent(
702 base::debug::TRACE_EVENT_PHASE_END, 711 base::debug::TRACE_EVENT_PHASE_END,
703 p_data_->category, 712 p_data_->category,
704 p_data_->name, 713 p_data_->name, 0,
705 NULL, 0, NULL, 0, 714 NULL, 0, NULL, 0,
706 p_data_->threshold_begin_id, p_data_->threshold, 715 p_data_->threshold_begin_id, p_data_->threshold,
707 TraceLog::EVENT_FLAG_NONE); 716 TraceLog::EVENT_FLAG_NONE);
708 } 717 }
709 } 718 }
710 719
711 } // namespace internal 720 } // namespace internal
712 721
713 } // namespace debug 722 } // namespace debug
714 } // namespace base 723 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698