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

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

Issue 6551019: Trace_event upgrades (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: More gooder js thanks to arv. Created 9 years, 10 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 | « no previous file | base/debug/trace_event.cc » ('j') | base/debug/trace_event.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 automaticlaly add to this information the
Ken Russell (switch to Gerrit) 2011/02/25 00:56:36 typo: automaticlaly
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
rvargas (doing something else) 2011/02/25 23:38:33 Is this really going to be the case?.
nduca 2011/03/02 04:15:12 This is a bit of a typo. The real answer is that t
38 // tracing and display data collected across all active processes.
39 //
40 // On Windows, the TRACE_EVENT_*_LEGACY macros output to ETW.
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/scoped_ptr.h" 50 #include "base/scoped_ptr.h"
51 #include "base/scoped_vector.h"
52 #include "base/atomicops.h"
35 #include "base/singleton.h" 53 #include "base/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 <vector>
41 #define TRACE_EVENT_BEGIN(name, id, extra) ((void) 0) 58
42 #define TRACE_EVENT_END(name, id, extra) ((void) 0) 59 #define UNIQUE_IDENTIFIER3(a,b) a##b
brettw 2011/02/25 18:30:03 I don't think it's a good idea to leak these gener
43 #define TRACE_EVENT_INSTANT(name, id, extra) ((void) 0) 60 #define UNIQUE_IDENTIFIER2(a,b) UNIQUE_IDENTIFIER3(a,b) // __LINE__ eval forced
Ken Russell (switch to Gerrit) 2011/02/25 00:56:36 Is this forced evaluation of the __LINE__ macro gu
44 61 #define UNIQUE_IDENTIFIER(name_prefix) UNIQUE_IDENTIFIER2(name_prefix, __LINE__)
45 #else // CHROMIUM_ENABLE_TRACE_EVENT 62
46 // Use the following macros rather than using the TraceLog class directly as the 63 // Records a begin and end event called "name" for the beginning and
47 // underlying implementation may change in the future. Here's a sample usage: 64 // end of the current scope, with one associated argument. If the
Ken Russell (switch to Gerrit) 2011/02/25 00:56:36 "with one associated argument" -- is this accurate
48 // TRACE_EVENT_BEGIN("v8.run", documentId, scriptLocation); 65 // category is not enabled, then this does nothing.#
49 // RunScript(script); 66 #define TRACE_EVENT0(category, name) \
50 // TRACE_EVENT_END("v8.run", documentId, scriptLocation); 67 TRACE_EVENT1(category, name, NULL, NULL)
51 68 #define TRACE_EVENT1(category, name, arg1name, arg1val) \
52 // Record that an event (of name, id) has begun. All BEGIN events should have 69 TRACE_EVENT2(category, name, arg1name, arg1val, NULL, NULL)
53 // corresponding END events with a matching (name, id). 70 #define TRACE_EVENT2(category, name, arg1name, arg1val, arg2name, arg2val) \
54 #define TRACE_EVENT_BEGIN(name, id, extra) \ 71 static base::debug::TraceCategory* UNIQUE_IDENTIFIER(catstatic) = \
brettw 2011/02/25 18:30:03 Is this static really necessary? Can you just call
nduca 2011/03/02 04:15:12 I should probably have been more clear in the code
55 base::debug::TraceLog::GetInstance()->Trace( \ 72 base::debug::TraceLog::GetInstance()->GetCategory(category); \
56 name, \ 73 if (base::subtle::Acquire_Load(&(UNIQUE_IDENTIFIER(catstatic))->enabled_)) \
57 base::debug::TraceLog::EVENT_BEGIN, \ 74 base::debug::TraceLog::GetInstance()->AddTraceEvent( \
58 reinterpret_cast<const void*>(id), \ 75 base::debug::TRACE_EVENT_PHASE_BEGIN, \
brettw 2011/02/25 18:30:03 Indent wrapped lines 4 spaces. Same elsewhere.
59 extra, \ 76 __FILE__, __LINE__, \
60 __FILE__, \ 77 UNIQUE_IDENTIFIER(catstatic), \
61 __LINE__) 78 name, \
62 79 arg1name, arg1val, \
63 // Record that an event (of name, id) has ended. All END events should have 80 arg2name, arg2val); \
64 // corresponding BEGIN events with a matching (name, id). 81 base::debug::TraceEndOnScopeClose __profileScope ## __LINE (__FILE__, \
65 #define TRACE_EVENT_END(name, id, extra) \ 82 __LINE__, UNIQUE_IDENTIFIER(catstatic), name);
66 base::debug::TraceLog::GetInstance()->Trace( \ 83
67 name, \ 84 // Records a single event called "name" immediately, with one
68 base::debug::TraceLog::EVENT_END, \ 85 // associated argument. If the category is not enabled, then this
Ken Russell (switch to Gerrit) 2011/02/25 00:56:36 Same question here.
69 reinterpret_cast<const void*>(id), \ 86 // does nothing.
70 extra, \ 87 #define TRACE_EVENT_INSTANT0(category, name) \
71 __FILE__, \ 88 TRACE_EVENT_INSTANT1(category, name, NULL, NULL)
72 __LINE__) 89 #define TRACE_EVENT_INSTANT1(category, name, arg1name, arg1val) \
73 90 TRACE_EVENT_INSTANT2(category, name, arg1name, arg1val, NULL, NULL)
74 // Record that an event (of name, id) with no duration has happened. 91 #define TRACE_EVENT_INSTANT2(category, name, arg1name, arg1val, \
75 #define TRACE_EVENT_INSTANT(name, id, extra) \ 92 arg2name, arg2val) \
76 base::debug::TraceLog::GetInstance()->Trace( \ 93 static base::debug::TraceCategory* UNIQUE_IDENTIFIER(catstatic) = \
77 name, \ 94 base::debug::TraceLog::GetInstance()->GetCategory(category); \
78 base::debug::TraceLog::EVENT_INSTANT, \ 95 if (base::subtle::Acquire_Load(&(UNIQUE_IDENTIFIER(catstatic))->enabled_)) \
79 reinterpret_cast<const void*>(id), \ 96 base::debug::TraceLog::GetInstance()->AddTraceEvent( \
80 extra, \ 97 base::debug::TRACE_EVENT_PHASE_INSTANT, \
81 __FILE__, \ 98 __FILE__, __LINE__, \
82 __LINE__) 99 UNIQUE_IDENTIFIER(catstatic), \
83 #endif // CHROMIUM_ENABLE_TRACE_EVENT 100 name, \
101 arg1name, arg1val, \
102 arg2name, arg2val); \
103
104
105 // Use these when you want to issue BEGIN and ENDs across ordinary
106 // scope boundaries.
107 #define TRACE_EVENT_BEGIN0(category, name) \
108 TRACE_EVENT_BEGIN1(category, name, NULL, NULL)
109 #define TRACE_EVENT_BEGIN1(category, name, arg1name, arg1val) \
110 TRACE_EVENT_BEGIN2(category, name, arg1name, arg1val, NULL, NULL)
111 #define TRACE_EVENT_BEGIN2(category, name, arg1name, arg1val, \
112 arg2name, arg2val) \
113 static base::debug::TraceCategory* UNIQUE_IDENTIFIER(catstatic) = \
114 base::debug::TraceLog::GetInstance()->GetCategory(category); \
115 if (base::subtle::Acquire_Load(&(UNIQUE_IDENTIFIER(catstatic))->enabled_)) \
116 base::debug::TraceLog::GetInstance()->AddTraceEvent( \
117 base::debug::TRACE_EVENT_PHASE_BEGIN, \
118 __FILE__, __LINE__, \
119 UNIQUE_IDENTIFIER(catstatic), \
120 name, \
121 arg1name, arg1val, \
122 arg2name, arg2val);
123
124 #define TRACE_EVENT_END(category, name) \
125 static base::debug::TraceCategory* UNIQUE_IDENTIFIER(catstatic) = \
126 base::debug::TraceLog::GetInstance()->GetCategory(category); \
127 if (base::subtle::Acquire_Load(&(UNIQUE_IDENTIFIER(catstatic))->enabled_)) \
brettw 2011/02/25 18:30:03 Multi-line conditions should use {}
128 base::debug::TraceLog::GetInstance()->AddTraceEvent( \
129 base::debug::TRACE_EVENT_PHASE_END, \
130 __FILE__, __LINE__, \
131 UNIQUE_IDENTIFIER(catstatic), \
132 name, \
133 arg1name, arg1val, \
134 arg2name, arg2val);
135
136
137 // LEGACY trace macro support
138 #define TRACE_EVENT_BEGIN_LEGACY(name, id, extra) \
139 base::debug::TraceLog::GetInstance()->AddTraceEventLegacy( \
140 base::debug::TRACE_EVENT_PHASE_BEGIN, \
141 __FILE__, __LINE__, name, reinterpret_cast<const void*>(id), extra);
142
143 #define TRACE_EVENT_END_LEGACY(name, id, extra) \
144 base::debug::TraceLog::GetInstance()->AddTraceEventLegacy( \
145 base::debug::TRACE_EVENT_PHASE_END, \
146 __FILE__, __LINE__, name, reinterpret_cast<const void*>(id), extra);
147
148 #define TRACE_EVENT_INSTANT_LEGACY(name, id, extra) \
149 base::debug::TraceLog::GetInstance()->AddTraceEventLegacy( \
150 base::debug::TRACE_EVENT_PHASE_INSTANT, \
151 __FILE__, __LINE__, name, reinterpret_cast<const void*>(id), extra);
84 152
85 namespace base { 153 namespace base {
86 154
87 class ProcessMetrics;
88
89 namespace debug { 155 namespace debug {
90 156
157 // Categories allow enabling/disabling of streams of trace events
158 // Don't manipulate the category object directly, as this may lead
159 // to threading issues. Use the TraceLog methods instead.
160 class TraceCategory {
161 public:
brettw 2011/02/25 18:30:03 Indent these one char.
162 TraceCategory(const char* name, bool enabled);
163 ~TraceCategory();
164
165 const char* name() const { return name_; }
166
167 // NEVER read these directly, let the macros do it for you
168 volatile base::subtle::Atomic32 enabled_;
169 protected:
170 const char* name_;
171 };
172
173 #define TRACE_MAX_NUM_ARGS 2
174
175 enum TraceEventPhase {
176 TRACE_EVENT_PHASE_BEGIN,
177 TRACE_EVENT_PHASE_END,
178 TRACE_EVENT_PHASE_INSTANT
179 };
180
181 // Output records are "Events" and can be obtained via the
182 // OutputCallback whenever the logging system decides to flush. This
183 // can happen at any time, on any thread, or you can programatically
184 // force it to happen.
185 struct TraceEvent {
186 static void AppendAsJSON(std::string& out,
Ken Russell (switch to Gerrit) 2011/02/25 00:56:36 The Google C++ style guide says that all reference
187 const std::vector<TraceEvent>& events);
188 void AppendAsJSON(std::string& out) const;
Ken Russell (switch to Gerrit) 2011/02/25 00:56:36 Same here.
189
190
191 unsigned long processId;
192 unsigned long threadId;
193 TimeTicks timestamp;
194 TraceEventPhase phase;
195 TraceCategory* category;
196 const char* name;
197 const char* argNames[TRACE_MAX_NUM_ARGS];
198 std::string argValues[TRACE_MAX_NUM_ARGS];
199 };
200
201
91 class TraceLog { 202 class TraceLog {
92 public: 203 public:
93 enum EventType {
94 EVENT_BEGIN,
95 EVENT_END,
96 EVENT_INSTANT
97 };
98 204
99 static TraceLog* GetInstance(); 205 static TraceLog* GetInstance();
100 206
101 // Is tracing currently enabled. 207 // Global enable of tracing. Currently enables all categories or not.
102 static bool IsTracing(); 208 // TODO(nduca) Replaced with an Enable/DisableCategory() that
103 // Start logging trace events. 209 // implicitly controls the global logging state.
104 static bool StartTracing(); 210 void SetEnabled(bool enabled);
105 // Stop logging trace events. 211
106 static void StopTracing(); 212 // When enough events are collected, they are handed (in bulk) to
107 213 // the output callback. If no callback is set, the output will be
108 // Log a trace event of (name, type, id) with the optional extra string. 214 // silently dropped.
109 void Trace(const std::string& name, 215 typedef Callback1<const std::string& /* json_events */>::Type OutputCallback;
110 EventType type, 216 void SetOutputCallback(OutputCallback* cb);
111 const void* id, 217
112 const std::wstring& extra, 218 // Forwards data collected by a child process to the registered
113 const char* file, 219 // output callback.
114 int line); 220 void AddRemotelyCollectedData(const std::string& json_events);
115 void Trace(const std::string& name, 221
116 EventType type, 222 // Flushes all logged data to the callback.
117 const void* id, 223 void Flush();
118 const std::string& extra, 224
119 const char* file, 225 // Called by TRACE_EVENT* macros, don't call this directly.
120 int line); 226 TraceCategory* GetCategory(const char* name);
227
228 // Called by TRACE_EVENT* macros, don't call this directly.
229 void AddTraceEvent(TraceEventPhase phase,
230 const char* file, int line,
231 TraceCategory* category,
232 const char* name,
233 const char* arg1name, const char* arg1val,
234 const char* arg2name, const char* arg2val);
235 void AddTraceEventLegacy(TraceEventPhase phase,
236 const char* file, int line,
237 const char* name,
238 const void* id,
239 const char* extra);
121 240
122 private: 241 private:
123 // This allows constructor and destructor to be private and usable only 242 // This allows constructor and destructor to be private and usable only
124 // by the Singleton class. 243 // by the Singleton class.
125 friend struct DefaultSingletonTraits<TraceLog>; 244 friend struct StaticMemorySingletonTraits<TraceLog>;
126 245
127 TraceLog(); 246 TraceLog();
128 ~TraceLog(); 247 ~TraceLog();
129 bool OpenLogFile(); 248 void FlushWithLockAlreadyHeld();
130 void CloseLogFile(); 249
131 bool Start(); 250 // Guards access to everything right now. If I can get this working,
132 void Stop(); 251 // there are a ton of things we can to reduce thread synchronization.
Ken Russell (switch to Gerrit) 2011/02/25 00:56:36 Perhaps a TODO(nduca): here then?
133 void Heartbeat(); 252 Lock lock_;
134 void Log(const std::string& msg);
135
136 bool enabled_; 253 bool enabled_;
137 FILE* log_file_; 254 ScopedVector<TraceCategory> categories_;
138 base::Lock file_lock_; 255 scoped_ptr<OutputCallback> output_callback_;
139 TimeTicks trace_start_time_; 256 std::vector<TraceEvent> logged_events_;
140 scoped_ptr<base::ProcessMetrics> process_metrics_; 257
141 RepeatingTimer<TraceLog> timer_; 258 DISALLOW_COPY_AND_ASSIGN(TraceLog);
259 };
260
261
262 class TraceEndOnScopeClose {
Ken Russell (switch to Gerrit) 2011/02/25 00:56:36 This class isn't supposed to be accessed externall
263 public:
brettw 2011/02/25 18:30:03 Indent these one char.
264 TraceEndOnScopeClose(const char* file, int line,
265 TraceCategory* category,
brettw 2011/02/25 18:30:03 Params should be aligned (should be under the cons
266 const char* name)
267 : file_(file),
brettw 2011/02/25 18:30:03 : should only be indented 4 spaces (4 fewer than n
268 line_(line),
269 category_(category),
270 name_(name) {
271 }
272 ~TraceEndOnScopeClose() {
273 if (base::subtle::Acquire_Load(&category_->enabled_))
274 base::debug::TraceLog::GetInstance()->AddTraceEvent(
275 base::debug::TRACE_EVENT_PHASE_END,
276 file_, line_,
277 category_,
278 name_,
279 NULL, NULL, NULL, NULL);
280 }
281 protected:
Ken Russell (switch to Gerrit) 2011/02/25 00:56:36 Why are these protected and not private?
282 const char* file_;
283 int line_;
284 TraceCategory* category_;
285 const char* name_;
142 }; 286 };
143 287
144 } // namespace debug 288 } // namespace debug
145 } // namespace base 289 } // namespace base
146 290
147 #endif // defined(OS_WIN)
148
149 #endif // BASE_DEBUG_TRACE_EVENT_H_ 291 #endif // BASE_DEBUG_TRACE_EVENT_H_
OLDNEW
« no previous file with comments | « no previous file | base/debug/trace_event.cc » ('j') | base/debug/trace_event.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698