1 // Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012 2 // Google Inc. All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are 6 // met: 7 // 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 13 // distribution. 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. 18 // 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. 30 31 /// 32 // Trace events are for tracking application performance and resource usage. 33 // Macros are provided to track: 34 // Begin and end of function calls 35 // Counters 36 // 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") 40 // 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. 48 // 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"); 53 // ... 54 // } 55 // 56 // Additional parameters can be associated with an event: 57 // void doSomethingCostly2(int howMuch) { 58 // TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly", 59 // "howMuch", howMuch); 60 // ... 61 // } 62 // 63 // The trace system will automatically add to this information the current 64 // process id, thread id, and a timestamp in microseconds. 65 // 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; 70 // ++send_count; 71 // TRACE_EVENT_ASYNC_BEGIN0("ipc", "message", send_count); 72 // Send(new MyMessage(send_count)); 73 // [receive code] 74 // void OnMyMessage(send_count) { 75 // TRACE_EVENT_ASYNC_END0("ipc", "message", send_count); 76 // } 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 { 83 // public: 84 // MyTracedClass() { 85 // TRACE_EVENT_ASYNC_BEGIN0("category", "MyTracedClass", this); 86 // } 87 // ~MyTracedClass() { 88 // TRACE_EVENT_ASYNC_END0("category", "MyTracedClass", this); 89 // } 90 // } 91 // 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); 95 // 96 // Counters are process-specific. The macro itself can be issued from any 97 // thread, however. 98 // 99 // Sometimes, you want to track two counters at once. You can do this with two 100 // counter macros: 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. 109 // 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. 112 // 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 116 // processes. 117 // 118 // 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 122 // problems: 123 // char* str = strdup("impprtantName"); 124 // TRACE_EVENT_INSTANT0("SUBSYSTEM", str); // BAD! 125 // free(str); // Trace system now has dangling pointer 126 // 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 129 // overhead. 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 132 // macros. 133 // 134 // 135 // Thread Safety: 136 // All macros are thread safe and can be used from any process. 137 /// 138 139 #ifndef CEF_INCLUDE_BASE_CEF_TRACE_EVENT_H_ 140 #define CEF_INCLUDE_BASE_CEF_TRACE_EVENT_H_ 141 #pragma once 142 143 #if defined(USING_CHROMIUM_INCLUDES) 144 // When building CEF include the Chromium header directly. 145 #include "base/trace_event/trace_event.h" 146 #else // !USING_CHROMIUM_INCLUDES 147 // The following is substantially similar to the Chromium implementation. 148 // If the Chromium implementation diverges the below implementation should be 149 // updated to match. 150 151 #include "include/internal/cef_trace_event_internal.h" 152 153 // Records a pair of begin and end events called "name" for the current 154 // scope, with 0, 1 or 2 associated arguments. If the category is not 155 // enabled, then this does nothing. 156 // - category and name strings must have application lifetime (statics or 157 // literals). They may not include " chars. 158 #define TRACE_EVENT0(category, name) \ 159 cef_trace_event_begin(category, name, NULL, 0, NULL, 0, false); \ 160 CEF_INTERNAL_TRACE_END_ON_SCOPE_CLOSE(category, name) 161 #define TRACE_EVENT1(category, name, arg1_name, arg1_val) \ 162 cef_trace_event_begin(category, name, arg1_name, arg1_val, NULL, 0, false); \ 163 CEF_INTERNAL_TRACE_END_ON_SCOPE_CLOSE(category, name) 164 #define TRACE_EVENT2(category, name, arg1_name, arg1_val, arg2_name, arg2_val) \ 165 cef_trace_event_begin(category, name, arg1_name, arg1_val, arg2_name, \ 166 arg2_val, false); \ 167 CEF_INTERNAL_TRACE_END_ON_SCOPE_CLOSE(category, name) 168 169 // Implementation detail: trace event macros create temporary variable names. 170 // These macros give each temporary variable a unique name based on the line 171 // number to prevent name collisions. 172 #define CEF_INTERNAL_TRACE_EVENT_UID3(a, b) cef_trace_event_unique_##a##b 173 #define CEF_INTERNAL_TRACE_EVENT_UID2(a, b) CEF_INTERNAL_TRACE_EVENT_UID3(a, b) 174 #define CEF_INTERNAL_TRACE_EVENT_UID(name_prefix) \ 175 CEF_INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__) 176 177 // Implementation detail: internal macro to end end event when the scope ends. 178 #define CEF_INTERNAL_TRACE_END_ON_SCOPE_CLOSE(category, name) \ 179 cef_trace_event::CefTraceEndOnScopeClose CEF_INTERNAL_TRACE_EVENT_UID( \ 180 profileScope)(category, name) 181 182 // Records a single event called "name" immediately, with 0, 1 or 2 183 // associated arguments. If the category is not enabled, then this 184 // does nothing. 185 // - category and name strings must have application lifetime (statics or 186 // literals). They may not include " chars. 187 #define TRACE_EVENT_INSTANT0(category, name) \ 188 cef_trace_event_instant(category, name, NULL, 0, NULL, 0, false) 189 #define TRACE_EVENT_INSTANT1(category, name, arg1_name, arg1_val) \ 190 cef_trace_event_instant(category, name, arg1_name, arg1_val, NULL, 0, false) 191 #define TRACE_EVENT_INSTANT2(category, name, arg1_name, arg1_val, arg2_name, \ 192 arg2_val) \ 193 cef_trace_event_instant(category, name, arg1_name, arg1_val, arg2_name, \ 194 arg2_val, false) 195 #define TRACE_EVENT_COPY_INSTANT0(category, name) \ 196 cef_trace_event_instant(category, name, NULL, 0, NULL, 0, true) 197 #define TRACE_EVENT_COPY_INSTANT1(category, name, arg1_name, arg1_val) \ 198 cef_trace_event_instant(category, name, arg1_name, arg1_val, NULL, 0, true) 199 #define TRACE_EVENT_COPY_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, \ 202 arg2_val, true) 203 204 // Records a single BEGIN event called "name" immediately, with 0, 1 or 2 205 // associated arguments. If the category is not enabled, then this 206 // does nothing. 207 // - category and name strings must have application lifetime (statics or 208 // literals). They may not include " chars. 209 #define TRACE_EVENT_BEGIN0(category, name) \ 210 cef_trace_event_begin(category, name, NULL, 0, NULL, 0, false) 211 #define TRACE_EVENT_BEGIN1(category, name, arg1_name, arg1_val) \ 212 cef_trace_event_begin(category, name, arg1_name, arg1_val, NULL, 0, false) 213 #define TRACE_EVENT_BEGIN2(category, name, arg1_name, arg1_val, arg2_name, \ 214 arg2_val) \ 215 cef_trace_event_begin(category, name, arg1_name, arg1_val, arg2_name, \ 216 arg2_val, false) 217 #define TRACE_EVENT_COPY_BEGIN0(category, name) \ 218 cef_trace_event_begin(category, name, NULL, 0, NULL, 0, true) 219 #define TRACE_EVENT_COPY_BEGIN1(category, name, arg1_name, arg1_val) \ 220 cef_trace_event_begin(category, name, arg1_name, arg1_val, NULL, 0, true) 221 #define TRACE_EVENT_COPY_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, \ 224 arg2_val, true) 225 226 // Records a single END event for "name" immediately. If the category 227 // is not enabled, then this does nothing. 228 // - category and name strings must have application lifetime (statics or 229 // literals). They may not include " chars. 230 #define TRACE_EVENT_END0(category, name) \ 231 cef_trace_event_end(category, name, NULL, 0, NULL, 0, false) 232 #define TRACE_EVENT_END1(category, name, arg1_name, arg1_val) \ 233 cef_trace_event_end(category, name, arg1_name, arg1_val, NULL, 0, false) 234 #define TRACE_EVENT_END2(category, name, arg1_name, arg1_val, arg2_name, \ 235 arg2_val) \ 236 cef_trace_event_end(category, name, arg1_name, arg1_val, arg2_name, \ 237 arg2_val, false) 238 #define TRACE_EVENT_COPY_END0(category, name) \ 239 cef_trace_event_end(category, name, NULL, 0, NULL, 0, true) 240 #define TRACE_EVENT_COPY_END1(category, name, arg1_name, arg1_val) \ 241 cef_trace_event_end(category, name, arg1_name, arg1_val, NULL, 0, true) 242 #define TRACE_EVENT_COPY_END2(category, name, arg1_name, arg1_val, arg2_name, \ 243 arg2_val) \ 244 cef_trace_event_end(category, name, arg1_name, arg1_val, arg2_name, \ 245 arg2_val, true) 246 247 // Records the value of a counter called "name" immediately. Value 248 // must be representable as a 32 bit integer. 249 // - category and name strings must have application lifetime (statics or 250 // literals). They may not include " chars. 251 #define TRACE_COUNTER1(category, name, value) \ 252 cef_trace_counter(category, name, NULL, value, NULL, 0, false) 253 #define TRACE_COPY_COUNTER1(category, name, value) \ 254 cef_trace_counter(category, name, NULL, value, NULL, 0, true) 255 256 // Records the values of a multi-parted counter called "name" immediately. 257 // The UI will treat value1 and value2 as parts of a whole, displaying their 258 // values as a stacked-bar chart. 259 // - category and name strings must have application lifetime (statics or 260 // literals). They may not include " chars. 261 #define TRACE_COUNTER2(category, name, value1_name, value1_val, value2_name, \ 262 value2_val) \ 263 cef_trace_counter(category, name, value1_name, value1_val, value2_name, \ 264 value2_val, false) 265 #define TRACE_COPY_COUNTER2(category, name, value1_name, value1_val, \ 266 value2_name, value2_val) \ 267 cef_trace_counter(category, name, value1_name, value1_val, value2_name, \ 268 value2_val, true) 269 270 // Records the value of a counter called "name" immediately. Value 271 // must be representable as a 32 bit integer. 272 // - category and name strings must have application lifetime (statics or 273 // literals). They may not include " chars. 274 // - |id| is used to disambiguate counters with the same name. It must either 275 // be a pointer or an integer value up to 64 bits. If it's a pointer, the 276 // bits will be xored with a hash of the process ID so that the same pointer 277 // on two different processes will not collide. 278 #define TRACE_COUNTER_ID1(category, name, id, value) \ 279 cef_trace_counter_id(category, name, id, NULL, value, NULL, 0, false) 280 #define TRACE_COPY_COUNTER_ID1(category, name, id, value) \ 281 cef_trace_counter_id(category, name, id, NULL, value, NULL, 0, true) 282 283 // Records the values of a multi-parted counter called "name" immediately. 284 // The UI will treat value1 and value2 as parts of a whole, displaying their 285 // values as a stacked-bar chart. 286 // - category and name strings must have application lifetime (statics or 287 // literals). They may not include " chars. 288 // - |id| is used to disambiguate counters with the same name. It must either 289 // be a pointer or an integer value up to 64 bits. If it's a pointer, the 290 // bits will be xored with a hash of the process ID so that the same pointer 291 // on two different processes will not collide. 292 #define TRACE_COUNTER_ID2(category, name, id, value1_name, value1_val, \ 293 value2_name, value2_val) \ 294 cef_trace_counter_id(category, name, id, value1_name, value1_val, \ 295 value2_name, value2_val, false) 296 #define TRACE_COPY_COUNTER_ID2(category, name, id, value1_name, value1_val, \ 297 value2_name, value2_val) \ 298 cef_trace_counter_id(category, name, id, value1_name, value1_val, \ 299 value2_name, value2_val, true) 300 301 // Records a single ASYNC_BEGIN event called "name" immediately, with 0, 1 or 2 302 // associated arguments. If the category is not enabled, then this 303 // does nothing. 304 // - category and name strings must have application lifetime (statics or 305 // literals). They may not include " chars. 306 // - |id| is used to match the ASYNC_BEGIN event with the ASYNC_END event. 307 // ASYNC events are considered to match if their category, name and id values 308 // all match. |id| must either be a pointer or an integer value up to 64 309 // bits. If it's a pointer, the bits will be xored with a hash of the process 310 // ID sothat the same pointer on two different processes will not collide. 311 // An asynchronous operation can consist of multiple phases. The first phase is 312 // defined by the ASYNC_BEGIN calls. Additional phases can be defined using the 313 // ASYNC_STEP_BEGIN macros. When the operation completes, call ASYNC_END. 314 // An async operation can span threads and processes, but all events in that 315 // operation must use the same |name| and |id|. Each event can have its own 316 // args. 317 #define TRACE_EVENT_ASYNC_BEGIN0(category, name, id) \ 318 cef_trace_event_async_begin(category, name, id, NULL, 0, NULL, 0, false) 319 #define TRACE_EVENT_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \ 320 cef_trace_event_async_begin(category, name, id, arg1_name, arg1_val, NULL, \ 321 0, false) 322 #define TRACE_EVENT_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \ 323 arg2_name, arg2_val) \ 324 cef_trace_event_async_begin(category, name, id, arg1_name, arg1_val, \ 325 arg2_name, arg2_val, false) 326 #define TRACE_EVENT_COPY_ASYNC_BEGIN0(category, name, id) \ 327 cef_trace_event_async_begin(category, name, id, NULL, 0, NULL, 0, true) 328 #define TRACE_EVENT_COPY_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \ 329 cef_trace_event_async_begin(category, name, id, arg1_name, arg1_val, NULL, \ 330 0, true) 331 #define TRACE_EVENT_COPY_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, true) 335 336 // Records a single ASYNC_STEP_INTO event for |step| immediately. If the 337 // category is not enabled, then this does nothing. The |name| and |id| must 338 // match the ASYNC_BEGIN event above. The |step| param identifies this step 339 // within the async event. This should be called at the beginning of the next 340 // phase of an asynchronous operation. The ASYNC_BEGIN event must not have any 341 // ASYNC_STEP_PAST events. 342 #define TRACE_EVENT_ASYNC_STEP_INTO0(category, name, id, step) \ 343 cef_trace_event_async_step_into(category, name, id, step, NULL, 0, false) 344 #define TRACE_EVENT_ASYNC_STEP_INTO1(category, name, id, step, arg1_name, \ 345 arg1_val) \ 346 cef_trace_event_async_step_into(category, name, id, step, arg1_name, \ 347 arg1_val, false) 348 #define TRACE_EVENT_COPY_ASYNC_STEP_INTO0(category, name, id, step) \ 349 cef_trace_event_async_step_into(category, name, id, step, NULL, 0, true) 350 #define TRACE_EVENT_COPY_ASYNC_STEP_INTO1(category, name, id, step, arg1_name, \ 351 arg1_val) \ 352 cef_trace_event_async_step_into(category, name, id, step, arg1_name, \ 353 arg1_val, true) 354 355 // Records a single ASYNC_STEP_PAST event for |step| immediately. If the 356 // category is not enabled, then this does nothing. The |name| and |id| must 357 // match the ASYNC_BEGIN event above. The |step| param identifies this step 358 // within the async event. This should be called at the beginning of the next 359 // phase of an asynchronous operation. The ASYNC_BEGIN event must not have any 360 // ASYNC_STEP_INTO events. 361 #define TRACE_EVENT_ASYNC_STEP_PAST0(category, name, id, step) \ 362 cef_trace_event_async_step_past(category, name, id, step, NULL, 0, false) 363 #define TRACE_EVENT_ASYNC_STEP_PAST1(category, name, id, step, arg1_name, \ 364 arg1_val) \ 365 cef_trace_event_async_step_past(category, name, id, step, arg1_name, \ 366 arg1_val, false) 367 #define TRACE_EVENT_COPY_ASYNC_STEP_PAST0(category, name, id, step) \ 368 cef_trace_event_async_step_past(category, name, id, step, NULL, 0, true) 369 #define TRACE_EVENT_COPY_ASYNC_STEP_PAST1(category, name, id, step, arg1_name, \ 370 arg1_val) \ 371 cef_trace_event_async_step_past(category, name, id, step, arg1_name, \ 372 arg1_val, true) 373 374 // Records a single ASYNC_END event for "name" immediately. If the category 375 // is not enabled, then this does nothing. 376 #define TRACE_EVENT_ASYNC_END0(category, name, id) \ 377 cef_trace_event_async_end(category, name, id, NULL, 0, NULL, 0, false) 378 #define TRACE_EVENT_ASYNC_END1(category, name, id, arg1_name, arg1_val) \ 379 cef_trace_event_async_end(category, name, id, arg1_name, arg1_val, NULL, 0, \ 380 false) 381 #define TRACE_EVENT_ASYNC_END2(category, name, id, arg1_name, arg1_val, \ 382 arg2_name, arg2_val) \ 383 cef_trace_event_async_end(category, name, id, arg1_name, arg1_val, \ 384 arg2_name, arg2_val, false) 385 #define TRACE_EVENT_COPY_ASYNC_END0(category, name, id) \ 386 cef_trace_event_async_end(category, name, id, NULL, 0, NULL, 0, true) 387 #define TRACE_EVENT_COPY_ASYNC_END1(category, name, id, arg1_name, arg1_val) \ 388 cef_trace_event_async_end(category, name, id, arg1_name, arg1_val, NULL, 0, \ 389 true) 390 #define TRACE_EVENT_COPY_ASYNC_END2(category, name, id, arg1_name, arg1_val, \ 391 arg2_name, arg2_val) \ 392 cef_trace_event_async_end(category, name, id, arg1_name, arg1_val, \ 393 arg2_name, arg2_val, true) 394 395 namespace cef_trace_event { 396 397 // Used by TRACE_EVENTx macro. Do not use directly. 398 class CefTraceEndOnScopeClose { 399 public: CefTraceEndOnScopeClose(const char * category,const char * name)400 CefTraceEndOnScopeClose(const char* category, const char* name) 401 : category_(category), name_(name) {} ~CefTraceEndOnScopeClose()402 ~CefTraceEndOnScopeClose() { 403 cef_trace_event_end(category_, name_, NULL, 0, NULL, 0, false); 404 } 405 406 private: 407 const char* category_; 408 const char* name_; 409 }; 410 411 } // cef_trace_event 412 413 #endif // !USING_CHROMIUM_INCLUDES 414 415 #endif // CEF_INCLUDE_BASE_CEF_TRACE_EVENT_H_ 416