Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 // Trace events to track application performance. Events consist of a name | 5 // Trace events are for tracking application performance. |
| 6 // a type (BEGIN, END or INSTANT), a tracking id and extra string data. | |
| 7 // In addition, the current process id, thread id, a timestamp down to the | |
| 8 // microsecond and a file and line number of the calling location. | |
| 9 // | 6 // |
| 10 // The current implementation logs these events into a log file of the form | 7 // Events are issued against categories. Whereas LOG's |
| 11 // trace_<pid>.log where it's designed to be post-processed to generate a | 8 // categories are statically defined, TRACE categories are created |
| 12 // trace report. In the future, it may use another mechansim to facilitate | 9 // implicitly with a string. For example: |
| 13 // real-time analysis. | 10 // TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent") |
| 11 // | |
| 12 // Events can be INSTANT, or can be pairs of BEGIN and END: | |
| 13 // TRACE_EVENT_BEGIN0("MY_SUBSYSTEM", "SomethingCostly") | |
| 14 // doSomethingCostly() | |
| 15 // TRACE_EVENT_END0("MY_SUBSYSTEM", "SomethingCostly") | |
| 16 // | |
| 17 // A common use case is to trace entire function scopes. This | |
| 18 // issues a trace BEGIN and END automatically: | |
| 19 // void doSomethingCostly() { | |
| 20 // TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly"); | |
| 21 // ... | |
| 22 // } | |
| 23 // | |
| 24 // Additional parameters can be associated with an event: | |
| 25 // void doSomethingCostly2(int howMuch) { | |
| 26 // TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly", | |
| 27 // "howMuch", StringPrintf("%i", howMuch).c_str()); | |
| 28 // ... | |
| 29 // } | |
| 30 // | |
| 31 // The trace system will automatically add to this information the | |
| 32 // current process id, thread id, a timestamp down to the | |
| 33 // microsecond, as well as the file and line number of the calling location. | |
| 34 // | |
| 35 // By default, trace collection is compiled in, but turned off at runtime. | |
| 36 // Collecting trace data is the responsibility of the embedding | |
| 37 // application. In Chrome's case, navigating to about:gpu will turn on | |
| 38 // tracing and display data collected across all active processes. | |
| 39 // | |
| 40 // On Windows, the TRACE_EVENT output to ETW. | |
|
Sigurður Ásgeirsson
2011/05/02 19:28:41
nit: abortive comment?
scheib
2011/05/04 02:14:15
Done.
| |
| 14 | 41 |
| 15 #ifndef BASE_DEBUG_TRACE_EVENT_H_ | 42 #ifndef BASE_DEBUG_TRACE_EVENT_H_ |
| 16 #define BASE_DEBUG_TRACE_EVENT_H_ | 43 #define BASE_DEBUG_TRACE_EVENT_H_ |
| 17 #pragma once | 44 #pragma once |
| 18 | 45 |
| 19 #include "build/build_config.h" | 46 #include "build/build_config.h" |
| 20 | 47 |
| 21 #if defined(OS_WIN) | |
| 22 // On Windows we always pull in an alternative implementation | |
| 23 // which logs to Event Tracing for Windows. | |
| 24 // | |
| 25 // Note that the Windows implementation is always enabled, irrespective the | |
| 26 // value of the CHROMIUM_ENABLE_TRACE_EVENT define. The Windows implementation | |
| 27 // is controlled by Event Tracing for Windows, which will turn tracing on only | |
| 28 // if there is someone listening for the events it generates. | |
| 29 #include "base/debug/trace_event_win.h" | |
| 30 #else // defined(OS_WIN) | |
| 31 | |
| 32 #include <string> | 48 #include <string> |
| 33 | 49 |
| 34 #include "base/memory/scoped_ptr.h" | 50 #include "base/memory/scoped_ptr.h" |
| 51 #include "base/atomicops.h" | |
| 52 #include "base/callback.h" | |
| 53 #include "base/memory/scoped_ptr.h" | |
| 54 #include "base/memory/scoped_vector.h" | |
| 35 #include "base/memory/singleton.h" | 55 #include "base/memory/singleton.h" |
| 36 #include "base/synchronization/lock.h" | |
| 37 #include "base/time.h" | 56 #include "base/time.h" |
| 38 #include "base/timer.h" | 57 #include "base/timer.h" |
| 39 | 58 #include "base/callback.h" |
| 40 #ifndef CHROMIUM_ENABLE_TRACE_EVENT | 59 #include "base/string_util.h" |
| 41 #define TRACE_EVENT_BEGIN(name, id, extra) ((void) 0) | 60 #include <vector> |
| 42 #define TRACE_EVENT_END(name, id, extra) ((void) 0) | 61 |
| 43 #define TRACE_EVENT_INSTANT(name, id, extra) ((void) 0) | 62 // Older style trace macros with explicit id and extra data |
| 44 | 63 // Only these macros result in publishing data to ETW as currently implemented. |
| 45 #else // CHROMIUM_ENABLE_TRACE_EVENT | 64 #define TRACE_EVENT_BEGIN_ETW(name, id, extra) \ |
| 46 // Use the following macros rather than using the TraceLog class directly as the | 65 base::debug::TraceLog::AddTraceEventEtw( \ |
| 47 // underlying implementation may change in the future. Here's a sample usage: | 66 base::debug::TRACE_EVENT_PHASE_BEGIN, \ |
| 48 // TRACE_EVENT_BEGIN("v8.run", documentId, scriptLocation); | 67 __FILE__, __LINE__, name, reinterpret_cast<const void*>(id), extra); |
| 49 // RunScript(script); | 68 |
| 50 // TRACE_EVENT_END("v8.run", documentId, scriptLocation); | 69 #define TRACE_EVENT_END_ETW(name, id, extra) \ |
| 51 | 70 base::debug::TraceLog::AddTraceEventEtw( \ |
| 52 // Record that an event (of name, id) has begun. All BEGIN events should have | 71 base::debug::TRACE_EVENT_PHASE_END, \ |
| 53 // corresponding END events with a matching (name, id). | 72 __FILE__, __LINE__, name, reinterpret_cast<const void*>(id), extra); |
| 54 #define TRACE_EVENT_BEGIN(name, id, extra) \ | 73 |
| 55 base::debug::TraceLog::GetInstance()->Trace( \ | 74 #define TRACE_EVENT_INSTANT_ETW(name, id, extra) \ |
| 56 name, \ | 75 base::debug::TraceLog::AddTraceEventEtw( \ |
| 57 base::debug::TraceLog::EVENT_BEGIN, \ | 76 base::debug::TRACE_EVENT_PHASE_INSTANT, \ |
| 58 reinterpret_cast<const void*>(id), \ | 77 __FILE__, __LINE__, name, reinterpret_cast<const void*>(id), extra); |
| 59 extra, \ | 78 |
| 60 __FILE__, \ | 79 |
| 61 __LINE__) | 80 // Implementation detail: trace event macros create temporary variables |
| 62 | 81 // to keep instrumentation overhead low. These macros give each temporary |
| 63 // Record that an event (of name, id) has ended. All END events should have | 82 // variable a unique name based on the line number to prevent name collissions. |
| 64 // corresponding BEGIN events with a matching (name, id). | 83 #define TRACE_EVENT_UNIQUE_IDENTIFIER3(a,b) a##b |
| 65 #define TRACE_EVENT_END(name, id, extra) \ | 84 #define TRACE_EVENT_UNIQUE_IDENTIFIER2(a,b) \ |
| 66 base::debug::TraceLog::GetInstance()->Trace( \ | 85 TRACE_EVENT_UNIQUE_IDENTIFIER3(a,b) |
| 67 name, \ | 86 #define TRACE_EVENT_UNIQUE_IDENTIFIER(name_prefix) \ |
| 68 base::debug::TraceLog::EVENT_END, \ | 87 TRACE_EVENT_UNIQUE_IDENTIFIER2(name_prefix, __LINE__) |
| 69 reinterpret_cast<const void*>(id), \ | 88 |
| 70 extra, \ | 89 // Records a pair of begin and end events called "name" for the current |
| 71 __FILE__, \ | 90 // scope, with 0, 1 or 2 associated arguments. If the category is not |
| 72 __LINE__) | 91 // enabled, then this does nothing. |
| 73 | 92 #define TRACE_EVENT0(category, name) \ |
| 74 // Record that an event (of name, id) with no duration has happened. | 93 TRACE_EVENT1(category, name, NULL, 0) |
| 75 #define TRACE_EVENT_INSTANT(name, id, extra) \ | 94 #define TRACE_EVENT1(category, name, arg1name, arg1val) \ |
| 76 base::debug::TraceLog::GetInstance()->Trace( \ | 95 TRACE_EVENT2(category, name, arg1name, arg1val, NULL, 0) |
| 77 name, \ | 96 #define TRACE_EVENT2(category, name, arg1name, arg1val, arg2name, arg2val) \ |
|
Sigurður Ásgeirsson
2011/05/02 19:28:41
the name arguments here are expected to have infin
scheib
2011/05/04 02:14:15
Done.
| |
| 78 base::debug::TraceLog::EVENT_INSTANT, \ | 97 static base::debug::TraceCategory* \ |
| 79 reinterpret_cast<const void*>(id), \ | 98 TRACE_EVENT_UNIQUE_IDENTIFIER(catstatic) = \ |
| 80 extra, \ | 99 base::debug::TraceLog::GetCategory(category); \ |
| 81 __FILE__, \ | 100 if (TRACE_EVENT_UNIQUE_IDENTIFIER(catstatic)->enabled_) { \ |
| 82 __LINE__) | 101 base::debug::TraceLog::GetInstance()->AddTraceEvent( \ |
| 83 #endif // CHROMIUM_ENABLE_TRACE_EVENT | 102 base::debug::TRACE_EVENT_PHASE_BEGIN, \ |
| 103 __FILE__, __LINE__, \ | |
| 104 TRACE_EVENT_UNIQUE_IDENTIFIER(catstatic), \ | |
| 105 name, \ | |
| 106 arg1name, arg1val, \ | |
| 107 arg2name, arg2val); \ | |
| 108 } \ | |
| 109 base::debug::internal::TraceEndOnScopeClose \ | |
| 110 TRACE_EVENT_UNIQUE_IDENTIFIER(profileScope) ( \ | |
| 111 __FILE__, __LINE__, \ | |
| 112 TRACE_EVENT_UNIQUE_IDENTIFIER(catstatic), name); | |
| 113 | |
| 114 // Records a single event called "name" immediately, with 0, 1 or 2 | |
| 115 // associated arguments. If the category is not enabled, then this | |
| 116 // does nothing. | |
| 117 #define TRACE_EVENT_INSTANT0(category, name) \ | |
| 118 TRACE_EVENT_INSTANT1(category, name, NULL, 0) | |
| 119 #define TRACE_EVENT_INSTANT1(category, name, arg1name, arg1val) \ | |
| 120 TRACE_EVENT_INSTANT2(category, name, arg1name, arg1val, NULL, 0) | |
| 121 #define TRACE_EVENT_INSTANT2(category, name, arg1name, arg1val, \ | |
| 122 arg2name, arg2val) \ | |
| 123 static base::debug::TraceCategory* \ | |
| 124 TRACE_EVENT_UNIQUE_IDENTIFIER(catstatic) = \ | |
| 125 base::debug::TraceLog::GetCategory(category); \ | |
| 126 if (TRACE_EVENT_UNIQUE_IDENTIFIER(catstatic)->enabled_) { \ | |
| 127 base::debug::TraceLog::GetInstance()->AddTraceEvent( \ | |
| 128 base::debug::TRACE_EVENT_PHASE_INSTANT, \ | |
| 129 __FILE__, __LINE__, \ | |
| 130 TRACE_EVENT_UNIQUE_IDENTIFIER(catstatic), \ | |
| 131 name, \ | |
| 132 arg1name, arg1val, \ | |
| 133 arg2name, arg2val); \ | |
| 134 } | |
| 135 | |
| 136 // Records a single BEGIN event called "name" immediately, with 0, 1 or 2 | |
| 137 // associated arguments. If the category is not enabled, then this | |
| 138 // does nothing. | |
| 139 #define TRACE_EVENT_BEGIN0(category, name) \ | |
| 140 TRACE_EVENT_BEGIN1(category, name, NULL, 0) | |
| 141 #define TRACE_EVENT_BEGIN1(category, name, arg1name, arg1val) \ | |
| 142 TRACE_EVENT_BEGIN2(category, name, arg1name, arg1val, NULL, 0) | |
| 143 #define TRACE_EVENT_BEGIN2(category, name, arg1name, arg1val, \ | |
| 144 arg2name, arg2val) \ | |
| 145 static base::debug::TraceCategory* \ | |
| 146 TRACE_EVENT_UNIQUE_IDENTIFIER(catstatic) = \ | |
| 147 base::debug::TraceLog::GetCategory(category); \ | |
| 148 if (TRACE_EVENT_UNIQUE_IDENTIFIER(catstatic)->enabled_) { \ | |
| 149 base::debug::TraceLog::GetInstance()->AddTraceEvent( \ | |
| 150 base::debug::TRACE_EVENT_PHASE_BEGIN, \ | |
| 151 __FILE__, __LINE__, \ | |
| 152 TRACE_EVENT_UNIQUE_IDENTIFIER(catstatic), \ | |
| 153 name, \ | |
| 154 arg1name, arg1val, \ | |
| 155 arg2name, arg2val); \ | |
| 156 } | |
| 157 | |
| 158 // Records a single END event for "name" immediately. If the category | |
| 159 // is not enabled, then this does nothing. | |
| 160 #define TRACE_EVENT_END0(category, name) \ | |
| 161 TRACE_EVENT_END1(category, name, NULL, 0) | |
| 162 #define TRACE_EVENT_END1(category, name, arg1name, arg1val) \ | |
| 163 TRACE_EVENT_END2(category, name, arg1name, arg1val, NULL, 0) | |
| 164 #define TRACE_EVENT_END2(category, name, arg1name, arg1val, \ | |
| 165 arg2name, arg2val) \ | |
| 166 static base::debug::TraceCategory* \ | |
| 167 TRACE_EVENT_UNIQUE_IDENTIFIER(catstatic) = \ | |
| 168 base::debug::TraceLog::GetCategory(category); \ | |
| 169 if (TRACE_EVENT_UNIQUE_IDENTIFIER(catstatic)->enabled_) { \ | |
| 170 base::debug::TraceLog::GetInstance()->AddTraceEvent( \ | |
| 171 base::debug::TRACE_EVENT_PHASE_END, \ | |
| 172 __FILE__, __LINE__, \ | |
| 173 TRACE_EVENT_UNIQUE_IDENTIFIER(catstatic), \ | |
| 174 name, \ | |
| 175 arg1name, arg1val, \ | |
| 176 arg2name, arg2val); \ | |
| 177 } | |
| 84 | 178 |
| 85 namespace base { | 179 namespace base { |
| 86 | 180 |
| 87 class ProcessMetrics; | |
| 88 | |
| 89 namespace debug { | 181 namespace debug { |
| 90 | 182 |
| 183 // Categories allow enabling/disabling of streams of trace events | |
| 184 class TraceCategory { | |
| 185 public: | |
| 186 TraceCategory(); | |
| 187 ~TraceCategory(); | |
| 188 | |
| 189 void set(const char* name, bool enabled) { | |
|
Sigurður Ásgeirsson
2011/05/02 19:28:41
more descriptive name here, probably needs to star
scheib
2011/05/04 02:14:15
Changed to POD
| |
| 190 name_ = name; | |
| 191 enabled_ = enabled; | |
| 192 } | |
| 193 | |
| 194 const char* name() const { return name_; } | |
| 195 | |
| 196 volatile bool enabled_; | |
|
Sigurður Ásgeirsson
2011/05/02 19:28:41
still ought to wrap this in an accessor, http://go
scheib
2011/05/04 02:14:15
Changed to POD
| |
| 197 protected: | |
| 198 const char* name_; | |
| 199 }; | |
| 200 | |
| 201 #define TRACE_MAX_NUM_ARGS 2 | |
| 202 | |
| 203 enum TraceEventPhase { | |
| 204 TRACE_EVENT_PHASE_BEGIN, | |
| 205 TRACE_EVENT_PHASE_END, | |
| 206 TRACE_EVENT_PHASE_INSTANT | |
| 207 }; | |
| 208 | |
| 209 // Simple union of values. This is much lighter weight than base::Value, which | |
| 210 // requires dynamic allocation and a vtable. To keep the trace runtime overhead | |
| 211 // low, we want constant size storage here. | |
| 212 class TraceValue { | |
| 213 public: | |
| 214 enum Type { | |
| 215 TRACE_TYPE_UNDEFINED, | |
| 216 TRACE_TYPE_BOOL, | |
| 217 TRACE_TYPE_UINT, | |
| 218 TRACE_TYPE_INT, | |
| 219 TRACE_TYPE_DOUBLE, | |
| 220 TRACE_TYPE_POINTER, | |
| 221 TRACE_TYPE_STRING | |
| 222 }; | |
| 223 | |
| 224 TraceValue() : type_(TRACE_TYPE_UNDEFINED) { | |
| 225 value_.as_uint = 0ull; | |
| 226 } | |
| 227 TraceValue(bool rhs) : type_(TRACE_TYPE_BOOL) { | |
| 228 value_.as_uint = 0ull; // zero all bits | |
|
Sigurður Ásgeirsson
2011/05/02 19:28:41
why single out a few cases for this nulling?
scheib
2011/05/04 02:14:15
This code simplified / cut, since it is not needed
| |
| 229 value_.as_bool = rhs; | |
| 230 } | |
| 231 TraceValue(uint64 rhs) : type_(TRACE_TYPE_UINT) { | |
| 232 value_.as_uint = rhs; | |
| 233 } | |
| 234 TraceValue(uint32 rhs) : type_(TRACE_TYPE_UINT) { | |
| 235 value_.as_uint = rhs; | |
| 236 } | |
| 237 TraceValue(uint16 rhs) : type_(TRACE_TYPE_UINT) { | |
| 238 value_.as_uint = rhs; | |
| 239 } | |
| 240 TraceValue(uint8 rhs) : type_(TRACE_TYPE_UINT) { | |
| 241 value_.as_uint = rhs; | |
| 242 } | |
| 243 TraceValue(int64 rhs) : type_(TRACE_TYPE_INT) { | |
| 244 value_.as_int = rhs; | |
| 245 } | |
| 246 TraceValue(int32 rhs) : type_(TRACE_TYPE_INT) { | |
| 247 value_.as_int = rhs; | |
| 248 } | |
| 249 TraceValue(int16 rhs) : type_(TRACE_TYPE_INT) { | |
| 250 value_.as_int = rhs; | |
| 251 } | |
| 252 TraceValue(int8 rhs) : type_(TRACE_TYPE_INT) { | |
| 253 value_.as_int = rhs; | |
| 254 } | |
| 255 TraceValue(double rhs) : type_(TRACE_TYPE_DOUBLE) { | |
| 256 value_.as_double = rhs; | |
| 257 } | |
| 258 TraceValue(const void* rhs) : type_(TRACE_TYPE_POINTER) { | |
| 259 value_.as_uint = 0ull; // zero all bits | |
| 260 value_.as_pointer = rhs; | |
| 261 } | |
| 262 TraceValue(const char* rhs) : type_(TRACE_TYPE_STRING) { | |
| 263 value_.as_uint = 0ull; // zero all bits | |
| 264 value_.as_string = base::strdup(rhs); | |
|
Sigurður Ásgeirsson
2011/05/02 19:28:41
Sorry, but no.
See comment at http://codesearch.go
scheib
2011/05/04 02:14:15
Done.
| |
| 265 } | |
| 266 TraceValue(const TraceValue& rhs) : type_(TRACE_TYPE_UNDEFINED) { | |
| 267 operator=(rhs); | |
| 268 } | |
| 269 ~TraceValue() { | |
| 270 Destroy(); | |
| 271 } | |
| 272 | |
| 273 TraceValue& operator=(const TraceValue& rhs); | |
| 274 bool operator==(const TraceValue& rhs) const; | |
| 275 bool operator!=(const TraceValue& rhs) const { | |
| 276 return !operator==(rhs); | |
| 277 } | |
| 278 | |
| 279 void Destroy(); | |
| 280 | |
| 281 void AppendAsJSON(std::string* out) const; | |
| 282 | |
| 283 Type type() const { | |
| 284 return type_; | |
| 285 } | |
| 286 uint64 as_uint() const { | |
| 287 return value_.as_uint; | |
| 288 } | |
| 289 bool as_bool() const { | |
| 290 return value_.as_bool; | |
| 291 } | |
| 292 int64 as_int() const { | |
| 293 return value_.as_int; | |
| 294 } | |
| 295 double as_double() const { | |
| 296 return value_.as_double; | |
| 297 } | |
| 298 const void* as_pointer() const { | |
| 299 return value_.as_pointer; | |
| 300 } | |
| 301 const char* as_string() const { | |
| 302 return value_.as_string; | |
| 303 } | |
| 304 | |
| 305 private: | |
| 306 union Value { | |
| 307 bool as_bool; | |
| 308 uint64 as_uint; | |
| 309 int64 as_int; | |
| 310 double as_double; | |
| 311 const void* as_pointer; | |
| 312 char* as_string; | |
| 313 }; | |
| 314 | |
| 315 Type type_; | |
| 316 Value value_; | |
| 317 }; | |
| 318 | |
| 319 // Output records are "Events" and can be obtained via the | |
| 320 // OutputCallback whenever the tracing system decides to flush. This | |
| 321 // can happen at any time, on any thread, or you can programatically | |
| 322 // force it to happen. | |
| 323 struct TraceEvent { | |
| 324 TraceEvent(); | |
| 325 ~TraceEvent(); | |
| 326 | |
| 327 // Serialize event data to JSON | |
| 328 static void AppendEventsAsJSON(const std::vector<TraceEvent>& events, | |
| 329 size_t start, | |
| 330 size_t count, | |
| 331 std::string* out); | |
| 332 void AppendAsJSON(std::string* out) const; | |
| 333 | |
| 334 | |
| 335 unsigned long process_id; | |
| 336 unsigned long thread_id; | |
| 337 TimeTicks timestamp; | |
| 338 TraceEventPhase phase; | |
| 339 TraceCategory* category; | |
| 340 const char* name; | |
| 341 const char* arg_names[TRACE_MAX_NUM_ARGS]; | |
| 342 TraceValue arg_values[TRACE_MAX_NUM_ARGS]; | |
| 343 }; | |
| 344 | |
| 345 | |
| 91 class TraceLog { | 346 class TraceLog { |
| 92 public: | 347 public: |
| 93 enum EventType { | |
| 94 EVENT_BEGIN, | |
| 95 EVENT_END, | |
| 96 EVENT_INSTANT | |
| 97 }; | |
| 98 | |
| 99 static TraceLog* GetInstance(); | 348 static TraceLog* GetInstance(); |
| 100 | 349 |
| 101 // Is tracing currently enabled. | 350 // Global enable of tracing. Currently enables all categories or not. |
| 102 static bool IsTracing(); | 351 // TODO(scheib): Replace with an Enable/DisableCategory() that |
| 103 // Start logging trace events. | 352 // implicitly controls the global logging state. |
| 104 static bool StartTracing(); | 353 void SetEnabled(bool enabled); |
| 105 // Stop logging trace events. | 354 bool IsEnabled() { return enabled_; } |
| 106 static void StopTracing(); | 355 |
| 107 | 356 float GetBufferPercentFull() const; |
| 108 // Log a trace event of (name, type, id) with the optional extra string. | 357 |
| 109 void Trace(const std::string& name, | 358 // When enough events are collected, they are handed (in bulk) to |
| 110 EventType type, | 359 // the output callback. If no callback is set, the output will be |
| 111 const void* id, | 360 // silently dropped. |
| 112 const std::wstring& extra, | 361 typedef Callback1<const std::string& /* json_events */>::Type OutputCallback; |
| 113 const char* file, | 362 void SetOutputCallback(OutputCallback* cb); // takes ownership of cb |
| 114 int line); | 363 |
| 115 void Trace(const std::string& name, | 364 // The trace buffer does not flush dynamically, so when it fills up, |
| 116 EventType type, | 365 // subsequent trace events will be dropped. This callback is generated when |
| 117 const void* id, | 366 // the trace buffer is full. |
| 118 const std::string& extra, | 367 typedef Callback0::Type BufferFullCallback; |
| 119 const char* file, | 368 void SetBufferFullCallback(BufferFullCallback* cb); |
| 120 int line); | 369 |
| 370 // Forwards data collected by a child process to the registered | |
| 371 // output callback. | |
| 372 void AddRemotelyCollectedData(const std::string& json_events); | |
| 373 | |
| 374 // Flushes all logged data to the callback. | |
| 375 void Flush(); | |
| 376 | |
| 377 // Called by TRACE_EVENT* macros, don't call this directly. | |
| 378 static TraceCategory* GetCategory(const char* name); | |
| 379 | |
| 380 // Called by TRACE_EVENT* macros, don't call this directly. | |
| 381 void AddTraceEvent(TraceEventPhase phase, | |
| 382 const char* file, int line, | |
| 383 TraceCategory* category, | |
| 384 const char* name, | |
| 385 const char* arg1_name, TraceValue arg1_val, | |
| 386 const char* arg2_name, TraceValue arg2_val); | |
| 387 static void AddTraceEventEtw(TraceEventPhase phase, | |
| 388 const char* file, int line, | |
| 389 const char* name, | |
| 390 const void* id, | |
| 391 const char* extra); | |
| 392 static void AddTraceEventEtw(TraceEventPhase phase, | |
| 393 const char* file, int line, | |
| 394 const char* name, | |
| 395 const void* id, | |
| 396 const std::string& extra) { | |
| 397 AddTraceEventEtw(phase, file, line, name, id, extra.c_str()); | |
| 398 } | |
| 399 | |
| 400 // Exposed for unittesting only, allows resurrecting our | |
| 401 // singleton instance post-AtExit processing. | |
| 402 static void Resurrect(); | |
| 121 | 403 |
| 122 private: | 404 private: |
| 123 // This allows constructor and destructor to be private and usable only | 405 // This allows constructor and destructor to be private and usable only |
| 124 // by the Singleton class. | 406 // by the Singleton class. |
| 125 friend struct DefaultSingletonTraits<TraceLog>; | 407 friend struct StaticMemorySingletonTraits<TraceLog>; |
| 126 | 408 |
| 127 TraceLog(); | 409 TraceLog(); |
| 128 ~TraceLog(); | 410 ~TraceLog(); |
| 129 bool OpenLogFile(); | 411 TraceCategory* GetCategoryInternal(const char* name); |
| 130 void CloseLogFile(); | 412 |
| 131 bool Start(); | 413 // TODO(nduca): switch to per-thread trace buffers to reduce thread |
| 132 void Stop(); | 414 // synchronization. |
| 133 void Heartbeat(); | 415 Lock lock_; |
| 134 void Log(const std::string& msg); | |
| 135 | |
| 136 bool enabled_; | 416 bool enabled_; |
| 137 FILE* log_file_; | 417 scoped_ptr<OutputCallback> output_callback_; |
| 138 base::Lock file_lock_; | 418 scoped_ptr<BufferFullCallback> buffer_full_callback_; |
| 139 TimeTicks trace_start_time_; | 419 std::vector<TraceEvent> logged_events_; |
| 140 scoped_ptr<base::ProcessMetrics> process_metrics_; | 420 |
| 141 RepeatingTimer<TraceLog> timer_; | 421 DISALLOW_COPY_AND_ASSIGN(TraceLog); |
| 142 }; | 422 }; |
| 423 | |
| 424 namespace internal { | |
| 425 | |
| 426 // Used by TRACE_EVENTx macro. Do not use directly. | |
| 427 class TraceEndOnScopeClose { | |
| 428 public: | |
| 429 TraceEndOnScopeClose(const char* file, int line, | |
| 430 TraceCategory* category, | |
| 431 const char* name) | |
| 432 : file_(file) | |
| 433 , line_(line) | |
| 434 , category_(category) | |
| 435 , name_(name) { } | |
| 436 | |
| 437 ~TraceEndOnScopeClose() { | |
| 438 if (category_->enabled_) | |
| 439 base::debug::TraceLog::GetInstance()->AddTraceEvent( | |
| 440 base::debug::TRACE_EVENT_PHASE_END, | |
| 441 file_, line_, | |
| 442 category_, | |
| 443 name_, | |
| 444 NULL, 0, NULL, 0); | |
| 445 } | |
| 446 | |
| 447 private: | |
| 448 const char* file_; | |
| 449 int line_; | |
| 450 TraceCategory* category_; | |
| 451 const char* name_; | |
| 452 }; | |
| 453 | |
| 454 } // namespace internal | |
| 143 | 455 |
| 144 } // namespace debug | 456 } // namespace debug |
| 145 } // namespace base | 457 } // namespace base |
| 146 | 458 |
| 147 #endif // defined(OS_WIN) | |
| 148 | |
| 149 #endif // BASE_DEBUG_TRACE_EVENT_H_ | 459 #endif // BASE_DEBUG_TRACE_EVENT_H_ |
| OLD | NEW |