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

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

Issue 6862002: Merge gpu_trace_event back into base/debug/trace_event (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: merge to r83717 Created 9 years, 7 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 // 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_
OLDNEW
« no previous file with comments | « base/base.gypi ('k') | base/debug/trace_event.cc » ('j') | base/debug/trace_event.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698