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

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

Powered by Google App Engine
This is Rietveld 408576698