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

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

Powered by Google App Engine
This is Rietveld 408576698