1 // Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012
2 // Google Inc. All rights reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
14 // * Neither the name of Google Inc. nor the name Chromium Embedded
15 // Framework nor the names of its contributors may be used to endorse
16 // or promote products derived from this software without specific prior
17 // written permission.
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 // Trace events are for tracking application performance and resource usage.
33 // Macros are provided to track:
34 // Begin and end of function calls
37 // Events are issued against categories. Whereas LOG's categories are statically
38 // defined, TRACE categories are created implicitly with a string. For example:
39 // TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent")
41 // Events can be INSTANT, or can be pairs of BEGIN and END in the same scope:
42 // TRACE_EVENT_BEGIN0("MY_SUBSYSTEM", "SomethingCostly")
43 // doSomethingCostly()
44 // TRACE_EVENT_END0("MY_SUBSYSTEM", "SomethingCostly")
45 // Note: Our tools can't always determine the correct BEGIN/END pairs unless
46 // these are used in the same scope. Use ASYNC_BEGIN/ASYNC_END macros if you
47 // need them to be in separate scopes.
49 // A common use case is to trace entire function scopes. This issues a trace
50 // BEGIN and END automatically:
51 // void doSomethingCostly() {
52 // TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly");
56 // Additional parameters can be associated with an event:
57 // void doSomethingCostly2(int howMuch) {
58 // TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly",
59 // "howMuch", howMuch);
63 // The trace system will automatically add to this information the current
64 // process id, thread id, and a timestamp in microseconds.
66 // To trace an asynchronous procedure such as an IPC send/receive, use
67 // ASYNC_BEGIN and ASYNC_END:
68 // [single threaded sender code]
69 // static int send_count = 0;
71 // TRACE_EVENT_ASYNC_BEGIN0("ipc", "message", send_count);
72 // Send(new MyMessage(send_count));
74 // void OnMyMessage(send_count) {
75 // TRACE_EVENT_ASYNC_END0("ipc", "message", send_count);
77 // The third parameter is a unique ID to match ASYNC_BEGIN/ASYNC_END pairs.
78 // ASYNC_BEGIN and ASYNC_END can occur on any thread of any traced process.
79 // Pointers can be used for the ID parameter, and they will be mangled
80 // internally so that the same pointer on two different processes will not
81 // match. For example:
82 // class MyTracedClass {
85 // TRACE_EVENT_ASYNC_BEGIN0("category", "MyTracedClass", this);
88 // TRACE_EVENT_ASYNC_END0("category", "MyTracedClass", this);
92 // The trace event also supports counters, which is a way to track a quantity
93 // as it varies over time. Counters are created with the following macro:
94 // TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter", g_myCounterValue);
96 // Counters are process-specific. The macro itself can be issued from any
99 // Sometimes, you want to track two counters at once. You can do this with two
101 // TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter0", g_myCounterValue[0]);
102 // TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter1", g_myCounterValue[1]);
103 // Or you can do it with a combined macro:
104 // TRACE_COUNTER2("MY_SUBSYSTEM", "myCounter",
105 // "bytesPinned", g_myCounterValue[0],
106 // "bytesAllocated", g_myCounterValue[1]);
107 // This indicates to the tracing UI that these counters should be displayed
108 // in a single graph, as a summed area chart.
110 // Since counters are in a global namespace, you may want to disembiguate with a
111 // unique ID, by using the TRACE_COUNTER_ID* variations.
113 // By default, trace collection is compiled in, but turned off at runtime.
114 // Collecting trace data is the responsibility of the embedding application. In
115 // CEF's case, calling BeginTracing will turn on tracing on all active
119 // Memory scoping note:
120 // Tracing copies the pointers, not the string content, of the strings passed
121 // in for category, name, and arg_names. Thus, the following code will cause
123 // char* str = strdup("impprtantName");
124 // TRACE_EVENT_INSTANT0("SUBSYSTEM", str); // BAD!
125 // free(str); // Trace system now has dangling pointer
127 // To avoid this issue with the |name| and |arg_name| parameters, use the
128 // TRACE_EVENT_COPY_XXX overloads of the macros at additional runtime
130 // Notes: The category must always be in a long-lived char* (i.e. static const).
131 // The |arg_values|, when used, are always deep copied with the _COPY
136 // All macros are thread safe and can be used from any process.
139 #ifndef CEF_INCLUDE_BASE_CEF_TRACE_EVENT_H_
140 #define CEF_INCLUDE_BASE_CEF_TRACE_EVENT_H_
143 #if defined(TRACE_EVENT0)
144 // Do nothing if the macros provided by this header already exist.
145 // This can happen in cases where Chromium code is used directly by the
146 // client application. When using Chromium code directly always include
147 // the Chromium header first to avoid type conflicts.
148 #elif defined(BUILDING_CEF_SHARED)
149 // When building CEF include the Chromium header directly.
150 #include "base/debug/trace_event.h"
151 #else // !BUILDING_CEF_SHARED
152 // The following is substantially similar to the Chromium implementation.
153 // If the Chromium implementation diverges the below implementation should be
156 #include "include/internal/cef_trace_event_internal.h"
158 // Records a pair of begin and end events called "name" for the current
159 // scope, with 0, 1 or 2 associated arguments. If the category is not
160 // enabled, then this does nothing.
161 // - category and name strings must have application lifetime (statics or
162 // literals). They may not include " chars.
163 #define TRACE_EVENT0(category, name) \
164 cef_trace_event_begin(category, name, NULL, 0, NULL, 0, false); \
165 CEF_INTERNAL_TRACE_END_ON_SCOPE_CLOSE(category, name)
166 #define TRACE_EVENT1(category, name, arg1_name, arg1_val) \
167 cef_trace_event_begin(category, name, arg1_name, arg1_val, NULL, 0, false); \
168 CEF_INTERNAL_TRACE_END_ON_SCOPE_CLOSE(category, name)
169 #define TRACE_EVENT2(category, name, arg1_name, arg1_val, arg2_name, \
171 cef_trace_event_begin(category, name, arg1_name, arg1_val, \
172 arg2_name, arg2_val, false); \
173 CEF_INTERNAL_TRACE_END_ON_SCOPE_CLOSE(category, name)
175 // Implementation detail: trace event macros create temporary variable names.
176 // These macros give each temporary variable a unique name based on the line
177 // number to prevent name collisions.
178 #define CEF_INTERNAL_TRACE_EVENT_UID3(a,b) \
179 cef_trace_event_unique_##a##b
180 #define CEF_INTERNAL_TRACE_EVENT_UID2(a,b) \
181 CEF_INTERNAL_TRACE_EVENT_UID3(a,b)
182 #define CEF_INTERNAL_TRACE_EVENT_UID(name_prefix) \
183 CEF_INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__)
185 // Implementation detail: internal macro to end end event when the scope ends.
186 #define CEF_INTERNAL_TRACE_END_ON_SCOPE_CLOSE(category, name) \
187 cef_trace_event::CefTraceEndOnScopeClose \
188 CEF_INTERNAL_TRACE_EVENT_UID(profileScope)(category, name)
190 // Records a single event called "name" immediately, with 0, 1 or 2
191 // associated arguments. If the category is not enabled, then this
193 // - category and name strings must have application lifetime (statics or
194 // literals). They may not include " chars.
195 #define TRACE_EVENT_INSTANT0(category, name) \
196 cef_trace_event_instant(category, name, NULL, 0, NULL, 0, false)
197 #define TRACE_EVENT_INSTANT1(category, name, arg1_name, arg1_val) \
198 cef_trace_event_instant(category, name, arg1_name, arg1_val, NULL, 0, false)
199 #define TRACE_EVENT_INSTANT2(category, name, arg1_name, arg1_val, \
200 arg2_name, arg2_val) \
201 cef_trace_event_instant(category, name, arg1_name, arg1_val, arg2_name, \
203 #define TRACE_EVENT_COPY_INSTANT0(category, name) \
204 cef_trace_event_instant(category, name, NULL, 0, NULL, 0, true)
205 #define TRACE_EVENT_COPY_INSTANT1(category, name, arg1_name, arg1_val) \
206 cef_trace_event_instant(category, name, arg1_name, arg1_val, NULL, 0, true)
207 #define TRACE_EVENT_COPY_INSTANT2(category, name, arg1_name, arg1_val, \
208 arg2_name, arg2_val) \
209 cef_trace_event_instant(category, name, arg1_name, arg1_val, arg2_name, \
212 // Records a single BEGIN event called "name" immediately, with 0, 1 or 2
213 // associated arguments. If the category is not enabled, then this
215 // - category and name strings must have application lifetime (statics or
216 // literals). They may not include " chars.
217 #define TRACE_EVENT_BEGIN0(category, name) \
218 cef_trace_event_begin(category, name, NULL, 0, NULL, 0, false)
219 #define TRACE_EVENT_BEGIN1(category, name, arg1_name, arg1_val) \
220 cef_trace_event_begin(category, name, arg1_name, arg1_val, NULL, 0, false)
221 #define TRACE_EVENT_BEGIN2(category, name, arg1_name, arg1_val, \
222 arg2_name, arg2_val) \
223 cef_trace_event_begin(category, name, arg1_name, arg1_val, arg2_name, \
225 #define TRACE_EVENT_COPY_BEGIN0(category, name) \
226 cef_trace_event_begin(category, name, NULL, 0, NULL, 0, true)
227 #define TRACE_EVENT_COPY_BEGIN1(category, name, arg1_name, arg1_val) \
228 cef_trace_event_begin(category, name, arg1_name, arg1_val, NULL, 0, true)
229 #define TRACE_EVENT_COPY_BEGIN2(category, name, arg1_name, arg1_val, \
230 arg2_name, arg2_val) \
231 cef_trace_event_begin(category, name, arg1_name, arg1_val, arg2_name, \
234 // Records a single END event for "name" immediately. If the category
235 // is not enabled, then this does nothing.
236 // - category and name strings must have application lifetime (statics or
237 // literals). They may not include " chars.
238 #define TRACE_EVENT_END0(category, name) \
239 cef_trace_event_end(category, name, NULL, 0, NULL, 0, false)
240 #define TRACE_EVENT_END1(category, name, arg1_name, arg1_val) \
241 cef_trace_event_end(category, name, arg1_name, arg1_val, NULL, 0, false)
242 #define TRACE_EVENT_END2(category, name, arg1_name, arg1_val, \
243 arg2_name, arg2_val) \
244 cef_trace_event_end(category, name, arg1_name, arg1_val, arg2_name, \
246 #define TRACE_EVENT_COPY_END0(category, name) \
247 cef_trace_event_end(category, name, NULL, 0, NULL, 0, true)
248 #define TRACE_EVENT_COPY_END1(category, name, arg1_name, arg1_val) \
249 cef_trace_event_end(category, name, arg1_name, arg1_val, NULL, 0, true)
250 #define TRACE_EVENT_COPY_END2(category, name, arg1_name, arg1_val, \
251 arg2_name, arg2_val) \
252 cef_trace_event_end(category, name, arg1_name, arg1_val, arg2_name, \
255 // Records the value of a counter called "name" immediately. Value
256 // must be representable as a 32 bit integer.
257 // - category and name strings must have application lifetime (statics or
258 // literals). They may not include " chars.
259 #define TRACE_COUNTER1(category, name, value) \
260 cef_trace_counter(category, name, NULL, value, NULL, 0, false)
261 #define TRACE_COPY_COUNTER1(category, name, value) \
262 cef_trace_counter(category, name, NULL, value, NULL, 0, true)
264 // Records the values of a multi-parted counter called "name" immediately.
265 // The UI will treat value1 and value2 as parts of a whole, displaying their
266 // values as a stacked-bar chart.
267 // - category and name strings must have application lifetime (statics or
268 // literals). They may not include " chars.
269 #define TRACE_COUNTER2(category, name, value1_name, value1_val, \
270 value2_name, value2_val) \
271 cef_trace_counter(category, name, value1_name, value1_val, value2_name, \
273 #define TRACE_COPY_COUNTER2(category, name, value1_name, value1_val, \
274 value2_name, value2_val) \
275 cef_trace_counter(category, name, value1_name, value1_val, value2_name, \
278 // Records the value of a counter called "name" immediately. Value
279 // must be representable as a 32 bit integer.
280 // - category and name strings must have application lifetime (statics or
281 // literals). They may not include " chars.
282 // - |id| is used to disambiguate counters with the same name. It must either
283 // be a pointer or an integer value up to 64 bits. If it's a pointer, the
284 // bits will be xored with a hash of the process ID so that the same pointer
285 // on two different processes will not collide.
286 #define TRACE_COUNTER_ID1(category, name, id, value) \
287 cef_trace_counter_id(category, name, id, NULL, value, NULL, 0, false)
288 #define TRACE_COPY_COUNTER_ID1(category, name, id, value) \
289 cef_trace_counter_id(category, name, id, NULL, value, NULL, 0, true)
291 // Records the values of a multi-parted counter called "name" immediately.
292 // The UI will treat value1 and value2 as parts of a whole, displaying their
293 // values as a stacked-bar chart.
294 // - category and name strings must have application lifetime (statics or
295 // literals). They may not include " chars.
296 // - |id| is used to disambiguate counters with the same name. It must either
297 // be a pointer or an integer value up to 64 bits. If it's a pointer, the
298 // bits will be xored with a hash of the process ID so that the same pointer
299 // on two different processes will not collide.
300 #define TRACE_COUNTER_ID2(category, name, id, value1_name, value1_val, \
301 value2_name, value2_val) \
302 cef_trace_counter_id(category, name, id, value1_name, value1_val, \
303 value2_name, value2_val, false)
304 #define TRACE_COPY_COUNTER_ID2(category, name, id, value1_name, \
305 value1_val, value2_name, value2_val) \
306 cef_trace_counter_id(category, name, id, value1_name, value1_val, \
307 value2_name, value2_val, true)
310 // Records a single ASYNC_BEGIN event called "name" immediately, with 0, 1 or 2
311 // associated arguments. If the category is not enabled, then this
313 // - category and name strings must have application lifetime (statics or
314 // literals). They may not include " chars.
315 // - |id| is used to match the ASYNC_BEGIN event with the ASYNC_END event.
316 // ASYNC events are considered to match if their category, name and id values
317 // all match. |id| must either be a pointer or an integer value up to 64
318 // bits. If it's a pointer, the bits will be xored with a hash of the process
319 // ID sothat the same pointer on two different processes will not collide.
320 // An asynchronous operation can consist of multiple phases. The first phase is
321 // defined by the ASYNC_BEGIN calls. Additional phases can be defined using the
322 // ASYNC_STEP_BEGIN macros. When the operation completes, call ASYNC_END.
323 // An async operation can span threads and processes, but all events in that
324 // operation must use the same |name| and |id|. Each event can have its own
326 #define TRACE_EVENT_ASYNC_BEGIN0(category, name, id) \
327 cef_trace_event_async_begin(category, name, id, NULL, 0, NULL, 0, false)
328 #define TRACE_EVENT_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \
329 cef_trace_event_async_begin(category, name, id, arg1_name, arg1_val, NULL, \
331 #define TRACE_EVENT_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \
332 arg2_name, arg2_val) \
333 cef_trace_event_async_begin(category, name, id, arg1_name, arg1_val, \
334 arg2_name, arg2_val, false)
335 #define TRACE_EVENT_COPY_ASYNC_BEGIN0(category, name, id) \
336 cef_trace_event_async_begin(category, name, id, NULL, 0, NULL, 0, true)
337 #define TRACE_EVENT_COPY_ASYNC_BEGIN1(category, name, id, arg1_name, \
339 cef_trace_event_async_begin(category, name, id, arg1_name, arg1_val, NULL, \
341 #define TRACE_EVENT_COPY_ASYNC_BEGIN2(category, name, id, arg1_name, \
342 arg1_val, arg2_name, arg2_val) \
343 cef_trace_event_async_begin(category, name, id, arg1_name, arg1_val, \
344 arg2_name, arg2_val, true)
346 // Records a single ASYNC_STEP_INTO event for |step| immediately. If the
347 // category is not enabled, then this does nothing. The |name| and |id| must
348 // match the ASYNC_BEGIN event above. The |step| param identifies this step
349 // within the async event. This should be called at the beginning of the next
350 // phase of an asynchronous operation. The ASYNC_BEGIN event must not have any
351 // ASYNC_STEP_PAST events.
352 #define TRACE_EVENT_ASYNC_STEP_INTO0(category, name, id, step) \
353 cef_trace_event_async_step_into(category, name, id, step, NULL, 0, false)
354 #define TRACE_EVENT_ASYNC_STEP_INTO1(category, name, id, step, \
355 arg1_name, arg1_val) \
356 cef_trace_event_async_step_into(category, name, id, step, arg1_name, \
358 #define TRACE_EVENT_COPY_ASYNC_STEP_INTO0(category, name, id, step) \
359 cef_trace_event_async_step_into(category, name, id, step, NULL, 0, true)
360 #define TRACE_EVENT_COPY_ASYNC_STEP_INTO1(category, name, id, step, \
361 arg1_name, arg1_val) \
362 cef_trace_event_async_step_into(category, name, id, step, arg1_name, \
365 // Records a single ASYNC_STEP_PAST event for |step| immediately. If the
366 // category is not enabled, then this does nothing. The |name| and |id| must
367 // match the ASYNC_BEGIN event above. The |step| param identifies this step
368 // within the async event. This should be called at the beginning of the next
369 // phase of an asynchronous operation. The ASYNC_BEGIN event must not have any
370 // ASYNC_STEP_INTO events.
371 #define TRACE_EVENT_ASYNC_STEP_PAST0(category, name, id, step) \
372 cef_trace_event_async_step_past(category, name, id, step, NULL, 0, false)
373 #define TRACE_EVENT_ASYNC_STEP_PAST1(category, name, id, step, \
374 arg1_name, arg1_val) \
375 cef_trace_event_async_step_past(category, name, id, step, arg1_name, \
377 #define TRACE_EVENT_COPY_ASYNC_STEP_PAST0(category, name, id, step) \
378 cef_trace_event_async_step_past(category, name, id, step, NULL, 0, true)
379 #define TRACE_EVENT_COPY_ASYNC_STEP_PAST1(category, name, id, step, \
380 arg1_name, arg1_val) \
381 cef_trace_event_async_step_past(category, name, id, step, arg1_name, \
384 // Records a single ASYNC_END event for "name" immediately. If the category
385 // is not enabled, then this does nothing.
386 #define TRACE_EVENT_ASYNC_END0(category, name, id) \
387 cef_trace_event_async_end(category, name, id, NULL, 0, NULL, 0, false)
388 #define TRACE_EVENT_ASYNC_END1(category, name, id, arg1_name, arg1_val) \
389 cef_trace_event_async_end(category, name, id, arg1_name, arg1_val, NULL, 0, \
391 #define TRACE_EVENT_ASYNC_END2(category, name, id, arg1_name, arg1_val, \
392 arg2_name, arg2_val) \
393 cef_trace_event_async_end(category, name, id, arg1_name, arg1_val, \
394 arg2_name, arg2_val, false)
395 #define TRACE_EVENT_COPY_ASYNC_END0(category, name, id) \
396 cef_trace_event_async_end(category, name, id, NULL, 0, NULL, 0, true)
397 #define TRACE_EVENT_COPY_ASYNC_END1(category, name, id, arg1_name, \
399 cef_trace_event_async_end(category, name, id, arg1_name, arg1_val, NULL, 0, \
401 #define TRACE_EVENT_COPY_ASYNC_END2(category, name, id, arg1_name, \
402 arg1_val, arg2_name, arg2_val) \
403 cef_trace_event_async_end(category, name, id, arg1_name, arg1_val, \
404 arg2_name, arg2_val, true)
406 namespace cef_trace_event {
408 // Used by TRACE_EVENTx macro. Do not use directly.
409 class CefTraceEndOnScopeClose {
411 CefTraceEndOnScopeClose(const char* category, const char* name)
412 : category_(category), name_(name) {
414 ~CefTraceEndOnScopeClose() {
415 cef_trace_event_end(category_, name_, NULL, 0, NULL, 0, false);
419 const char* category_;
425 #endif // !BUILDING_CEF_SHARED
427 #endif // CEF_INCLUDE_BASE_CEF_TRACE_EVENT_H_