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

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

Issue 11345019: Make Chrome Trace work with Android ATrace. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Don't append arguments to name Created 8 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) 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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698