1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef BASE_TRACE_EVENT_TRACE_EVENT_H_
6 #define BASE_TRACE_EVENT_TRACE_EVENT_H_
7
8 // This header file defines implementation details of how the trace macros in
9 // trace_event_common.h collect and store trace events. Anything not
10 // implementation-specific should go in trace_event_common.h instead of here.
11
12 #include <stddef.h>
13 #include <stdint.h>
14
15 #include <memory>
16 #include <utility>
17
18 #include "base/atomicops.h"
19 #include "base/base_export.h"
20 #include "base/threading/platform_thread.h"
21 #include "base/time/time.h"
22 #include "base/time/time_override.h"
23 #include "base/trace_event/builtin_categories.h"
24 #include "base/trace_event/common/trace_event_common.h" // IWYU pragma: export
25 #include "base/trace_event/trace_arguments.h"
26 #include "base/trace_event/trace_category.h"
27 #include "base/trace_event/trace_log.h"
28 #include "base/trace_event/traced_value_support.h"
29 #include "base/tracing_buildflags.h"
30
31 // Legacy TRACE_EVENT_API entrypoints. Do not use from new code.
32
33 // Add a trace event to the platform tracing system.
34 // base::trace_event::TraceEventHandle TRACE_EVENT_API_ADD_TRACE_EVENT(
35 // char phase,
36 // const unsigned char* category_group_enabled,
37 // const char* name,
38 // const char* scope,
39 // uint64_t id,
40 // base::trace_event::TraceArguments* args,
41 // unsigned int flags)
42 #define TRACE_EVENT_API_ADD_TRACE_EVENT trace_event_internal::AddTraceEvent
43
44 // Add a trace event to the platform tracing system.
45 // base::trace_event::TraceEventHandle
46 // TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_BIND_ID(
47 // char phase,
48 // const unsigned char* category_group_enabled,
49 // const char* name,
50 // const char* scope,
51 // uint64_t id,
52 // uint64_t bind_id,
53 // base::trace_event::TraceArguments* args,
54 // unsigned int flags)
55 #define TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_BIND_ID \
56 trace_event_internal::AddTraceEventWithBindId
57
58 // Add a trace event to the platform tracing system overriding the pid.
59 // The resulting event will have tid = pid == (process_id passed here).
60 // base::trace_event::TraceEventHandle
61 // TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_PROCESS_ID(
62 // char phase,
63 // const unsigned char* category_group_enabled,
64 // const char* name,
65 // const char* scope,
66 // uint64_t id,
67 // base::ProcessId process_id,
68 // base::trace_event::TraceArguments* args,
69 // unsigned int flags)
70 #define TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_PROCESS_ID \
71 trace_event_internal::AddTraceEventWithProcessId
72
73 // Add a trace event to the platform tracing system.
74 // base::trace_event::TraceEventHandle
75 // TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
76 // char phase,
77 // const unsigned char* category_group_enabled,
78 // const char* name,
79 // const char* scope,
80 // uint64_t id,
81 // uint64_t bind_id,
82 // base::PlatformThreadId thread_id,
83 // const TimeTicks& timestamp,
84 // base::trace_event::TraceArguments* args,
85 // unsigned int flags)
86 #define TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP \
87 trace_event_internal::AddTraceEventWithThreadIdAndTimestamp
88
89 // Set the duration field of a COMPLETE trace event.
90 // void TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(
91 // const unsigned char* category_group_enabled,
92 // const char* name,
93 // base::trace_event::TraceEventHandle id)
94 #define TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION \
95 trace_event_internal::UpdateTraceEventDuration
96
97 // Adds a metadata event to the trace log. The |AppendValueAsTraceFormat| method
98 // on the convertable value will be called at flush time.
99 // TRACE_EVENT_API_ADD_METADATA_EVENT(
100 // const unsigned char* category_group_enabled,
101 // const char* event_name,
102 // const char* arg_name,
103 // std::unique_ptr<ConvertableToTraceFormat> arg_value)
104 #define TRACE_EVENT_API_ADD_METADATA_EVENT \
105 trace_event_internal::AddMetadataEvent
106
107 // Defines atomic operations used internally by the tracing system.
108 // Acquire/release barriers are important here: crbug.com/1330114#c8.
109 #define TRACE_EVENT_API_ATOMIC_WORD base::subtle::AtomicWord
110 #define TRACE_EVENT_API_ATOMIC_LOAD(var) base::subtle::Acquire_Load(&(var))
111 #define TRACE_EVENT_API_ATOMIC_STORE(var, value) \
112 base::subtle::Release_Store(&(var), (value))
113
114 // Defines visibility for classes in trace_event.h
115 #define TRACE_EVENT_API_CLASS_EXPORT BASE_EXPORT
116
117 ////////////////////////////////////////////////////////////////////////////////
118
119 namespace trace_event_internal {
120
121 // Specify these values when the corresponding argument of AddTraceEvent is not
122 // used.
123 const int kZeroNumArgs = 0;
124 const std::nullptr_t kGlobalScope = nullptr;
125 const uint64_t kNoId = 0;
126
127 // TraceID encapsulates an ID that can either be an integer or pointer.
128 class BASE_EXPORT TraceID {
129 public:
130 // Can be combined with WithScope.
131 class LocalId {
132 public:
LocalId(const void * raw_id)133 explicit LocalId(const void* raw_id)
134 : raw_id_(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(raw_id))) {}
LocalId(uint64_t raw_id)135 explicit LocalId(uint64_t raw_id) : raw_id_(raw_id) {}
raw_id()136 uint64_t raw_id() const { return raw_id_; }
137
138 private:
139 uint64_t raw_id_;
140 };
141
142 // Can be combined with WithScope.
143 class GlobalId {
144 public:
GlobalId(uint64_t raw_id)145 explicit GlobalId(uint64_t raw_id) : raw_id_(raw_id) {}
raw_id()146 uint64_t raw_id() const { return raw_id_; }
147
148 private:
149 uint64_t raw_id_;
150 };
151
152 class WithScope {
153 public:
WithScope(const char * scope,uint64_t raw_id)154 WithScope(const char* scope, uint64_t raw_id)
155 : scope_(scope), raw_id_(raw_id) {}
WithScope(const char * scope,LocalId local_id)156 WithScope(const char* scope, LocalId local_id)
157 : scope_(scope), raw_id_(local_id.raw_id()) {
158 id_flags_ = TRACE_EVENT_FLAG_HAS_LOCAL_ID;
159 }
WithScope(const char * scope,GlobalId global_id)160 WithScope(const char* scope, GlobalId global_id)
161 : scope_(scope), raw_id_(global_id.raw_id()) {
162 id_flags_ = TRACE_EVENT_FLAG_HAS_GLOBAL_ID;
163 }
raw_id()164 uint64_t raw_id() const { return raw_id_; }
scope()165 const char* scope() const { return scope_; }
id_flags()166 unsigned int id_flags() const { return id_flags_; }
167
168 private:
169 const char* scope_ = nullptr;
170 uint64_t raw_id_;
171 unsigned int id_flags_ = TRACE_EVENT_FLAG_HAS_ID;
172 };
173
TraceID(const void * raw_id)174 explicit TraceID(const void* raw_id)
175 : raw_id_(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(raw_id))) {
176 id_flags_ = TRACE_EVENT_FLAG_HAS_LOCAL_ID;
177 }
TraceID(unsigned long long raw_id)178 explicit TraceID(unsigned long long raw_id)
179 : raw_id_(static_cast<uint64_t>(raw_id)) {}
TraceID(unsigned long raw_id)180 explicit TraceID(unsigned long raw_id)
181 : raw_id_(static_cast<uint64_t>(raw_id)) {}
TraceID(unsigned int raw_id)182 explicit TraceID(unsigned int raw_id)
183 : raw_id_(static_cast<uint64_t>(raw_id)) {}
TraceID(unsigned short raw_id)184 explicit TraceID(unsigned short raw_id)
185 : raw_id_(static_cast<uint64_t>(raw_id)) {}
TraceID(unsigned char raw_id)186 explicit TraceID(unsigned char raw_id)
187 : raw_id_(static_cast<uint64_t>(raw_id)) {}
TraceID(long long raw_id)188 explicit TraceID(long long raw_id) : raw_id_(static_cast<uint64_t>(raw_id)) {}
TraceID(long raw_id)189 explicit TraceID(long raw_id) : raw_id_(static_cast<uint64_t>(raw_id)) {}
TraceID(int raw_id)190 explicit TraceID(int raw_id) : raw_id_(static_cast<uint64_t>(raw_id)) {}
TraceID(short raw_id)191 explicit TraceID(short raw_id) : raw_id_(static_cast<uint64_t>(raw_id)) {}
TraceID(signed char raw_id)192 explicit TraceID(signed char raw_id)
193 : raw_id_(static_cast<uint64_t>(raw_id)) {}
TraceID(LocalId raw_id)194 explicit TraceID(LocalId raw_id) : raw_id_(raw_id.raw_id()) {
195 id_flags_ = TRACE_EVENT_FLAG_HAS_LOCAL_ID;
196 }
TraceID(GlobalId raw_id)197 explicit TraceID(GlobalId raw_id) : raw_id_(raw_id.raw_id()) {
198 id_flags_ = TRACE_EVENT_FLAG_HAS_GLOBAL_ID;
199 }
TraceID(WithScope scoped_id)200 explicit TraceID(WithScope scoped_id)
201 : scope_(scoped_id.scope()),
202 raw_id_(scoped_id.raw_id()),
203 id_flags_(scoped_id.id_flags()) {}
204
raw_id()205 uint64_t raw_id() const { return raw_id_; }
scope()206 const char* scope() const { return scope_; }
id_flags()207 unsigned int id_flags() const { return id_flags_; }
208
209 private:
210 const char* scope_ = nullptr;
211 uint64_t raw_id_;
212 unsigned int id_flags_ = TRACE_EVENT_FLAG_HAS_ID;
213 };
214
215 // These functions all internally call
216 // base::trace_event::TraceLog::GetInstance() then call the method with the same
217 // name on it. This is used to reduce the generated machine code at each
218 // TRACE_EVENTXXX macro call.
219
220 base::trace_event::TraceEventHandle BASE_EXPORT
221 AddTraceEvent(char phase,
222 const unsigned char* category_group_enabled,
223 const char* name,
224 const char* scope,
225 uint64_t id,
226 base::trace_event::TraceArguments* args,
227 unsigned int flags);
228
229 base::trace_event::TraceEventHandle BASE_EXPORT
230 AddTraceEventWithBindId(char phase,
231 const unsigned char* category_group_enabled,
232 const char* name,
233 const char* scope,
234 uint64_t id,
235 uint64_t bind_id,
236 base::trace_event::TraceArguments* args,
237 unsigned int flags);
238
239 base::trace_event::TraceEventHandle BASE_EXPORT
240 AddTraceEventWithProcessId(char phase,
241 const unsigned char* category_group_enabled,
242 const char* name,
243 const char* scope,
244 uint64_t id,
245 base::ProcessId process_id,
246 base::trace_event::TraceArguments* args,
247 unsigned int flags);
248
249 base::trace_event::TraceEventHandle BASE_EXPORT
250 AddTraceEventWithThreadIdAndTimestamp(
251 char phase,
252 const unsigned char* category_group_enabled,
253 const char* name,
254 const char* scope,
255 uint64_t id,
256 base::PlatformThreadId thread_id,
257 const base::TimeTicks& timestamp,
258 base::trace_event::TraceArguments* args,
259 unsigned int flags);
260
261 base::trace_event::TraceEventHandle BASE_EXPORT
262 AddTraceEventWithThreadIdAndTimestamp(
263 char phase,
264 const unsigned char* category_group_enabled,
265 const char* name,
266 const char* scope,
267 uint64_t id,
268 uint64_t bind_id,
269 base::PlatformThreadId thread_id,
270 const base::TimeTicks& timestamp,
271 base::trace_event::TraceArguments* args,
272 unsigned int flags);
273
274 base::trace_event::TraceEventHandle BASE_EXPORT
275 AddTraceEventWithThreadIdAndTimestamps(
276 char phase,
277 const unsigned char* category_group_enabled,
278 const char* name,
279 const char* scope,
280 uint64_t id,
281 base::PlatformThreadId thread_id,
282 const base::TimeTicks& timestamp,
283 const base::ThreadTicks& thread_timestamp,
284 unsigned int flags);
285
286 void BASE_EXPORT AddMetadataEvent(const unsigned char* category_group_enabled,
287 const char* name,
288 base::trace_event::TraceArguments* args,
289 unsigned int flags);
290
291 int BASE_EXPORT GetNumTracesRecorded();
292
293 void BASE_EXPORT
294 UpdateTraceEventDuration(const unsigned char* category_group_enabled,
295 const char* name,
296 base::trace_event::TraceEventHandle handle);
297
298 void BASE_EXPORT
299 UpdateTraceEventDurationExplicit(const unsigned char* category_group_enabled,
300 const char* name,
301 base::trace_event::TraceEventHandle handle,
302 base::PlatformThreadId thread_id,
303 bool explicit_timestamps,
304 const base::TimeTicks& now,
305 const base::ThreadTicks& thread_now);
306
307 // These AddTraceEvent and AddTraceEventWithThreadIdAndTimestamp template
308 // functions are defined here instead of in the macro, because the arg_values
309 // could be temporary objects, such as `std::string`. In order to store
310 // pointers to the internal c_str and pass through to the tracing API,
311 // the arg_values must live throughout these procedures.
312
313 template <class ARG1_TYPE>
314 inline base::trace_event::TraceEventHandle
AddTraceEventWithThreadIdAndTimestamp(char phase,const unsigned char * category_group_enabled,const char * name,const char * scope,uint64_t id,base::PlatformThreadId thread_id,const base::TimeTicks & timestamp,unsigned int flags,uint64_t bind_id,const char * arg1_name,ARG1_TYPE && arg1_val)315 AddTraceEventWithThreadIdAndTimestamp(
316 char phase,
317 const unsigned char* category_group_enabled,
318 const char* name,
319 const char* scope,
320 uint64_t id,
321 base::PlatformThreadId thread_id,
322 const base::TimeTicks& timestamp,
323 unsigned int flags,
324 uint64_t bind_id,
325 const char* arg1_name,
326 ARG1_TYPE&& arg1_val) {
327 base::trace_event::TraceArguments args(arg1_name,
328 std::forward<ARG1_TYPE>(arg1_val));
329 return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
330 phase, category_group_enabled, name, scope, id, bind_id, thread_id,
331 timestamp, &args, flags);
332 }
333
334 template <class ARG1_TYPE, class ARG2_TYPE>
335 inline base::trace_event::TraceEventHandle
AddTraceEventWithThreadIdAndTimestamp(char phase,const unsigned char * category_group_enabled,const char * name,const char * scope,uint64_t id,base::PlatformThreadId thread_id,const base::TimeTicks & timestamp,unsigned int flags,uint64_t bind_id,const char * arg1_name,ARG1_TYPE && arg1_val,const char * arg2_name,ARG2_TYPE && arg2_val)336 AddTraceEventWithThreadIdAndTimestamp(
337 char phase,
338 const unsigned char* category_group_enabled,
339 const char* name,
340 const char* scope,
341 uint64_t id,
342 base::PlatformThreadId thread_id,
343 const base::TimeTicks& timestamp,
344 unsigned int flags,
345 uint64_t bind_id,
346 const char* arg1_name,
347 ARG1_TYPE&& arg1_val,
348 const char* arg2_name,
349 ARG2_TYPE&& arg2_val) {
350 base::trace_event::TraceArguments args(
351 arg1_name, std::forward<ARG1_TYPE>(arg1_val), arg2_name,
352 std::forward<ARG2_TYPE>(arg2_val));
353 return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
354 phase, category_group_enabled, name, scope, id, bind_id, thread_id,
355 timestamp, &args, flags);
356 }
357
358 inline base::trace_event::TraceEventHandle
AddTraceEventWithThreadIdAndTimestamp(char phase,const unsigned char * category_group_enabled,const char * name,const char * scope,uint64_t id,base::PlatformThreadId thread_id,const base::TimeTicks & timestamp,unsigned int flags,uint64_t bind_id)359 AddTraceEventWithThreadIdAndTimestamp(
360 char phase,
361 const unsigned char* category_group_enabled,
362 const char* name,
363 const char* scope,
364 uint64_t id,
365 base::PlatformThreadId thread_id,
366 const base::TimeTicks& timestamp,
367 unsigned int flags,
368 uint64_t bind_id) {
369 return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
370 phase, category_group_enabled, name, scope, id, bind_id, thread_id,
371 timestamp, nullptr, flags);
372 }
373
AddTraceEvent(char phase,const unsigned char * category_group_enabled,const char * name,const char * scope,uint64_t id,unsigned int flags,uint64_t bind_id)374 inline base::trace_event::TraceEventHandle AddTraceEvent(
375 char phase,
376 const unsigned char* category_group_enabled,
377 const char* name,
378 const char* scope,
379 uint64_t id,
380 unsigned int flags,
381 uint64_t bind_id) {
382 return AddTraceEventWithThreadIdAndTimestamp(
383 phase, category_group_enabled, name, scope, id,
384 TRACE_EVENT_API_CURRENT_THREAD_ID, TRACE_TIME_TICKS_NOW(), flags,
385 bind_id);
386 }
387
388 template <class ARG1_TYPE>
AddTraceEvent(char phase,const unsigned char * category_group_enabled,const char * name,const char * scope,uint64_t id,unsigned int flags,uint64_t bind_id,const char * arg1_name,ARG1_TYPE && arg1_val)389 inline base::trace_event::TraceEventHandle AddTraceEvent(
390 char phase,
391 const unsigned char* category_group_enabled,
392 const char* name,
393 const char* scope,
394 uint64_t id,
395 unsigned int flags,
396 uint64_t bind_id,
397 const char* arg1_name,
398 ARG1_TYPE&& arg1_val) {
399 return AddTraceEventWithThreadIdAndTimestamp(
400 phase, category_group_enabled, name, scope, id,
401 TRACE_EVENT_API_CURRENT_THREAD_ID, TRACE_TIME_TICKS_NOW(), flags, bind_id,
402 arg1_name, std::forward<ARG1_TYPE>(arg1_val));
403 }
404
405 template <class ARG1_TYPE, class ARG2_TYPE>
AddTraceEvent(char phase,const unsigned char * category_group_enabled,const char * name,const char * scope,uint64_t id,unsigned int flags,uint64_t bind_id,const char * arg1_name,ARG1_TYPE && arg1_val,const char * arg2_name,ARG2_TYPE && arg2_val)406 inline base::trace_event::TraceEventHandle AddTraceEvent(
407 char phase,
408 const unsigned char* category_group_enabled,
409 const char* name,
410 const char* scope,
411 uint64_t id,
412 unsigned int flags,
413 uint64_t bind_id,
414 const char* arg1_name,
415 ARG1_TYPE&& arg1_val,
416 const char* arg2_name,
417 ARG2_TYPE&& arg2_val) {
418 return AddTraceEventWithThreadIdAndTimestamp(
419 phase, category_group_enabled, name, scope, id,
420 TRACE_EVENT_API_CURRENT_THREAD_ID, TRACE_TIME_TICKS_NOW(), flags, bind_id,
421 arg1_name, std::forward<ARG1_TYPE>(arg1_val), arg2_name,
422 std::forward<ARG2_TYPE>(arg2_val));
423 }
424
425 template <class ARG1_TYPE>
AddMetadataEvent(const unsigned char * category_group_enabled,const char * event_name,const char * arg_name,ARG1_TYPE && arg_val)426 void AddMetadataEvent(const unsigned char* category_group_enabled,
427 const char* event_name,
428 const char* arg_name,
429 ARG1_TYPE&& arg_val) {
430 base::trace_event::TraceArguments args(arg_name,
431 std::forward<ARG1_TYPE>(arg_val));
432 trace_event_internal::AddMetadataEvent(category_group_enabled, event_name,
433 &args, TRACE_EVENT_FLAG_NONE);
434 }
435
436 } // namespace trace_event_internal
437
438 namespace base {
439 namespace trace_event {
440
441 template <typename IDType, const char* category>
442 class TraceScopedTrackableObject {
443 public:
TraceScopedTrackableObject(const char * name,IDType id)444 TraceScopedTrackableObject(const char* name, IDType id)
445 : name_(name), id_(id) {
446 TRACE_EVENT_OBJECT_CREATED_WITH_ID(category, name_, id_);
447 }
448 TraceScopedTrackableObject(const TraceScopedTrackableObject&) = delete;
449 TraceScopedTrackableObject& operator=(const TraceScopedTrackableObject&) =
450 delete;
451
snapshot(ArgType snapshot)452 template <typename ArgType> void snapshot(ArgType snapshot) {
453 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(category, name_, id_, snapshot);
454 }
455
~TraceScopedTrackableObject()456 ~TraceScopedTrackableObject() {
457 TRACE_EVENT_OBJECT_DELETED_WITH_ID(category, name_, id_);
458 }
459
460 private:
461 const char* name_;
462 IDType id_;
463 };
464
465 } // namespace trace_event
466 } // namespace base
467
468 #endif // BASE_TRACE_EVENT_TRACE_EVENT_H_
469