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(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(USING_CHROMIUM_INCLUDES) 149 // When building CEF include the Chromium header directly. 150 #include "base/trace_event/trace_event.h" 151 #else // !USING_CHROMIUM_INCLUDES 152 // The following is substantially similar to the Chromium implementation. 153 // If the Chromium implementation diverges the below implementation should be 154 // updated to match. 155 156 #include "include/internal/cef_trace_event_internal.h" 157 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, arg2_val) \ 170 cef_trace_event_begin(category, name, arg1_name, arg1_val, arg2_name, \ 171 arg2_val, false); \ 172 CEF_INTERNAL_TRACE_END_ON_SCOPE_CLOSE(category, name) 173 174 // Implementation detail: trace event macros create temporary variable names. 175 // These macros give each temporary variable a unique name based on the line 176 // number to prevent name collisions. 177 #define CEF_INTERNAL_TRACE_EVENT_UID3(a, b) cef_trace_event_unique_##a##b 178 #define CEF_INTERNAL_TRACE_EVENT_UID2(a, b) CEF_INTERNAL_TRACE_EVENT_UID3(a, b) 179 #define CEF_INTERNAL_TRACE_EVENT_UID(name_prefix) \ 180 CEF_INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__) 181 182 // Implementation detail: internal macro to end end event when the scope ends. 183 #define CEF_INTERNAL_TRACE_END_ON_SCOPE_CLOSE(category, name) \ 184 cef_trace_event::CefTraceEndOnScopeClose CEF_INTERNAL_TRACE_EVENT_UID( \ 185 profileScope)(category, name) 186 187 // Records a single event called "name" immediately, with 0, 1 or 2 188 // associated arguments. If the category is not enabled, then this 189 // does nothing. 190 // - category and name strings must have application lifetime (statics or 191 // literals). They may not include " chars. 192 #define TRACE_EVENT_INSTANT0(category, name) \ 193 cef_trace_event_instant(category, name, NULL, 0, NULL, 0, false) 194 #define TRACE_EVENT_INSTANT1(category, name, arg1_name, arg1_val) \ 195 cef_trace_event_instant(category, name, arg1_name, arg1_val, NULL, 0, false) 196 #define TRACE_EVENT_INSTANT2(category, name, arg1_name, arg1_val, arg2_name, \ 197 arg2_val) \ 198 cef_trace_event_instant(category, name, arg1_name, arg1_val, arg2_name, \ 199 arg2_val, false) 200 #define TRACE_EVENT_COPY_INSTANT0(category, name) \ 201 cef_trace_event_instant(category, name, NULL, 0, NULL, 0, true) 202 #define TRACE_EVENT_COPY_INSTANT1(category, name, arg1_name, arg1_val) \ 203 cef_trace_event_instant(category, name, arg1_name, arg1_val, NULL, 0, true) 204 #define TRACE_EVENT_COPY_INSTANT2(category, name, arg1_name, arg1_val, \ 205 arg2_name, arg2_val) \ 206 cef_trace_event_instant(category, name, arg1_name, arg1_val, arg2_name, \ 207 arg2_val, true) 208 209 // Records a single BEGIN event called "name" immediately, with 0, 1 or 2 210 // associated arguments. If the category is not enabled, then this 211 // does nothing. 212 // - category and name strings must have application lifetime (statics or 213 // literals). They may not include " chars. 214 #define TRACE_EVENT_BEGIN0(category, name) \ 215 cef_trace_event_begin(category, name, NULL, 0, NULL, 0, false) 216 #define TRACE_EVENT_BEGIN1(category, name, arg1_name, arg1_val) \ 217 cef_trace_event_begin(category, name, arg1_name, arg1_val, NULL, 0, false) 218 #define TRACE_EVENT_BEGIN2(category, name, arg1_name, arg1_val, arg2_name, \ 219 arg2_val) \ 220 cef_trace_event_begin(category, name, arg1_name, arg1_val, arg2_name, \ 221 arg2_val, false) 222 #define TRACE_EVENT_COPY_BEGIN0(category, name) \ 223 cef_trace_event_begin(category, name, NULL, 0, NULL, 0, true) 224 #define TRACE_EVENT_COPY_BEGIN1(category, name, arg1_name, arg1_val) \ 225 cef_trace_event_begin(category, name, arg1_name, arg1_val, NULL, 0, true) 226 #define TRACE_EVENT_COPY_BEGIN2(category, name, arg1_name, arg1_val, \ 227 arg2_name, arg2_val) \ 228 cef_trace_event_begin(category, name, arg1_name, arg1_val, arg2_name, \ 229 arg2_val, true) 230 231 // Records a single END event for "name" immediately. If the category 232 // is not enabled, then this does nothing. 233 // - category and name strings must have application lifetime (statics or 234 // literals). They may not include " chars. 235 #define TRACE_EVENT_END0(category, name) \ 236 cef_trace_event_end(category, name, NULL, 0, NULL, 0, false) 237 #define TRACE_EVENT_END1(category, name, arg1_name, arg1_val) \ 238 cef_trace_event_end(category, name, arg1_name, arg1_val, NULL, 0, false) 239 #define TRACE_EVENT_END2(category, name, arg1_name, arg1_val, arg2_name, \ 240 arg2_val) \ 241 cef_trace_event_end(category, name, arg1_name, arg1_val, arg2_name, \ 242 arg2_val, false) 243 #define TRACE_EVENT_COPY_END0(category, name) \ 244 cef_trace_event_end(category, name, NULL, 0, NULL, 0, true) 245 #define TRACE_EVENT_COPY_END1(category, name, arg1_name, arg1_val) \ 246 cef_trace_event_end(category, name, arg1_name, arg1_val, NULL, 0, true) 247 #define TRACE_EVENT_COPY_END2(category, name, arg1_name, arg1_val, arg2_name, \ 248 arg2_val) \ 249 cef_trace_event_end(category, name, arg1_name, arg1_val, arg2_name, \ 250 arg2_val, true) 251 252 // Records the value of a counter called "name" immediately. Value 253 // must be representable as a 32 bit integer. 254 // - category and name strings must have application lifetime (statics or 255 // literals). They may not include " chars. 256 #define TRACE_COUNTER1(category, name, value) \ 257 cef_trace_counter(category, name, NULL, value, NULL, 0, false) 258 #define TRACE_COPY_COUNTER1(category, name, value) \ 259 cef_trace_counter(category, name, NULL, value, NULL, 0, true) 260 261 // Records the values of a multi-parted counter called "name" immediately. 262 // The UI will treat value1 and value2 as parts of a whole, displaying their 263 // values as a stacked-bar chart. 264 // - category and name strings must have application lifetime (statics or 265 // literals). They may not include " chars. 266 #define TRACE_COUNTER2(category, name, value1_name, value1_val, value2_name, \ 267 value2_val) \ 268 cef_trace_counter(category, name, value1_name, value1_val, value2_name, \ 269 value2_val, false) 270 #define TRACE_COPY_COUNTER2(category, name, value1_name, value1_val, \ 271 value2_name, value2_val) \ 272 cef_trace_counter(category, name, value1_name, value1_val, value2_name, \ 273 value2_val, true) 274 275 // Records the value of a counter called "name" immediately. Value 276 // must be representable as a 32 bit integer. 277 // - category and name strings must have application lifetime (statics or 278 // literals). They may not include " chars. 279 // - |id| is used to disambiguate counters with the same name. It must either 280 // be a pointer or an integer value up to 64 bits. If it's a pointer, the 281 // bits will be xored with a hash of the process ID so that the same pointer 282 // on two different processes will not collide. 283 #define TRACE_COUNTER_ID1(category, name, id, value) \ 284 cef_trace_counter_id(category, name, id, NULL, value, NULL, 0, false) 285 #define TRACE_COPY_COUNTER_ID1(category, name, id, value) \ 286 cef_trace_counter_id(category, name, id, NULL, value, NULL, 0, true) 287 288 // Records the values of a multi-parted counter called "name" immediately. 289 // The UI will treat value1 and value2 as parts of a whole, displaying their 290 // values as a stacked-bar chart. 291 // - category and name strings must have application lifetime (statics or 292 // literals). They may not include " chars. 293 // - |id| is used to disambiguate counters with the same name. It must either 294 // be a pointer or an integer value up to 64 bits. If it's a pointer, the 295 // bits will be xored with a hash of the process ID so that the same pointer 296 // on two different processes will not collide. 297 #define TRACE_COUNTER_ID2(category, name, id, value1_name, value1_val, \ 298 value2_name, value2_val) \ 299 cef_trace_counter_id(category, name, id, value1_name, value1_val, \ 300 value2_name, value2_val, false) 301 #define TRACE_COPY_COUNTER_ID2(category, name, id, value1_name, value1_val, \ 302 value2_name, value2_val) \ 303 cef_trace_counter_id(category, name, id, value1_name, value1_val, \ 304 value2_name, value2_val, true) 305 306 // Records a single ASYNC_BEGIN event called "name" immediately, with 0, 1 or 2 307 // associated arguments. If the category is not enabled, then this 308 // does nothing. 309 // - category and name strings must have application lifetime (statics or 310 // literals). They may not include " chars. 311 // - |id| is used to match the ASYNC_BEGIN event with the ASYNC_END event. 312 // ASYNC events are considered to match if their category, name and id values 313 // all match. |id| must either be a pointer or an integer value up to 64 314 // bits. If it's a pointer, the bits will be xored with a hash of the process 315 // ID sothat the same pointer on two different processes will not collide. 316 // An asynchronous operation can consist of multiple phases. The first phase is 317 // defined by the ASYNC_BEGIN calls. Additional phases can be defined using the 318 // ASYNC_STEP_BEGIN macros. When the operation completes, call ASYNC_END. 319 // An async operation can span threads and processes, but all events in that 320 // operation must use the same |name| and |id|. Each event can have its own 321 // args. 322 #define TRACE_EVENT_ASYNC_BEGIN0(category, name, id) \ 323 cef_trace_event_async_begin(category, name, id, NULL, 0, NULL, 0, false) 324 #define TRACE_EVENT_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \ 325 cef_trace_event_async_begin(category, name, id, arg1_name, arg1_val, NULL, \ 326 0, false) 327 #define TRACE_EVENT_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \ 328 arg2_name, arg2_val) \ 329 cef_trace_event_async_begin(category, name, id, arg1_name, arg1_val, \ 330 arg2_name, arg2_val, false) 331 #define TRACE_EVENT_COPY_ASYNC_BEGIN0(category, name, id) \ 332 cef_trace_event_async_begin(category, name, id, NULL, 0, NULL, 0, true) 333 #define TRACE_EVENT_COPY_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \ 334 cef_trace_event_async_begin(category, name, id, arg1_name, arg1_val, NULL, \ 335 0, true) 336 #define TRACE_EVENT_COPY_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \ 337 arg2_name, arg2_val) \ 338 cef_trace_event_async_begin(category, name, id, arg1_name, arg1_val, \ 339 arg2_name, arg2_val, true) 340 341 // Records a single ASYNC_STEP_INTO event for |step| immediately. If the 342 // category is not enabled, then this does nothing. The |name| and |id| must 343 // match the ASYNC_BEGIN event above. The |step| param identifies this step 344 // within the async event. This should be called at the beginning of the next 345 // phase of an asynchronous operation. The ASYNC_BEGIN event must not have any 346 // ASYNC_STEP_PAST events. 347 #define TRACE_EVENT_ASYNC_STEP_INTO0(category, name, id, step) \ 348 cef_trace_event_async_step_into(category, name, id, step, NULL, 0, false) 349 #define TRACE_EVENT_ASYNC_STEP_INTO1(category, name, id, step, arg1_name, \ 350 arg1_val) \ 351 cef_trace_event_async_step_into(category, name, id, step, arg1_name, \ 352 arg1_val, false) 353 #define TRACE_EVENT_COPY_ASYNC_STEP_INTO0(category, name, id, step) \ 354 cef_trace_event_async_step_into(category, name, id, step, NULL, 0, true) 355 #define TRACE_EVENT_COPY_ASYNC_STEP_INTO1(category, name, id, step, arg1_name, \ 356 arg1_val) \ 357 cef_trace_event_async_step_into(category, name, id, step, arg1_name, \ 358 arg1_val, true) 359 360 // Records a single ASYNC_STEP_PAST event for |step| immediately. If the 361 // category is not enabled, then this does nothing. The |name| and |id| must 362 // match the ASYNC_BEGIN event above. The |step| param identifies this step 363 // within the async event. This should be called at the beginning of the next 364 // phase of an asynchronous operation. The ASYNC_BEGIN event must not have any 365 // ASYNC_STEP_INTO events. 366 #define TRACE_EVENT_ASYNC_STEP_PAST0(category, name, id, step) \ 367 cef_trace_event_async_step_past(category, name, id, step, NULL, 0, false) 368 #define TRACE_EVENT_ASYNC_STEP_PAST1(category, name, id, step, arg1_name, \ 369 arg1_val) \ 370 cef_trace_event_async_step_past(category, name, id, step, arg1_name, \ 371 arg1_val, false) 372 #define TRACE_EVENT_COPY_ASYNC_STEP_PAST0(category, name, id, step) \ 373 cef_trace_event_async_step_past(category, name, id, step, NULL, 0, true) 374 #define TRACE_EVENT_COPY_ASYNC_STEP_PAST1(category, name, id, step, arg1_name, \ 375 arg1_val) \ 376 cef_trace_event_async_step_past(category, name, id, step, arg1_name, \ 377 arg1_val, true) 378 379 // Records a single ASYNC_END event for "name" immediately. If the category 380 // is not enabled, then this does nothing. 381 #define TRACE_EVENT_ASYNC_END0(category, name, id) \ 382 cef_trace_event_async_end(category, name, id, NULL, 0, NULL, 0, false) 383 #define TRACE_EVENT_ASYNC_END1(category, name, id, arg1_name, arg1_val) \ 384 cef_trace_event_async_end(category, name, id, arg1_name, arg1_val, NULL, 0, \ 385 false) 386 #define TRACE_EVENT_ASYNC_END2(category, name, id, arg1_name, arg1_val, \ 387 arg2_name, arg2_val) \ 388 cef_trace_event_async_end(category, name, id, arg1_name, arg1_val, \ 389 arg2_name, arg2_val, false) 390 #define TRACE_EVENT_COPY_ASYNC_END0(category, name, id) \ 391 cef_trace_event_async_end(category, name, id, NULL, 0, NULL, 0, true) 392 #define TRACE_EVENT_COPY_ASYNC_END1(category, name, id, arg1_name, arg1_val) \ 393 cef_trace_event_async_end(category, name, id, arg1_name, arg1_val, NULL, 0, \ 394 true) 395 #define TRACE_EVENT_COPY_ASYNC_END2(category, name, id, arg1_name, arg1_val, \ 396 arg2_name, arg2_val) \ 397 cef_trace_event_async_end(category, name, id, arg1_name, arg1_val, \ 398 arg2_name, arg2_val, true) 399 400 namespace cef_trace_event { 401 402 // Used by TRACE_EVENTx macro. Do not use directly. 403 class CefTraceEndOnScopeClose { 404 public: CefTraceEndOnScopeClose(const char * category,const char * name)405 CefTraceEndOnScopeClose(const char* category, const char* name) 406 : category_(category), name_(name) {} ~CefTraceEndOnScopeClose()407 ~CefTraceEndOnScopeClose() { 408 cef_trace_event_end(category_, name_, NULL, 0, NULL, 0, false); 409 } 410 411 private: 412 const char* category_; 413 const char* name_; 414 }; 415 416 } // cef_trace_event 417 418 #endif // !USING_CHROMIUM_INCLUDES 419 420 #endif // CEF_INCLUDE_BASE_CEF_TRACE_EVENT_H_ 421