Chromium Code Reviews| 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/base_switches.h" | |
| 9 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/command_line.h" | |
| 10 #include "base/debug/leak_annotations.h" | 12 #include "base/debug/leak_annotations.h" |
| 11 #include "base/debug/trace_event.h" | 13 #include "base/debug/trace_event.h" |
| 12 #include "base/format_macros.h" | 14 #include "base/format_macros.h" |
| 13 #include "base/lazy_instance.h" | 15 #include "base/lazy_instance.h" |
| 14 #include "base/memory/singleton.h" | 16 #include "base/memory/singleton.h" |
| 15 #include "base/process_util.h" | 17 #include "base/process_util.h" |
| 16 #include "base/stl_util.h" | 18 #include "base/stl_util.h" |
| 17 #include "base/strings/string_split.h" | 19 #include "base/strings/string_split.h" |
| 18 #include "base/strings/string_tokenizer.h" | 20 #include "base/strings/string_tokenizer.h" |
| 19 #include "base/strings/string_util.h" | 21 #include "base/strings/string_util.h" |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 60 #define MAX_CATEGORY_GROUPS 100 | 62 #define MAX_CATEGORY_GROUPS 100 |
| 61 | 63 |
| 62 namespace { | 64 namespace { |
| 63 | 65 |
| 64 // Parallel arrays g_category_groups and g_category_group_enabled are separate | 66 // Parallel arrays g_category_groups and g_category_group_enabled are separate |
| 65 // so that a pointer to a member of g_category_group_enabled can be easily | 67 // so that a pointer to a member of g_category_group_enabled can be easily |
| 66 // converted to an index into g_category_groups. This allows macros to deal | 68 // converted to an index into g_category_groups. This allows macros to deal |
| 67 // only with char enabled pointers from g_category_group_enabled, and we can | 69 // only with char enabled pointers from g_category_group_enabled, and we can |
| 68 // convert internally to determine the category name from the char enabled | 70 // convert internally to determine the category name from the char enabled |
| 69 // pointer. | 71 // pointer. |
| 70 const char* g_category_groups[MAX_CATEGORY_GROUPS] = { | 72 const char* g_category_groups[MAX_CATEGORY_GROUPS] = { |
|
willchan no longer on Chromium
2013/07/03 17:55:19
Just noticed, we ought to make this const char* co
| |
| 71 "tracing already shutdown", | 73 "tracing already shutdown", |
| 72 "tracing categories exhausted; must increase MAX_CATEGORY_GROUPS", | 74 "tracing categories exhausted; must increase MAX_CATEGORY_GROUPS", |
| 73 "__metadata", | 75 "__metadata", |
| 74 }; | 76 }; |
| 75 | 77 |
| 76 // The enabled flag is char instead of bool so that the API can be used from C. | 78 // The enabled flag is char instead of bool so that the API can be used from C. |
| 77 unsigned char g_category_group_enabled[MAX_CATEGORY_GROUPS] = { 0 }; | 79 unsigned char g_category_group_enabled[MAX_CATEGORY_GROUPS] = { 0 }; |
| 78 const int g_category_already_shutdown = 0; | 80 const int g_category_already_shutdown = 0; |
| 79 const int g_category_categories_exhausted = 1; | 81 const int g_category_categories_exhausted = 1; |
| 80 const int g_category_metadata = 2; | 82 const int g_category_metadata = 2; |
| (...skipping 713 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 794 ANNOTATE_BENIGN_RACE(&g_category_group_enabled[i], | 796 ANNOTATE_BENIGN_RACE(&g_category_group_enabled[i], |
| 795 "trace_event category enabled"); | 797 "trace_event category enabled"); |
| 796 } | 798 } |
| 797 #if defined(OS_NACL) // NaCl shouldn't expose the process id. | 799 #if defined(OS_NACL) // NaCl shouldn't expose the process id. |
| 798 SetProcessID(0); | 800 SetProcessID(0); |
| 799 #else | 801 #else |
| 800 SetProcessID(static_cast<int>(GetCurrentProcId())); | 802 SetProcessID(static_cast<int>(GetCurrentProcId())); |
| 801 #endif | 803 #endif |
| 802 | 804 |
| 803 logged_events_.reset(GetTraceBuffer()); | 805 logged_events_.reset(GetTraceBuffer()); |
| 806 | |
| 807 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kTraceToConsole)) { | |
|
willchan no longer on Chromium
2013/07/03 17:55:19
Not super fond of this, but since nduca is fine wi
| |
| 808 std::string category_string = | |
| 809 CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | |
| 810 switches::kTraceToConsole); | |
| 811 | |
| 812 if (!category_string.size()) | |
|
willchan no longer on Chromium
2013/07/03 17:55:19
STL doesn't specify the algorithmic complexity of
Ian Vollick
2013/07/03 18:48:03
Switched to empty().
| |
| 813 category_string = "*"; | |
| 814 | |
| 815 SetEnabled(CategoryFilter(category_string), ECHO_TO_CONSOLE); | |
| 816 } | |
| 804 } | 817 } |
| 805 | 818 |
| 806 TraceLog::~TraceLog() { | 819 TraceLog::~TraceLog() { |
| 807 } | 820 } |
| 808 | 821 |
| 809 const unsigned char* TraceLog::GetCategoryGroupEnabled( | 822 const unsigned char* TraceLog::GetCategoryGroupEnabled( |
| 810 const char* category_group) { | 823 const char* category_group) { |
| 811 TraceLog* tracelog = GetInstance(); | 824 TraceLog* tracelog = GetInstance(); |
| 812 if (!tracelog) { | 825 if (!tracelog) { |
| 813 DCHECK(!g_category_group_enabled[g_category_already_shutdown]); | 826 DCHECK(!g_category_group_enabled[g_category_already_shutdown]); |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1057 | 1070 |
| 1058 void TraceLog::SetNotificationCallback( | 1071 void TraceLog::SetNotificationCallback( |
| 1059 const TraceLog::NotificationCallback& cb) { | 1072 const TraceLog::NotificationCallback& cb) { |
| 1060 AutoLock lock(lock_); | 1073 AutoLock lock(lock_); |
| 1061 notification_callback_ = cb; | 1074 notification_callback_ = cb; |
| 1062 } | 1075 } |
| 1063 | 1076 |
| 1064 TraceBuffer* TraceLog::GetTraceBuffer() { | 1077 TraceBuffer* TraceLog::GetTraceBuffer() { |
| 1065 if (trace_options_ & RECORD_CONTINUOUSLY) | 1078 if (trace_options_ & RECORD_CONTINUOUSLY) |
| 1066 return new TraceBufferRingBuffer(); | 1079 return new TraceBufferRingBuffer(); |
| 1067 else if (trace_options_ & ECHO_TO_VLOG) | 1080 else if (trace_options_ & ECHO_TO_CONSOLE) |
| 1068 return new TraceBufferDiscardsEvents(); | 1081 return new TraceBufferDiscardsEvents(); |
| 1069 return new TraceBufferVector(); | 1082 return new TraceBufferVector(); |
| 1070 } | 1083 } |
| 1071 | 1084 |
| 1072 void TraceLog::SetEventCallback(EventCallback cb) { | 1085 void TraceLog::SetEventCallback(EventCallback cb) { |
| 1073 AutoLock lock(lock_); | 1086 AutoLock lock(lock_); |
| 1074 event_callback_ = cb; | 1087 event_callback_ = cb; |
| 1075 }; | 1088 }; |
| 1076 | 1089 |
| 1077 void TraceLog::Flush(const TraceLog::OutputCallback& cb) { | 1090 void TraceLog::Flush(const TraceLog::OutputCallback& cb) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1129 const TimeTicks& timestamp, | 1142 const TimeTicks& timestamp, |
| 1130 int num_args, | 1143 int num_args, |
| 1131 const char** arg_names, | 1144 const char** arg_names, |
| 1132 const unsigned char* arg_types, | 1145 const unsigned char* arg_types, |
| 1133 const unsigned long long* arg_values, | 1146 const unsigned long long* arg_values, |
| 1134 scoped_ptr<ConvertableToTraceFormat> convertable_values[], | 1147 scoped_ptr<ConvertableToTraceFormat> convertable_values[], |
| 1135 unsigned char flags) { | 1148 unsigned char flags) { |
| 1136 DCHECK(name); | 1149 DCHECK(name); |
| 1137 | 1150 |
| 1138 TimeDelta duration; | 1151 TimeDelta duration; |
| 1139 if (phase == TRACE_EVENT_PHASE_END && trace_options_ & ECHO_TO_VLOG) { | 1152 if (phase == TRACE_EVENT_PHASE_END && trace_options_ & ECHO_TO_CONSOLE) { |
| 1140 duration = timestamp - thread_event_start_times_[thread_id].top(); | 1153 duration = timestamp - thread_event_start_times_[thread_id].top(); |
| 1141 thread_event_start_times_[thread_id].pop(); | 1154 thread_event_start_times_[thread_id].pop(); |
| 1142 } | 1155 } |
| 1143 | 1156 |
| 1144 if (flags & TRACE_EVENT_FLAG_MANGLE_ID) | 1157 if (flags & TRACE_EVENT_FLAG_MANGLE_ID) |
| 1145 id ^= process_id_hash_; | 1158 id ^= process_id_hash_; |
| 1146 | 1159 |
| 1147 #if defined(OS_ANDROID) | 1160 #if defined(OS_ANDROID) |
| 1148 SendToATrace(phase, GetCategoryGroupName(category_group_enabled), name, id, | 1161 SendToATrace(phase, GetCategoryGroupName(category_group_enabled), name, id, |
| 1149 num_args, arg_names, arg_types, arg_values, convertable_values, | 1162 num_args, arg_names, arg_types, arg_values, convertable_values, |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1187 bool found = std::find(existing_names.begin(), | 1200 bool found = std::find(existing_names.begin(), |
| 1188 existing_names.end(), | 1201 existing_names.end(), |
| 1189 new_name) != existing_names.end(); | 1202 new_name) != existing_names.end(); |
| 1190 if (!found) { | 1203 if (!found) { |
| 1191 existing_name->second.push_back(','); | 1204 existing_name->second.push_back(','); |
| 1192 existing_name->second.append(new_name); | 1205 existing_name->second.append(new_name); |
| 1193 } | 1206 } |
| 1194 } | 1207 } |
| 1195 } | 1208 } |
| 1196 | 1209 |
| 1197 if (trace_options_ & ECHO_TO_VLOG) { | 1210 if (trace_options_ & ECHO_TO_CONSOLE) { |
| 1198 std::string thread_name = thread_names_[thread_id]; | 1211 std::string thread_name = thread_names_[thread_id]; |
| 1199 if (thread_colors_.find(thread_name) == thread_colors_.end()) | 1212 if (thread_colors_.find(thread_name) == thread_colors_.end()) |
| 1200 thread_colors_[thread_name] = (thread_colors_.size() % 6) + 1; | 1213 thread_colors_[thread_name] = (thread_colors_.size() % 6) + 1; |
| 1201 | 1214 |
| 1202 std::ostringstream log; | 1215 std::ostringstream log; |
| 1203 log << base::StringPrintf("%s: \x1b[0;3%dm", | 1216 log << base::StringPrintf("%s: \x1b[0;3%dm", |
| 1204 thread_name.c_str(), | 1217 thread_name.c_str(), |
| 1205 thread_colors_[thread_name]); | 1218 thread_colors_[thread_name]); |
| 1206 | 1219 |
| 1207 size_t depth = 0; | 1220 size_t depth = 0; |
| 1208 if (thread_event_start_times_.find(thread_id) != | 1221 if (thread_event_start_times_.find(thread_id) != |
| 1209 thread_event_start_times_.end()) | 1222 thread_event_start_times_.end()) |
| 1210 depth = thread_event_start_times_[thread_id].size(); | 1223 depth = thread_event_start_times_[thread_id].size(); |
| 1211 | 1224 |
| 1212 for (size_t i = 0; i < depth; ++i) | 1225 for (size_t i = 0; i < depth; ++i) |
| 1213 log << "| "; | 1226 log << "| "; |
| 1214 | 1227 |
| 1215 log << base::StringPrintf("'%c', %s", phase, name); | 1228 log << base::StringPrintf("'%c', %s", phase, name); |
| 1216 | 1229 |
| 1217 if (phase == TRACE_EVENT_PHASE_END) | 1230 if (phase == TRACE_EVENT_PHASE_END) |
| 1218 log << base::StringPrintf(" (%.3f ms)", duration.InMillisecondsF()); | 1231 log << base::StringPrintf(" (%.3f ms)", duration.InMillisecondsF()); |
| 1219 | 1232 |
| 1220 VLOG(0) << log.str() << "\x1b[0;m"; | 1233 LOG(ERROR) << log.str() << "\x1b[0;m"; |
| 1221 } | 1234 } |
| 1222 | 1235 |
| 1223 logged_events_->AddEvent(TraceEvent(thread_id, | 1236 logged_events_->AddEvent(TraceEvent(thread_id, |
| 1224 now, phase, category_group_enabled, name, id, | 1237 now, phase, category_group_enabled, name, id, |
| 1225 num_args, arg_names, arg_types, arg_values, | 1238 num_args, arg_names, arg_types, arg_values, |
| 1226 convertable_values, flags)); | 1239 convertable_values, flags)); |
| 1227 | 1240 |
| 1228 if (logged_events_->IsFull()) | 1241 if (logged_events_->IsFull()) |
| 1229 notifier.AddNotificationWhileLocked(TRACE_BUFFER_FULL); | 1242 notifier.AddNotificationWhileLocked(TRACE_BUFFER_FULL); |
| 1230 | 1243 |
| 1231 if (watch_category_ == category_group_enabled && watch_event_name_ == name) | 1244 if (watch_category_ == category_group_enabled && watch_event_name_ == name) |
| 1232 notifier.AddNotificationWhileLocked(EVENT_WATCH_NOTIFICATION); | 1245 notifier.AddNotificationWhileLocked(EVENT_WATCH_NOTIFICATION); |
| 1233 } while (0); // release lock | 1246 } while (0); // release lock |
| 1234 | 1247 |
| 1235 if (phase == TRACE_EVENT_PHASE_BEGIN && trace_options_ & ECHO_TO_VLOG) | 1248 if (phase == TRACE_EVENT_PHASE_BEGIN && trace_options_ & ECHO_TO_CONSOLE) |
| 1236 thread_event_start_times_[thread_id].push(timestamp); | 1249 thread_event_start_times_[thread_id].push(timestamp); |
| 1237 | 1250 |
| 1238 notifier.SendNotificationIfAny(); | 1251 notifier.SendNotificationIfAny(); |
| 1239 if (event_callback_copy != NULL) { | 1252 if (event_callback_copy != NULL) { |
| 1240 event_callback_copy(phase, category_group_enabled, name, id, | 1253 event_callback_copy(phase, category_group_enabled, name, id, |
| 1241 num_args, arg_names, arg_types, arg_values, | 1254 num_args, arg_names, arg_types, arg_values, |
| 1242 flags); | 1255 flags); |
| 1243 } | 1256 } |
| 1244 } | 1257 } |
| 1245 | 1258 |
| (...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1549 0, // num_args | 1562 0, // num_args |
| 1550 NULL, // arg_names | 1563 NULL, // arg_names |
| 1551 NULL, // arg_types | 1564 NULL, // arg_types |
| 1552 NULL, // arg_values | 1565 NULL, // arg_values |
| 1553 NULL, // convertable values | 1566 NULL, // convertable values |
| 1554 TRACE_EVENT_FLAG_NONE); // flags | 1567 TRACE_EVENT_FLAG_NONE); // flags |
| 1555 } | 1568 } |
| 1556 } | 1569 } |
| 1557 | 1570 |
| 1558 } // namespace trace_event_internal | 1571 } // namespace trace_event_internal |
| OLD | NEW |