OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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_impl.h" | 5 #include "base/debug/trace_event_impl.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/debug/leak_annotations.h" | 10 #include "base/debug/leak_annotations.h" |
11 #include "base/debug/trace_event.h" | 11 #include "base/debug/trace_event.h" |
12 #include "base/file_util.h" | |
13 #include "base/format_macros.h" | 12 #include "base/format_macros.h" |
14 #include "base/lazy_instance.h" | 13 #include "base/lazy_instance.h" |
15 #include "base/memory/singleton.h" | 14 #include "base/memory/singleton.h" |
16 #include "base/process_util.h" | 15 #include "base/process_util.h" |
17 #include "base/stl_util.h" | 16 #include "base/stl_util.h" |
18 #include "base/stringprintf.h" | 17 #include "base/stringprintf.h" |
19 #include "base/string_tokenizer.h" | 18 #include "base/string_tokenizer.h" |
20 #include "base/string_util.h" | 19 #include "base/string_util.h" |
21 #include "base/sys_info.h" | 20 #include "base/sys_info.h" |
22 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" | 21 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
63 unsigned char g_category_enabled[TRACE_EVENT_MAX_CATEGORIES] = { 0 }; | 62 unsigned char g_category_enabled[TRACE_EVENT_MAX_CATEGORIES] = { 0 }; |
64 const int g_category_already_shutdown = 0; | 63 const int g_category_already_shutdown = 0; |
65 const int g_category_categories_exhausted = 1; | 64 const int g_category_categories_exhausted = 1; |
66 const int g_category_metadata = 2; | 65 const int g_category_metadata = 2; |
67 int g_category_index = 3; // skip initial 3 categories | 66 int g_category_index = 3; // skip initial 3 categories |
68 | 67 |
69 // The most-recently captured name of the current thread | 68 // The most-recently captured name of the current thread |
70 LazyInstance<ThreadLocalPointer<const char> >::Leaky | 69 LazyInstance<ThreadLocalPointer<const char> >::Leaky |
71 g_current_thread_name = LAZY_INSTANCE_INITIALIZER; | 70 g_current_thread_name = LAZY_INSTANCE_INITIALIZER; |
72 | 71 |
73 void AppendValueAsJSON(unsigned char type, | |
74 TraceEvent::TraceValue value, | |
75 std::string* out) { | |
76 std::string::size_type start_pos; | |
77 switch (type) { | |
78 case TRACE_VALUE_TYPE_BOOL: | |
79 *out += value.as_bool ? "true" : "false"; | |
80 break; | |
81 case TRACE_VALUE_TYPE_UINT: | |
82 StringAppendF(out, "%" PRIu64, static_cast<uint64>(value.as_uint)); | |
83 break; | |
84 case TRACE_VALUE_TYPE_INT: | |
85 StringAppendF(out, "%" PRId64, static_cast<int64>(value.as_int)); | |
86 break; | |
87 case TRACE_VALUE_TYPE_DOUBLE: | |
88 StringAppendF(out, "%f", value.as_double); | |
89 break; | |
90 case TRACE_VALUE_TYPE_POINTER: | |
91 // JSON only supports double and int numbers. | |
92 // So as not to lose bits from a 64-bit pointer, output as a hex string. | |
93 StringAppendF(out, "\"%" PRIx64 "\"", static_cast<uint64>( | |
94 reinterpret_cast<intptr_t>( | |
95 value.as_pointer))); | |
96 break; | |
97 case TRACE_VALUE_TYPE_STRING: | |
98 case TRACE_VALUE_TYPE_COPY_STRING: | |
99 *out += "\""; | |
100 start_pos = out->size(); | |
101 *out += value.as_string ? value.as_string : "NULL"; | |
102 // insert backslash before special characters for proper json format. | |
103 while ((start_pos = out->find_first_of("\\\"", start_pos)) != | |
104 std::string::npos) { | |
105 out->insert(start_pos, 1, '\\'); | |
106 // skip inserted escape character and following character. | |
107 start_pos += 2; | |
108 } | |
109 *out += "\""; | |
110 break; | |
111 default: | |
112 NOTREACHED() << "Don't know how to print this value"; | |
113 break; | |
114 } | |
115 } | |
116 | |
117 } // namespace | 72 } // namespace |
118 | 73 |
119 //////////////////////////////////////////////////////////////////////////////// | 74 //////////////////////////////////////////////////////////////////////////////// |
120 // | 75 // |
121 // TraceEvent | 76 // TraceEvent |
122 // | 77 // |
123 //////////////////////////////////////////////////////////////////////////////// | 78 //////////////////////////////////////////////////////////////////////////////// |
124 | 79 |
125 namespace { | 80 namespace { |
126 | 81 |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
218 if (arg_is_copy[i]) | 173 if (arg_is_copy[i]) |
219 CopyTraceEventParameter(&ptr, &arg_values_[i].as_string, end); | 174 CopyTraceEventParameter(&ptr, &arg_values_[i].as_string, end); |
220 } | 175 } |
221 DCHECK_EQ(end, ptr) << "Overrun by " << ptr - end; | 176 DCHECK_EQ(end, ptr) << "Overrun by " << ptr - end; |
222 } | 177 } |
223 } | 178 } |
224 | 179 |
225 TraceEvent::~TraceEvent() { | 180 TraceEvent::~TraceEvent() { |
226 } | 181 } |
227 | 182 |
183 // static | |
184 void TraceEvent::AppendValueAsJSON(unsigned char type, | |
185 TraceEvent::TraceValue value, | |
186 std::string* out) { | |
187 std::string::size_type start_pos; | |
188 switch (type) { | |
189 case TRACE_VALUE_TYPE_BOOL: | |
190 *out += value.as_bool ? "true" : "false"; | |
191 break; | |
192 case TRACE_VALUE_TYPE_UINT: | |
193 StringAppendF(out, "%" PRIu64, static_cast<uint64>(value.as_uint)); | |
194 break; | |
195 case TRACE_VALUE_TYPE_INT: | |
196 StringAppendF(out, "%" PRId64, static_cast<int64>(value.as_int)); | |
197 break; | |
198 case TRACE_VALUE_TYPE_DOUBLE: | |
199 StringAppendF(out, "%f", value.as_double); | |
200 break; | |
201 case TRACE_VALUE_TYPE_POINTER: | |
202 // JSON only supports double and int numbers. | |
203 // So as not to lose bits from a 64-bit pointer, output as a hex string. | |
204 StringAppendF(out, "\"%" PRIx64 "\"", static_cast<uint64>( | |
205 reinterpret_cast<intptr_t>( | |
206 value.as_pointer))); | |
207 break; | |
208 case TRACE_VALUE_TYPE_STRING: | |
209 case TRACE_VALUE_TYPE_COPY_STRING: | |
210 *out += "\""; | |
211 start_pos = out->size(); | |
212 *out += value.as_string ? value.as_string : "NULL"; | |
213 // insert backslash before special characters for proper json format. | |
214 while ((start_pos = out->find_first_of("\\\"", start_pos)) != | |
215 std::string::npos) { | |
216 out->insert(start_pos, 1, '\\'); | |
217 // skip inserted escape character and following character. | |
218 start_pos += 2; | |
219 } | |
220 *out += "\""; | |
221 break; | |
222 default: | |
223 NOTREACHED() << "Don't know how to print this value"; | |
224 break; | |
225 } | |
226 } | |
227 | |
228 void TraceEvent::AppendEventsAsJSON(const std::vector<TraceEvent>& events, | 228 void TraceEvent::AppendEventsAsJSON(const std::vector<TraceEvent>& events, |
229 size_t start, | 229 size_t start, |
230 size_t count, | 230 size_t count, |
231 std::string* out) { | 231 std::string* out) { |
232 for (size_t i = 0; i < count && start + i < events.size(); ++i) { | 232 for (size_t i = 0; i < count && start + i < events.size(); ++i) { |
233 if (i > 0) | 233 if (i > 0) |
234 *out += ","; | 234 *out += ","; |
235 events[i + start].AppendAsJSON(out); | 235 events[i + start].AppendAsJSON(out); |
236 } | 236 } |
237 } | 237 } |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
536 dispatching_to_observer_list_ = false; | 536 dispatching_to_observer_list_ = false; |
537 | 537 |
538 enabled_ = false; | 538 enabled_ = false; |
539 included_categories_.clear(); | 539 included_categories_.clear(); |
540 excluded_categories_.clear(); | 540 excluded_categories_.clear(); |
541 watch_category_ = NULL; | 541 watch_category_ = NULL; |
542 watch_event_name_ = ""; | 542 watch_event_name_ = ""; |
543 for (int i = 0; i < g_category_index; i++) | 543 for (int i = 0; i < g_category_index; i++) |
544 g_category_enabled[i] = 0; | 544 g_category_enabled[i] = 0; |
545 AddThreadNameMetadataEvents(); | 545 AddThreadNameMetadataEvents(); |
546 #if defined(OS_ANDROID) | |
546 AddClockSyncMetadataEvents(); | 547 AddClockSyncMetadataEvents(); |
548 #endif | |
547 } | 549 } |
548 | 550 |
549 void TraceLog::SetEnabled(bool enabled) { | 551 void TraceLog::SetEnabled(bool enabled) { |
550 if (enabled) | 552 if (enabled) |
551 SetEnabled(std::vector<std::string>(), std::vector<std::string>()); | 553 SetEnabled(std::vector<std::string>(), std::vector<std::string>()); |
552 else | 554 else |
553 SetDisabled(); | 555 SetDisabled(); |
554 } | 556 } |
555 | 557 |
556 void TraceLog::AddEnabledStateObserver(EnabledStateChangedObserver* listener) { | 558 void TraceLog::AddEnabledStateObserver(EnabledStateChangedObserver* listener) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
597 const char* name, | 599 const char* name, |
598 unsigned long long id, | 600 unsigned long long id, |
599 int num_args, | 601 int num_args, |
600 const char** arg_names, | 602 const char** arg_names, |
601 const unsigned char* arg_types, | 603 const unsigned char* arg_types, |
602 const unsigned long long* arg_values, | 604 const unsigned long long* arg_values, |
603 int threshold_begin_id, | 605 int threshold_begin_id, |
604 long long threshold, | 606 long long threshold, |
605 unsigned char flags) { | 607 unsigned char flags) { |
606 DCHECK(name); | 608 DCHECK(name); |
609 | |
610 #if defined(OS_ANDROID) | |
611 if (IsATraceEnabled()) { | |
jbates
2012/10/30 20:22:14
This if looks redundant
Xianzhu
2012/10/30 21:45:01
Done.
| |
612 SendToATrace(phase, GetCategoryName(category_enabled), name, | |
613 num_args, arg_names, arg_types, arg_values); | |
614 } | |
615 #endif | |
616 | |
607 TimeTicks now = TimeTicks::NowFromSystemTraceTime(); | 617 TimeTicks now = TimeTicks::NowFromSystemTraceTime(); |
608 NotificationHelper notifier(this); | 618 NotificationHelper notifier(this); |
609 int ret_begin_id = -1; | 619 int ret_begin_id = -1; |
610 { | 620 { |
611 AutoLock lock(lock_); | 621 AutoLock lock(lock_); |
612 if (!*category_enabled) | 622 if (!*category_enabled) |
613 return -1; | 623 return -1; |
614 if (logged_events_.size() >= kTraceEventBufferSize) | 624 if (logged_events_.size() >= kTraceEventBufferSize) |
615 return -1; | 625 return -1; |
616 | 626 |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
734 notifier.SendNotificationIfAny(); | 744 notifier.SendNotificationIfAny(); |
735 } | 745 } |
736 } | 746 } |
737 | 747 |
738 void TraceLog::CancelWatchEvent() { | 748 void TraceLog::CancelWatchEvent() { |
739 AutoLock lock(lock_); | 749 AutoLock lock(lock_); |
740 watch_category_ = NULL; | 750 watch_category_ = NULL; |
741 watch_event_name_ = ""; | 751 watch_event_name_ = ""; |
742 } | 752 } |
743 | 753 |
744 void TraceLog::AddClockSyncMetadataEvents() { | |
745 #if defined(OS_ANDROID) | |
746 // Since Android does not support sched_setaffinity, we cannot establish clock | |
747 // sync unless the scheduler clock is set to global. If the trace_clock file | |
748 // can't be read, we will assume the kernel doesn't support tracing and do | |
749 // nothing. | |
750 std::string clock_mode; | |
751 if (!file_util::ReadFileToString( | |
752 FilePath("/sys/kernel/debug/tracing/trace_clock"), | |
753 &clock_mode)) | |
754 return; | |
755 | |
756 if (clock_mode != "local [global]\n") { | |
757 DLOG(WARNING) << | |
758 "The kernel's tracing clock must be set to global in order for " << | |
759 "trace_event to be synchronized with . Do this by\n" << | |
760 " echo global > /sys/kerel/debug/tracing/trace_clock"; | |
761 return; | |
762 } | |
763 | |
764 // Android's kernel trace system has a trace_marker feature: this is a file on | |
765 // debugfs that takes the written data and pushes it onto the trace | |
766 // buffer. So, to establish clock sync, we write our monotonic clock into that | |
767 // trace buffer. | |
768 TimeTicks now = TimeTicks::NowFromSystemTraceTime(); | |
769 | |
770 double now_in_seconds = now.ToInternalValue() / 1000000.0; | |
771 std::string marker = | |
772 StringPrintf("trace_event_clock_sync: parent_ts=%f\n", | |
773 now_in_seconds); | |
774 if (file_util::WriteFile( | |
775 FilePath("/sys/kernel/debug/tracing/trace_marker"), | |
776 marker.c_str(), marker.size()) == -1) { | |
777 DLOG(WARNING) << "Couldn't write to /sys/kernel/debug/tracing/trace_marker"; | |
778 return; | |
779 } | |
780 #endif | |
781 } | |
782 | |
783 void TraceLog::AddThreadNameMetadataEvents() { | 754 void TraceLog::AddThreadNameMetadataEvents() { |
784 lock_.AssertAcquired(); | 755 lock_.AssertAcquired(); |
785 for(base::hash_map<int, std::string>::iterator it = thread_names_.begin(); | 756 for(base::hash_map<int, std::string>::iterator it = thread_names_.begin(); |
786 it != thread_names_.end(); | 757 it != thread_names_.end(); |
787 it++) { | 758 it++) { |
788 if (!it->second.empty()) { | 759 if (!it->second.empty()) { |
789 int num_args = 1; | 760 int num_args = 1; |
790 const char* arg_name = "name"; | 761 const char* arg_name = "name"; |
791 unsigned char arg_type; | 762 unsigned char arg_type; |
792 unsigned long long arg_value; | 763 unsigned long long arg_value; |
(...skipping 22 matching lines...) Expand all Loading... | |
815 // Create a FNV hash from the process ID for XORing. | 786 // Create a FNV hash from the process ID for XORing. |
816 // See http://isthe.com/chongo/tech/comp/fnv/ for algorithm details. | 787 // See http://isthe.com/chongo/tech/comp/fnv/ for algorithm details. |
817 unsigned long long offset_basis = 14695981039346656037ull; | 788 unsigned long long offset_basis = 14695981039346656037ull; |
818 unsigned long long fnv_prime = 1099511628211ull; | 789 unsigned long long fnv_prime = 1099511628211ull; |
819 unsigned long long pid = static_cast<unsigned long long>(process_id_); | 790 unsigned long long pid = static_cast<unsigned long long>(process_id_); |
820 process_id_hash_ = (offset_basis ^ pid) * fnv_prime; | 791 process_id_hash_ = (offset_basis ^ pid) * fnv_prime; |
821 } | 792 } |
822 | 793 |
823 } // namespace debug | 794 } // namespace debug |
824 } // namespace base | 795 } // namespace base |
OLD | NEW |