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

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

Issue 9155024: Allow tracing in third_party libraries (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: jar feedback Created 8 years, 11 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
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/file_util.h" 10 #include "base/file_util.h"
(...skipping 27 matching lines...) Expand all
38 38
39 // Controls the number of trace events we will buffer in-memory 39 // Controls the number of trace events we will buffer in-memory
40 // before throwing them away. 40 // before throwing them away.
41 const size_t kTraceEventBufferSize = 500000; 41 const size_t kTraceEventBufferSize = 500000;
42 const size_t kTraceEventBatchSize = 1000; 42 const size_t kTraceEventBatchSize = 1000;
43 43
44 #define TRACE_EVENT_MAX_CATEGORIES 100 44 #define TRACE_EVENT_MAX_CATEGORIES 100
45 45
46 namespace { 46 namespace {
47 47
48 // Specify these values when the corresponding argument of AddTraceEvent is not 48 // Parallel arrays g_categories and g_category_enabled are separate so that
49 // used. 49 // a pointer to a member of g_category_enabled can be easily converted to an
50 static const char* kNoArgName = NULL; 50 // index into g_categories. This allows macros to deal only with bool enabled
51 static const int kNoArgValue = 0; 51 // pointers from g_category_enabled, and we can convert internally to determine
52 static const int kNoThreshholdBeginId = -1; 52 // the category name from the bool enabled pointer.
53 static const int64 kNoThresholdValue = 0; 53 const char* g_categories[TRACE_EVENT_MAX_CATEGORIES] = {
54 static const int kNoEventId = 0; 54 "tracing already shutdown",
55 55 "tracing categories exhausted; must increase TRACE_EVENT_MAX_CATEGORIES",
56 TraceCategory g_categories[TRACE_EVENT_MAX_CATEGORIES] = { 56 "__metadata",
57 { "tracing already shutdown", false },
58 { "tracing categories exhausted; must increase TRACE_EVENT_MAX_CATEGORIES",
59 false },
60 { "__metadata",
61 false }
62 }; 57 };
63 const TraceCategory* const g_category_already_shutdown = 58 volatile bool g_category_enabled[TRACE_EVENT_MAX_CATEGORIES] = { false };
jar (doing other things) 2012/01/12 02:20:03 Here again, I doubt volatile is providing signific
jbates 2012/01/12 19:41:29 The only behavior I expected from volatile was to
jar (doing other things) 2012/01/12 21:48:43 Two things: a) You're movin' away from volatile,
jbates 2012/01/12 22:22:11 I don't think that is possible thanks to cache coh
64 &g_categories[0]; 59 const int g_category_already_shutdown = 0;
65 const TraceCategory* const g_category_categories_exhausted = 60 const int g_category_categories_exhausted = 1;
66 &g_categories[1]; 61 const int g_category_metadata = 2;
67 const TraceCategory* const g_category_metadata =
68 &g_categories[2];
69 int g_category_index = 3; // skip initial 3 categories 62 int g_category_index = 3; // skip initial 3 categories
70 63
71 // The most-recently captured name of the current thread 64 // The most-recently captured name of the current thread
72 LazyInstance<ThreadLocalPointer<const char>, 65 LazyInstance<ThreadLocalPointer<const char>,
73 LeakyLazyInstanceTraits<ThreadLocalPointer<const char> > > 66 LeakyLazyInstanceTraits<ThreadLocalPointer<const char> > >
74 g_current_thread_name = LAZY_INSTANCE_INITIALIZER; 67 g_current_thread_name = LAZY_INSTANCE_INITIALIZER;
75 68
76 } // namespace 69 void AppendValueAsJSON(uint8 type,
77 70 TraceEvent::TraceValue value,
78 //////////////////////////////////////////////////////////////////////////////// 71 std::string* out) {
79 //
80 // TraceValue
81 //
82 ////////////////////////////////////////////////////////////////////////////////
83
84 void TraceValue::AppendAsJSON(std::string* out) const {
85 std::string::size_type start_pos; 72 std::string::size_type start_pos;
86 switch (type_) { 73 switch (type) {
87 case TRACE_TYPE_BOOL: 74 case TRACE_VALUE_TYPE_BOOL:
88 *out += as_bool() ? "true" : "false"; 75 *out += value.as_bool ? "true" : "false";
89 break; 76 break;
90 case TRACE_TYPE_UINT: 77 case TRACE_VALUE_TYPE_UINT:
91 StringAppendF(out, "%" PRIu64, as_uint()); 78 StringAppendF(out, "%" PRIu64, value.as_uint);
92 break; 79 break;
93 case TRACE_TYPE_INT: 80 case TRACE_VALUE_TYPE_INT:
94 StringAppendF(out, "%" PRId64, as_int()); 81 StringAppendF(out, "%" PRId64, value.as_int);
95 break; 82 break;
96 case TRACE_TYPE_DOUBLE: 83 case TRACE_VALUE_TYPE_DOUBLE:
97 StringAppendF(out, "%f", as_double()); 84 StringAppendF(out, "%f", value.as_double);
98 break; 85 break;
99 case TRACE_TYPE_POINTER: 86 case TRACE_VALUE_TYPE_POINTER:
100 // JSON only supports double and int numbers. 87 // JSON only supports double and int numbers.
101 // So as not to lose bits from a 64-bit pointer, output as a hex string. 88 // So as not to lose bits from a 64-bit pointer, output as a hex string.
102 StringAppendF(out, "\"%" PRIx64 "\"", static_cast<uint64>( 89 StringAppendF(out, "\"%" PRIx64 "\"", static_cast<uint64>(
103 reinterpret_cast<intptr_t>( 90 reinterpret_cast<intptr_t>(
104 as_pointer()))); 91 value.as_pointer)));
105 break; 92 break;
106 case TRACE_TYPE_STRING: 93 case TRACE_VALUE_TYPE_STRING:
107 case TRACE_TYPE_STATIC_STRING: 94 case TRACE_VALUE_TYPE_COPY_STRING:
108 *out += "\""; 95 *out += "\"";
109 start_pos = out->size(); 96 start_pos = out->size();
110 *out += as_string() ? as_string() : "NULL"; 97 *out += value.as_string ? value.as_string : "NULL";
111 // insert backslash before special characters for proper json format. 98 // insert backslash before special characters for proper json format.
112 while ((start_pos = out->find_first_of("\\\"", start_pos)) != 99 while ((start_pos = out->find_first_of("\\\"", start_pos)) !=
113 std::string::npos) { 100 std::string::npos) {
114 out->insert(start_pos, 1, '\\'); 101 out->insert(start_pos, 1, '\\');
115 // skip inserted escape character and following character. 102 // skip inserted escape character and following character.
116 start_pos += 2; 103 start_pos += 2;
117 } 104 }
118 *out += "\""; 105 *out += "\"";
119 break; 106 break;
120 default: 107 default:
121 NOTREACHED() << "Don't know how to print this value"; 108 NOTREACHED() << "Don't know how to print this value";
122 break; 109 break;
123 } 110 }
124 } 111 }
125 112
126 //////////////////////////////////////////////////////////////////////////////// 113 } // namespace
127 //
128 // TraceID
129 //
130 ////////////////////////////////////////////////////////////////////////////////
131
132 TraceID::TraceID(void* rhs) {
133 data_ = base::debug::TraceLog::GetInstance()->GetIntraProcessID(
134 static_cast<uint64>(reinterpret_cast<uintptr_t>(rhs)));
135 }
136 114
137 //////////////////////////////////////////////////////////////////////////////// 115 ////////////////////////////////////////////////////////////////////////////////
138 // 116 //
139 // TraceEvent 117 // TraceEvent
140 // 118 //
141 //////////////////////////////////////////////////////////////////////////////// 119 ////////////////////////////////////////////////////////////////////////////////
142 120
143 namespace { 121 namespace {
144 122
145 size_t GetAllocLength(const char* str) { return str ? strlen(str) + 1 : 0; } 123 size_t GetAllocLength(const char* str) { return str ? strlen(str) + 1 : 0; }
146 124
147 // Copies |*member| into |*buffer|, sets |*member| to point to this new 125 // Copies |*member| into |*buffer|, sets |*member| to point to this new
148 // location, and then advances |*buffer| by the amount written. 126 // location, and then advances |*buffer| by the amount written.
149 void CopyTraceEventParameter(char** buffer, 127 void CopyTraceEventParameter(char** buffer,
150 const char** member, 128 const char** member,
151 const char* end) { 129 const char* end) {
152 if (*member) { 130 if (*member) {
153 size_t written = strlcpy(*buffer, *member, end - *buffer) + 1; 131 size_t written = strlcpy(*buffer, *member, end - *buffer) + 1;
154 DCHECK_LE(static_cast<int>(written), end - *buffer); 132 DCHECK_LE(static_cast<int>(written), end - *buffer);
155 *member = *buffer; 133 *member = *buffer;
156 *buffer += written; 134 *buffer += written;
157 } 135 }
158 } 136 }
159 137
160 } // namespace 138 } // namespace
161 139
162 TraceEvent::TraceEvent() 140 TraceEvent::TraceEvent()
163 : id_(0u), 141 : id_(0u),
164 category_(NULL), 142 category_enabled_(NULL),
165 name_(NULL), 143 name_(NULL),
166 thread_id_(0), 144 thread_id_(0),
167 phase_(TRACE_EVENT_PHASE_BEGIN), 145 phase_(TRACE_EVENT_PHASE_BEGIN),
168 flags_(0) { 146 flags_(0) {
169 arg_names_[0] = NULL; 147 arg_names_[0] = NULL;
170 arg_names_[1] = NULL; 148 arg_names_[1] = NULL;
171 } 149 }
172 150
173 TraceEvent::TraceEvent(int thread_id, 151 TraceEvent::TraceEvent(int thread_id,
174 TimeTicks timestamp, 152 TimeTicks timestamp,
175 TraceEventPhase phase, 153 char phase,
176 const TraceCategory* category, 154 const volatile bool* category_enabled,
177 const char* name, 155 const char* name,
178 TraceID id, 156 uint64 id,
179 const char* arg1_name, const TraceValue& arg1_val, 157 int num_args,
180 const char* arg2_name, const TraceValue& arg2_val, 158 const char** arg_names,
181 TraceEventFlags flags) 159 const uint8* arg_types,
160 const uint64* arg_values,
161 uint8 flags)
182 : timestamp_(timestamp), 162 : timestamp_(timestamp),
183 id_(id), 163 id_(id),
184 category_(category), 164 category_enabled_(category_enabled),
185 name_(name), 165 name_(name),
186 thread_id_(thread_id), 166 thread_id_(thread_id),
187 phase_(phase), 167 phase_(phase),
188 flags_(flags) { 168 flags_(flags) {
189 COMPILE_ASSERT(kTraceMaxNumArgs == 2, TraceEvent_arg_count_out_of_sync); 169 // Clamp num_args since it may have been set by a third_party library.
190 arg_names_[0] = arg1_name; 170 num_args = (num_args > kTraceMaxNumArgs) ? kTraceMaxNumArgs : num_args;
191 arg_names_[1] = arg2_name; 171 int i = 0;
192 arg_values_[0] = arg1_val; 172 for (; i < num_args; ++i) {
193 arg_values_[1] = arg2_val; 173 arg_names_[i] = arg_names[i];
174 arg_values_[i].as_uint = arg_values[i];
175 arg_types_[i] = arg_types[i];
176 }
177 for (; i < kTraceMaxNumArgs; ++i) {
178 arg_names_[i] = NULL;
179 arg_values_[i].as_uint = 0u;
180 arg_types_[i] = TRACE_VALUE_TYPE_UINT;
181 }
194 182
195 bool copy = !!(flags & TRACE_EVENT_FLAG_COPY); 183 bool copy = !!(flags & TRACE_EVENT_FLAG_COPY);
196 size_t alloc_size = 0; 184 size_t alloc_size = 0;
197 if (copy) { 185 if (copy) {
198 alloc_size += GetAllocLength(name); 186 alloc_size += GetAllocLength(name);
199 alloc_size += GetAllocLength(arg1_name); 187 for (i = 0; i < num_args; ++i) {
200 alloc_size += GetAllocLength(arg2_name); 188 alloc_size += GetAllocLength(arg_names_[i]);
189 if (arg_types_[i] == TRACE_VALUE_TYPE_STRING)
190 arg_types_[i] = TRACE_VALUE_TYPE_COPY_STRING;
191 }
201 } 192 }
202 193
203 bool arg1_is_copy = (arg1_val.type() == TraceValue::TRACE_TYPE_STRING); 194 bool arg_is_copy[kTraceMaxNumArgs];
204 bool arg2_is_copy = (arg2_val.type() == TraceValue::TRACE_TYPE_STRING); 195 for (i = 0; i < num_args; ++i) {
205 196 // We only take a copy of arg_vals if they are of type COPY_STRING.
206 // We only take a copy of arg_vals if they are of type string (not static 197 arg_is_copy[i] = (arg_types_[i] == TRACE_VALUE_TYPE_COPY_STRING);
207 // string), regardless of the |copy| flag. 198 if (arg_is_copy[i])
208 if (arg1_is_copy) 199 alloc_size += GetAllocLength(arg_values_[i].as_string);
209 alloc_size += GetAllocLength(arg1_val.as_string()); 200 }
210 if (arg2_is_copy)
211 alloc_size += GetAllocLength(arg2_val.as_string());
212 201
213 if (alloc_size) { 202 if (alloc_size) {
214 parameter_copy_storage_ = new base::RefCountedString; 203 parameter_copy_storage_ = new base::RefCountedString;
215 parameter_copy_storage_->data().resize(alloc_size); 204 parameter_copy_storage_->data().resize(alloc_size);
216 char* ptr = string_as_array(&parameter_copy_storage_->data()); 205 char* ptr = string_as_array(&parameter_copy_storage_->data());
217 const char* end = ptr + alloc_size; 206 const char* end = ptr + alloc_size;
218 if (copy) { 207 if (copy) {
219 CopyTraceEventParameter(&ptr, &name_, end); 208 CopyTraceEventParameter(&ptr, &name_, end);
220 CopyTraceEventParameter(&ptr, &arg_names_[0], end); 209 for (i = 0; i < num_args; ++i)
221 CopyTraceEventParameter(&ptr, &arg_names_[1], end); 210 CopyTraceEventParameter(&ptr, &arg_names_[i], end);
222 } 211 }
223 if (arg1_is_copy) 212 for (i = 0; i < num_args; ++i) {
224 CopyTraceEventParameter(&ptr, arg_values_[0].as_assignable_string(), end); 213 if (arg_is_copy[i])
225 if (arg2_is_copy) 214 CopyTraceEventParameter(&ptr, &arg_values_[i].as_string, end);
226 CopyTraceEventParameter(&ptr, arg_values_[1].as_assignable_string(), end); 215 }
227 DCHECK_EQ(end, ptr) << "Overrun by " << ptr - end; 216 DCHECK_EQ(end, ptr) << "Overrun by " << ptr - end;
228 } 217 }
229 } 218 }
230 219
231 TraceEvent::~TraceEvent() { 220 TraceEvent::~TraceEvent() {
232 } 221 }
233 222
234 void TraceEvent::AppendEventsAsJSON(const std::vector<TraceEvent>& events, 223 void TraceEvent::AppendEventsAsJSON(const std::vector<TraceEvent>& events,
235 size_t start, 224 size_t start,
236 size_t count, 225 size_t count,
237 std::string* out) { 226 std::string* out) {
238 for (size_t i = 0; i < count && start + i < events.size(); ++i) { 227 for (size_t i = 0; i < count && start + i < events.size(); ++i) {
239 if (i > 0) 228 if (i > 0)
240 *out += ","; 229 *out += ",";
241 events[i + start].AppendAsJSON(out); 230 events[i + start].AppendAsJSON(out);
242 } 231 }
243 } 232 }
244 233
245 void TraceEvent::AppendAsJSON(std::string* out) const { 234 void TraceEvent::AppendAsJSON(std::string* out) const {
246 const char phase_char = GetPhaseChar(phase_);
247 int64 time_int64 = timestamp_.ToInternalValue(); 235 int64 time_int64 = timestamp_.ToInternalValue();
248 int process_id = TraceLog::GetInstance()->process_id(); 236 int process_id = TraceLog::GetInstance()->process_id();
249 // Category name checked at category creation time. 237 // Category name checked at category creation time.
250 DCHECK(!strchr(name_, '"')); 238 DCHECK(!strchr(name_, '"'));
251 StringAppendF(out, 239 StringAppendF(out,
252 "{\"cat\":\"%s\",\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64 "," 240 "{\"cat\":\"%s\",\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64 ","
253 "\"ph\":\"%c\",\"name\":\"%s\",\"args\":{", 241 "\"ph\":\"%c\",\"name\":\"%s\",\"args\":{",
254 category_->name, 242 TraceLog::GetCategoryName(category_enabled_),
255 process_id, 243 process_id,
256 thread_id_, 244 thread_id_,
257 time_int64, 245 time_int64,
258 phase_char, 246 phase_,
259 name_); 247 name_);
260 248
261 // Output argument names and values, stop at first NULL argument name. 249 // Output argument names and values, stop at first NULL argument name.
262 for (size_t i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) { 250 for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) {
263 if (i > 0) 251 if (i > 0)
264 *out += ","; 252 *out += ",";
265 *out += "\""; 253 *out += "\"";
266 *out += arg_names_[i]; 254 *out += arg_names_[i];
267 *out += "\":"; 255 *out += "\":";
268 arg_values_[i].AppendAsJSON(out); 256 AppendValueAsJSON(arg_types_[i], arg_values_[i], out);
269 } 257 }
270 *out += "}"; 258 *out += "}";
271 259
272 // If id_ is set, print it out as a hex string so we don't loose any 260 // If id_ is set, print it out as a hex string so we don't loose any
273 // bits (it might be a 64-bit pointer). 261 // bits (it might be a 64-bit pointer).
274 if (flags_ & TRACE_EVENT_FLAG_HAS_ID) 262 if (flags_ & TRACE_EVENT_FLAG_HAS_ID)
275 StringAppendF(out, ",\"id\":\"%" PRIx64 "\"", id_.data()); 263 StringAppendF(out, ",\"id\":\"%" PRIx64 "\"", id_);
276 *out += "}"; 264 *out += "}";
277 } 265 }
278 266
279 //////////////////////////////////////////////////////////////////////////////// 267 ////////////////////////////////////////////////////////////////////////////////
280 // 268 //
281 // TraceResultBuffer 269 // TraceResultBuffer
282 // 270 //
283 //////////////////////////////////////////////////////////////////////////////// 271 ////////////////////////////////////////////////////////////////////////////////
284 272
285 TraceResultBuffer::OutputCallback 273 TraceResultBuffer::OutputCallback
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
331 } 319 }
332 320
333 TraceLog::TraceLog() 321 TraceLog::TraceLog()
334 : enabled_(false) { 322 : enabled_(false) {
335 SetProcessID(static_cast<int>(base::GetCurrentProcId())); 323 SetProcessID(static_cast<int>(base::GetCurrentProcId()));
336 } 324 }
337 325
338 TraceLog::~TraceLog() { 326 TraceLog::~TraceLog() {
339 } 327 }
340 328
341 const TraceCategory* TraceLog::GetCategory(const char* name) { 329 const volatile bool* TraceLog::GetCategoryEnabled(const char* name) {
342 TraceLog* tracelog = GetInstance(); 330 TraceLog* tracelog = GetInstance();
343 if (!tracelog){ 331 if (!tracelog){
344 DCHECK(!g_category_already_shutdown->enabled); 332 DCHECK(!g_category_enabled[g_category_already_shutdown]);
345 return g_category_already_shutdown; 333 return &g_category_enabled[g_category_already_shutdown];
346 } 334 }
347 return tracelog->GetCategoryInternal(name); 335 return tracelog->GetCategoryEnabledInternal(name);
336 }
337
338 const char* TraceLog::GetCategoryName(const volatile bool* category_enabled) {
339 // Calculate the index of the category by finding category_enabled in
340 // g_category_enabled array.
341 uintptr_t category_begin = reinterpret_cast<uintptr_t>(g_category_enabled);
342 uintptr_t category_ptr = reinterpret_cast<uintptr_t>(category_enabled);
343 DCHECK(category_ptr >= category_begin &&
344 category_ptr < reinterpret_cast<uintptr_t>(g_category_enabled +
345 TRACE_EVENT_MAX_CATEGORIES)) <<
346 "out of bounds category pointer";
347 uintptr_t category_index =
348 (category_ptr - category_begin) / sizeof(g_category_enabled[0]);
349 return g_categories[category_index];
348 } 350 }
349 351
350 static void EnableMatchingCategory(int category_index, 352 static void EnableMatchingCategory(int category_index,
351 const std::vector<std::string>& patterns, 353 const std::vector<std::string>& patterns,
352 bool is_included) { 354 bool is_included) {
353 std::vector<std::string>::const_iterator ci = patterns.begin(); 355 std::vector<std::string>::const_iterator ci = patterns.begin();
354 bool is_match = false; 356 bool is_match = false;
355 for (; ci != patterns.end(); ++ci) { 357 for (; ci != patterns.end(); ++ci) {
356 is_match = MatchPattern(g_categories[category_index].name, ci->c_str()); 358 is_match = MatchPattern(g_categories[category_index], ci->c_str());
357 if (is_match) 359 if (is_match)
358 break; 360 break;
359 } 361 }
360 ANNOTATE_BENIGN_RACE(&g_categories[category_index].enabled, 362 ANNOTATE_BENIGN_RACE(&g_category_enabled[category_index],
361 "trace_event category enabled"); 363 "trace_event category enabled");
362 g_categories[category_index].enabled = is_match ? is_included : !is_included; 364 g_category_enabled[category_index] = is_match ? is_included : !is_included;
363 } 365 }
364 366
365 // Enable/disable each category based on the category filters in |patterns|. 367 // Enable/disable each category based on the category filters in |patterns|.
366 // If the category name matches one of the patterns, its enabled status is set 368 // If the category name matches one of the patterns, its enabled status is set
367 // to |is_included|. Otherwise its enabled status is set to !|is_included|. 369 // to |is_included|. Otherwise its enabled status is set to !|is_included|.
368 static void EnableMatchingCategories(const std::vector<std::string>& patterns, 370 static void EnableMatchingCategories(const std::vector<std::string>& patterns,
369 bool is_included) { 371 bool is_included) {
370 for (int i = 0; i < g_category_index; i++) 372 for (int i = 0; i < g_category_index; i++)
371 EnableMatchingCategory(i, patterns, is_included); 373 EnableMatchingCategory(i, patterns, is_included);
372 } 374 }
373 375
374 const TraceCategory* TraceLog::GetCategoryInternal(const char* name) { 376 const volatile bool* TraceLog::GetCategoryEnabledInternal(const char* name) {
375 AutoLock lock(lock_); 377 AutoLock lock(lock_);
376 DCHECK(!strchr(name, '"')) << "Category names may not contain double quote"; 378 DCHECK(!strchr(name, '"')) << "Category names may not contain double quote";
377 379
378 // Search for pre-existing category matching this name 380 // Search for pre-existing category matching this name
379 for (int i = 0; i < g_category_index; i++) { 381 for (int i = 0; i < g_category_index; i++) {
380 if (strcmp(g_categories[i].name, name) == 0) 382 if (strcmp(g_categories[i], name) == 0)
381 return &g_categories[i]; 383 return &g_category_enabled[i];
382 } 384 }
383 385
384 // Create a new category 386 // Create a new category
385 DCHECK(g_category_index < TRACE_EVENT_MAX_CATEGORIES) << 387 DCHECK(g_category_index < TRACE_EVENT_MAX_CATEGORIES) <<
386 "must increase TRACE_EVENT_MAX_CATEGORIES"; 388 "must increase TRACE_EVENT_MAX_CATEGORIES";
387 if (g_category_index < TRACE_EVENT_MAX_CATEGORIES) { 389 if (g_category_index < TRACE_EVENT_MAX_CATEGORIES) {
388 int new_index = g_category_index++; 390 int new_index = g_category_index++;
389 g_categories[new_index].name = name; 391 g_categories[new_index] = name;
390 DCHECK(!g_categories[new_index].enabled); 392 DCHECK(!g_category_enabled[new_index]);
391 if (enabled_) { 393 if (enabled_) {
392 // Note that if both included and excluded_categories are empty, the else 394 // Note that if both included and excluded_categories are empty, the else
393 // clause below excludes nothing, thereby enabling this category. 395 // clause below excludes nothing, thereby enabling this category.
394 if (!included_categories_.empty()) 396 if (!included_categories_.empty())
395 EnableMatchingCategory(new_index, included_categories_, true); 397 EnableMatchingCategory(new_index, included_categories_, true);
396 else 398 else
397 EnableMatchingCategory(new_index, excluded_categories_, false); 399 EnableMatchingCategory(new_index, excluded_categories_, false);
398 } else { 400 } else {
399 ANNOTATE_BENIGN_RACE(&g_categories[new_index].enabled, 401 ANNOTATE_BENIGN_RACE(&g_category_enabled[new_index],
400 "trace_event category enabled"); 402 "trace_event category enabled");
401 g_categories[new_index].enabled = false; 403 g_category_enabled[new_index] = false;
402 } 404 }
403 return &g_categories[new_index]; 405 return &g_category_enabled[new_index];
404 } else { 406 } else {
405 return g_category_categories_exhausted; 407 return &g_category_enabled[g_category_categories_exhausted];
406 } 408 }
407 } 409 }
408 410
409 void TraceLog::GetKnownCategories(std::vector<std::string>* categories) { 411 void TraceLog::GetKnownCategories(std::vector<std::string>* categories) {
410 AutoLock lock(lock_); 412 AutoLock lock(lock_);
411 for (int i = 0; i < g_category_index; i++) 413 for (int i = 0; i < g_category_index; i++)
412 categories->push_back(g_categories[i].name); 414 categories->push_back(g_categories[i]);
413 } 415 }
414 416
415 void TraceLog::SetEnabled(const std::vector<std::string>& included_categories, 417 void TraceLog::SetEnabled(const std::vector<std::string>& included_categories,
416 const std::vector<std::string>& excluded_categories) { 418 const std::vector<std::string>& excluded_categories) {
417 AutoLock lock(lock_); 419 AutoLock lock(lock_);
418 if (enabled_) 420 if (enabled_)
419 return; 421 return;
420 logged_events_.reserve(1024); 422 logged_events_.reserve(1024);
421 enabled_ = true; 423 enabled_ = true;
422 included_categories_ = included_categories; 424 included_categories_ = included_categories;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 void TraceLog::SetDisabled() { 465 void TraceLog::SetDisabled() {
464 { 466 {
465 AutoLock lock(lock_); 467 AutoLock lock(lock_);
466 if (!enabled_) 468 if (!enabled_)
467 return; 469 return;
468 470
469 enabled_ = false; 471 enabled_ = false;
470 included_categories_.clear(); 472 included_categories_.clear();
471 excluded_categories_.clear(); 473 excluded_categories_.clear();
472 for (int i = 0; i < g_category_index; i++) 474 for (int i = 0; i < g_category_index; i++)
473 g_categories[i].enabled = false; 475 g_category_enabled[i] = false;
474 AddThreadNameMetadataEvents(); 476 AddThreadNameMetadataEvents();
475 AddClockSyncMetadataEvents(); 477 AddClockSyncMetadataEvents();
476 } // release lock 478 } // release lock
477 Flush(); 479 Flush();
478 } 480 }
479 481
480 void TraceLog::SetEnabled(bool enabled) { 482 void TraceLog::SetEnabled(bool enabled) {
481 if (enabled) 483 if (enabled)
482 SetEnabled(std::vector<std::string>(), std::vector<std::string>()); 484 SetEnabled(std::vector<std::string>(), std::vector<std::string>());
483 else 485 else
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
516 scoped_refptr<RefCountedString> json_events_str_ptr = 518 scoped_refptr<RefCountedString> json_events_str_ptr =
517 new RefCountedString(); 519 new RefCountedString();
518 TraceEvent::AppendEventsAsJSON(previous_logged_events, 520 TraceEvent::AppendEventsAsJSON(previous_logged_events,
519 i, 521 i,
520 kTraceEventBatchSize, 522 kTraceEventBatchSize,
521 &(json_events_str_ptr->data)); 523 &(json_events_str_ptr->data));
522 output_callback_copy.Run(json_events_str_ptr); 524 output_callback_copy.Run(json_events_str_ptr);
523 } 525 }
524 } 526 }
525 527
526 int TraceLog::AddTraceEvent(TraceEventPhase phase, 528 int TraceLog::AddTraceEvent(char phase,
527 const TraceCategory* category, 529 const volatile bool* category_enabled,
528 const char* name, 530 const char* name,
529 TraceID id, 531 uint64 id,
530 const char* arg1_name, TraceValue arg1_val, 532 int num_args,
531 const char* arg2_name, TraceValue arg2_val, 533 const char** arg_names,
534 const uint8* arg_types,
535 const uint64* arg_values,
532 int threshold_begin_id, 536 int threshold_begin_id,
533 int64 threshold, 537 int64 threshold,
534 TraceEventFlags flags) { 538 uint8 flags) {
535 DCHECK(name); 539 DCHECK(name);
536 TimeTicks now = TimeTicks::HighResNow(); 540 TimeTicks now = TimeTicks::HighResNow();
537 BufferFullCallback buffer_full_callback_copy; 541 BufferFullCallback buffer_full_callback_copy;
538 int ret_begin_id = -1; 542 int ret_begin_id = -1;
539 { 543 {
540 AutoLock lock(lock_); 544 AutoLock lock(lock_);
541 if (!category->enabled) 545 if (!*category_enabled)
542 return -1; 546 return -1;
543 if (logged_events_.size() >= kTraceEventBufferSize) 547 if (logged_events_.size() >= kTraceEventBufferSize)
544 return -1; 548 return -1;
545 549
546 int thread_id = static_cast<int>(PlatformThread::CurrentId()); 550 int thread_id = static_cast<int>(PlatformThread::CurrentId());
547 551
548 const char* new_name = PlatformThread::GetName(); 552 const char* new_name = PlatformThread::GetName();
549 // Check if the thread name has been set or changed since the previous 553 // Check if the thread name has been set or changed since the previous
550 // call (if any), but don't bother if the new name is empty. Note this will 554 // call (if any), but don't bother if the new name is empty. Note this will
551 // not detect a thread name change within the same char* buffer address: we 555 // not detect a thread name change within the same char* buffer address: we
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
585 // Remove begin event and do not add end event. 589 // Remove begin event and do not add end event.
586 // This will be expensive if there have been other events in the 590 // This will be expensive if there have been other events in the
587 // mean time (should be rare). 591 // mean time (should be rare).
588 logged_events_.erase(logged_events_.begin() + begin_i); 592 logged_events_.erase(logged_events_.begin() + begin_i);
589 return -1; 593 return -1;
590 } 594 }
591 } 595 }
592 ret_begin_id = static_cast<int>(logged_events_.size()); 596 ret_begin_id = static_cast<int>(logged_events_.size());
593 logged_events_.push_back( 597 logged_events_.push_back(
594 TraceEvent(thread_id, 598 TraceEvent(thread_id,
595 now, phase, category, name, id, 599 now, phase, category_enabled, name, id,
596 arg1_name, arg1_val, 600 num_args, arg_names, arg_types, arg_values,
597 arg2_name, arg2_val,
598 flags)); 601 flags));
599 602
600 if (logged_events_.size() == kTraceEventBufferSize) { 603 if (logged_events_.size() == kTraceEventBufferSize) {
601 buffer_full_callback_copy = buffer_full_callback_; 604 buffer_full_callback_copy = buffer_full_callback_;
602 } 605 }
603 } // release lock 606 } // release lock
604 607
605 if (!buffer_full_callback_copy.is_null()) 608 if (!buffer_full_callback_copy.is_null())
606 buffer_full_callback_copy.Run(); 609 buffer_full_callback_copy.Run();
607 610
608 return ret_begin_id; 611 return ret_begin_id;
609 } 612 }
610 613
611 void TraceLog::AddTraceEventEtw(TraceEventPhase phase, 614 void TraceLog::AddTraceEventEtw(char phase,
612 const char* name, 615 const char* name,
613 const void* id, 616 const void* id,
614 const char* extra) { 617 const char* extra) {
615 #if defined(OS_WIN) 618 #if defined(OS_WIN)
616 TraceEventETWProvider::Trace(name, phase, id, extra); 619 TraceEventETWProvider::Trace(name, phase, id, extra);
617 #endif 620 #endif
618 INTERNAL_TRACE_EVENT_ADD(phase, 621 INTERNAL_TRACE_EVENT_ADD(phase, "ETW Trace Event", name,
619 "ETW Trace Event", name, "id", id, "extra", TRACE_STR_COPY(extra), 622 TRACE_EVENT_FLAG_COPY, "id", id, "extra", extra);
620 TRACE_EVENT_FLAG_COPY);
621 } 623 }
622 624
623 void TraceLog::AddTraceEventEtw(TraceEventPhase phase, 625 void TraceLog::AddTraceEventEtw(char phase,
624 const char* name, 626 const char* name,
625 const void* id, 627 const void* id,
626 const std::string& extra) 628 const std::string& extra)
627 { 629 {
628 #if defined(OS_WIN) 630 #if defined(OS_WIN)
629 TraceEventETWProvider::Trace(name, phase, id, extra); 631 TraceEventETWProvider::Trace(name, phase, id, extra);
630 #endif 632 #endif
631 INTERNAL_TRACE_EVENT_ADD(phase, 633 INTERNAL_TRACE_EVENT_ADD(phase, "ETW Trace Event", name,
632 "ETW Trace Event", name, "id", id, "extra", extra, 634 TRACE_EVENT_FLAG_COPY, "id", id, "extra", extra);
633 TRACE_EVENT_FLAG_COPY);
634 } 635 }
635 636
636 int TraceLog::AddCounterEvent(const TraceCategory* category, 637 void TraceLog::AddCounterEvent(const volatile bool* category_enabled,
637 const char* name, 638 const char* name,
638 TraceID id, 639 uint64 id,
639 const char* value1_name, int32 value1_val, 640 const char* value1_name, int32 value1_val,
640 const char* value2_name, int32 value2_val, 641 const char* value2_name, int32 value2_val,
641 TraceEventFlags flags) { 642 uint8 flags) {
642 return AddTraceEvent(TRACE_EVENT_PHASE_COUNTER, 643 int num_args = value2_name ? 2 : 1;
643 category, 644 const char* arg_names[2] = {value1_name, value2_name};
644 name, 645 uint8 arg_types[2];
645 id, 646 uint64 arg_values[2];
646 value1_name, value1_val, 647 trace_event_internal::SetTraceValue(value1_val, &arg_types[0],
647 value2_name, value2_val, 648 &arg_values[0]);
648 -1, 0, 649 trace_event_internal::SetTraceValue(value2_val, &arg_types[1],
649 flags); 650 &arg_values[1]);
651 AddTraceEvent(TRACE_EVENT_PHASE_COUNTER,
652 category_enabled,
653 name,
654 id,
655 num_args,
656 arg_names,
657 arg_types,
658 arg_values,
659 trace_event_internal::kNoThreshholdBeginId,
660 trace_event_internal::kNoThresholdValue,
661 flags);
650 } 662 }
651 663
652 void TraceLog::AddClockSyncMetadataEvents() { 664 void TraceLog::AddClockSyncMetadataEvents() {
653 #if defined(OS_ANDROID) 665 #if defined(OS_ANDROID)
654 // Since Android does not support sched_setaffinity, we cannot establish clock 666 // Since Android does not support sched_setaffinity, we cannot establish clock
655 // sync unless the scheduler clock is set to global. If the trace_clock file 667 // sync unless the scheduler clock is set to global. If the trace_clock file
656 // can't be read, we will assume the kernel doesn't support tracing and do 668 // can't be read, we will assume the kernel doesn't support tracing and do
657 // nothing. 669 // nothing.
658 std::string clock_mode; 670 std::string clock_mode;
659 if (!file_util::ReadFileToString( 671 if (!file_util::ReadFileToString(
(...skipping 26 matching lines...) Expand all
686 return; 698 return;
687 } 699 }
688 #endif 700 #endif
689 } 701 }
690 702
691 void TraceLog::AddThreadNameMetadataEvents() { 703 void TraceLog::AddThreadNameMetadataEvents() {
692 lock_.AssertAcquired(); 704 lock_.AssertAcquired();
693 for(base::hash_map<int, std::string>::iterator it = thread_names_.begin(); 705 for(base::hash_map<int, std::string>::iterator it = thread_names_.begin();
694 it != thread_names_.end(); 706 it != thread_names_.end();
695 it++) { 707 it++) {
696 if (!it->second.empty()) 708 if (!it->second.empty()) {
709 int num_args = 1;
710 const char* arg_name = "name";
711 uint8 arg_type;
712 uint64 arg_value;
713 trace_event_internal::SetTraceValue(it->second, &arg_type, &arg_value);
697 logged_events_.push_back( 714 logged_events_.push_back(
698 TraceEvent(it->first, 715 TraceEvent(it->first,
699 TimeTicks(), TRACE_EVENT_PHASE_METADATA, 716 TimeTicks(), TRACE_EVENT_PHASE_METADATA,
700 g_category_metadata, "thread_name", 0, 717 &g_category_enabled[g_category_metadata],
701 "name", it->second, 718 "thread_name", trace_event_internal::kNoEventId,
702 NULL, 0, 719 num_args, &arg_name, &arg_type, &arg_value,
703 TRACE_EVENT_FLAG_NONE)); 720 TRACE_EVENT_FLAG_NONE));
721 }
704 } 722 }
705 } 723 }
706 724
707 void TraceLog::DeleteForTesting() { 725 void TraceLog::DeleteForTesting() {
708 DeleteTraceLogForTesting::Delete(); 726 DeleteTraceLogForTesting::Delete();
709 } 727 }
710 728
711 void TraceLog::Resurrect() { 729 void TraceLog::Resurrect() {
712 StaticMemorySingletonTraits<TraceLog>::Resurrect(); 730 StaticMemorySingletonTraits<TraceLog>::Resurrect();
713 } 731 }
714 732
715 void TraceLog::SetProcessID(int process_id) { 733 void TraceLog::SetProcessID(int process_id) {
716 process_id_ = process_id; 734 process_id_ = process_id;
717 // Create a FNV hash from the process ID for XORing. 735 // Create a FNV hash from the process ID for XORing.
718 // See http://isthe.com/chongo/tech/comp/fnv/ for algorithm details. 736 // See http://isthe.com/chongo/tech/comp/fnv/ for algorithm details.
719 uint64 offset_basis = 14695981039346656037ull; 737 uint64 offset_basis = 14695981039346656037ull;
720 uint64 fnv_prime = 1099511628211ull; 738 uint64 fnv_prime = 1099511628211ull;
721 unsigned long long pid = static_cast<unsigned long long>(process_id_); 739 unsigned long long pid = static_cast<unsigned long long>(process_id_);
722 process_id_hash_ = (offset_basis ^ pid) * fnv_prime; 740 process_id_hash_ = (offset_basis ^ pid) * fnv_prime;
723 } 741 }
724 742
725 namespace internal { 743 } // namespace debug
744 } // namespace base
726 745
727 void TraceEndOnScopeClose::Initialize(const TraceCategory* category, 746 namespace trace_event_internal {
747
748 void TraceEndOnScopeClose::Initialize(const volatile bool* category_enabled,
728 const char* name) { 749 const char* name) {
729 data_.category = category; 750 data_.category_enabled = category_enabled;
730 data_.name = name; 751 data_.name = name;
731 p_data_ = &data_; 752 p_data_ = &data_;
732 } 753 }
733 754
734 void TraceEndOnScopeClose::AddEventIfEnabled() { 755 void TraceEndOnScopeClose::AddEventIfEnabled() {
735 // Only called when p_data_ is non-null. 756 // Only called when p_data_ is non-null.
736 if (p_data_->category->enabled) { 757 if (*p_data_->category_enabled) {
737 base::debug::TraceLog::GetInstance()->AddTraceEvent( 758 TRACE_EVENT_API_ADD_TRACE_EVENT(
738 TRACE_EVENT_PHASE_END, 759 TRACE_EVENT_PHASE_END,
739 p_data_->category, 760 p_data_->category_enabled,
740 p_data_->name, kNoEventId, 761 p_data_->name, kNoEventId,
741 kNoArgName, kNoArgValue, kNoArgName, kNoArgValue, 762 kZeroNumArgs, NULL, NULL, NULL,
742 kNoThreshholdBeginId, kNoThresholdValue, TRACE_EVENT_FLAG_NONE); 763 kNoThreshholdBeginId, kNoThresholdValue, TRACE_EVENT_FLAG_NONE);
743 } 764 }
744 } 765 }
745 766
746 void TraceEndOnScopeCloseThreshold::Initialize(const TraceCategory* category, 767 void TraceEndOnScopeCloseThreshold::Initialize(
747 const char* name, 768 const volatile bool* category_enabled,
748 int threshold_begin_id, 769 const char* name,
749 int64 threshold) { 770 int threshold_begin_id,
750 data_.category = category; 771 int64 threshold) {
772 data_.category_enabled = category_enabled;
751 data_.name = name; 773 data_.name = name;
752 data_.threshold_begin_id = threshold_begin_id; 774 data_.threshold_begin_id = threshold_begin_id;
753 data_.threshold = threshold; 775 data_.threshold = threshold;
754 p_data_ = &data_; 776 p_data_ = &data_;
755 } 777 }
756 778
757 void TraceEndOnScopeCloseThreshold::AddEventIfEnabled() { 779 void TraceEndOnScopeCloseThreshold::AddEventIfEnabled() {
758 // Only called when p_data_ is non-null. 780 // Only called when p_data_ is non-null.
759 if (p_data_->category->enabled) { 781 if (*p_data_->category_enabled) {
760 base::debug::TraceLog::GetInstance()->AddTraceEvent( 782 TRACE_EVENT_API_ADD_TRACE_EVENT(
761 TRACE_EVENT_PHASE_END, 783 TRACE_EVENT_PHASE_END,
762 p_data_->category, 784 p_data_->category_enabled,
763 p_data_->name, kNoEventId, 785 p_data_->name, kNoEventId,
764 kNoArgName, kNoArgValue, kNoArgName, kNoArgValue, 786 kZeroNumArgs, NULL, NULL, NULL,
765 p_data_->threshold_begin_id, p_data_->threshold, 787 p_data_->threshold_begin_id, p_data_->threshold,
766 TRACE_EVENT_FLAG_NONE); 788 TRACE_EVENT_FLAG_NONE);
767 } 789 }
768 } 790 }
769 791
770 } // namespace internal 792 } // namespace trace_event_internal
771
772 } // namespace debug
773 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698