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