• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef INCLUDE_PERFETTO_TRACING_TRACK_EVENT_H_
18 #define INCLUDE_PERFETTO_TRACING_TRACK_EVENT_H_
19 
20 #include "perfetto/tracing/internal/track_event_data_source.h"
21 #include "perfetto/tracing/internal/track_event_internal.h"
22 #include "perfetto/tracing/internal/track_event_macros.h"
23 #include "perfetto/tracing/string_helpers.h"
24 #include "perfetto/tracing/track.h"
25 #include "perfetto/tracing/track_event_category_registry.h"
26 #include "protos/perfetto/trace/track_event/track_event.pbzero.h"
27 
28 #include <type_traits>
29 
30 // This file contains a set of macros designed for instrumenting applications
31 // with track event trace points. While the underlying TrackEvent API can also
32 // be used directly, doing so efficiently requires some care (e.g., to avoid
33 // evaluating arguments while tracing is disabled). These types of optimizations
34 // are abstracted away by the macros below.
35 //
36 // ================
37 // Quickstart guide
38 // ================
39 //
40 //   To add track events to your application, first define your categories in,
41 //   e.g., my_tracing.h:
42 //
43 //       PERFETTO_DEFINE_CATEGORIES(
44 //           perfetto::Category("base"),
45 //           perfetto::Category("v8"),
46 //           perfetto::Category("cc"));
47 //
48 //   Then in a single .cc file, e.g., my_tracing.cc:
49 //
50 //       #include "my_tracing.h"
51 //       PERFETTO_TRACK_EVENT_STATIC_STORAGE();
52 //
53 //   Finally, register track events at startup, after which you can record
54 //   events with the TRACE_EVENT macros:
55 //
56 //       #include "my_tracing.h"
57 //
58 //       int main() {
59 //         perfetto::TrackEvent::Register();
60 //
61 //         // A basic track event with just a name.
62 //         TRACE_EVENT("category", "MyEvent");
63 //
64 //         // A track event with (up to two) debug annotations.
65 //         TRACE_EVENT("category", "MyEvent", "parameter", 42);
66 //
67 //         // A track event with a strongly typed parameter.
68 //         TRACE_EVENT("category", "MyEvent", [](perfetto::EventContext ctx) {
69 //           ctx.event()->set_foo(42);
70 //           ctx.event()->set_bar(.5f);
71 //         });
72 //       }
73 //
74 //  Note that track events must be nested consistently, i.e., the following is
75 //  not allowed:
76 //
77 //    TRACE_EVENT_BEGIN("a", "bar", ...);
78 //    TRACE_EVENT_BEGIN("b", "foo", ...);
79 //    TRACE_EVENT_END("a");  // "foo" must be closed before "bar".
80 //    TRACE_EVENT_END("b");
81 //
82 // ====================
83 // Implementation notes
84 // ====================
85 //
86 // The track event library consists of the following layers and components. The
87 // classes the internal namespace shouldn't be considered part of the public
88 // API.
89 //                    .--------------------------------.
90 //               .----|  TRACE_EVENT                   |----.
91 //      write   |     |   - App instrumentation point  |     |  write
92 //      event   |     '--------------------------------'     |  arguments
93 //              V                                            V
94 //  .----------------------------------.    .-----------------------------.
95 //  | TrackEvent                       |    | EventContext                |
96 //  |  - Registry of event categories  |    |  - One track event instance |
97 //  '----------------------------------'    '-----------------------------'
98 //              |                                            |
99 //              |                                            | look up
100 //              | is                                         | interning ids
101 //              V                                            V
102 //  .----------------------------------.    .-----------------------------.
103 //  | internal::TrackEventDataSource   |    | TrackEventInternedDataIndex |
104 //  | - Perfetto data source           |    | - Corresponds to a field in |
105 //  | - Has TrackEventIncrementalState |    |   in interned_data.proto    |
106 //  '----------------------------------'    '-----------------------------'
107 //              |                  |                         ^
108 //              |                  |       owns (1:many)     |
109 //              | write event      '-------------------------'
110 //              V
111 //  .----------------------------------.
112 //  | internal::TrackEventInternal     |
113 //  | - Outlined code to serialize     |
114 //  |   one track event                |
115 //  '----------------------------------'
116 //
117 
118 // DEPRECATED: Please use PERFETTO_DEFINE_CATEGORIES_IN_NAMESPACE to implement
119 // multiple track event category sets in one program.
120 //
121 // Each compilation unit can be in exactly one track event namespace,
122 // allowing the overall program to use multiple track event data sources and
123 // category lists if necessary. Use this macro to select the namespace for the
124 // current compilation unit.
125 //
126 // If the program uses multiple track event namespaces, category & track event
127 // registration (see quickstart above) needs to happen for both namespaces
128 // separately.
129 
130 #ifndef PERFETTO_TRACK_EVENT_NAMESPACE
131 #define PERFETTO_TRACK_EVENT_NAMESPACE perfetto_track_event
132 #endif
133 
134 // Deprecated; see perfetto::Category().
135 #define PERFETTO_CATEGORY(name) \
136   ::perfetto::Category { #name }
137 
138 // Internal helpers for determining if a given category is defined at build or
139 // runtime.
140 namespace PERFETTO_TRACK_EVENT_NAMESPACE {
141 namespace internal {
142 
143 // By default no statically defined categories are dynamic, but this can be
144 // overridden with PERFETTO_DEFINE_TEST_CATEGORY_PREFIXES.
145 template <typename... T>
IsDynamicCategory(const char *)146 constexpr bool IsDynamicCategory(const char*) {
147   return false;
148 }
149 
150 // Explicitly dynamic categories are always dynamic.
IsDynamicCategory(const::perfetto::DynamicCategory &)151 constexpr bool IsDynamicCategory(const ::perfetto::DynamicCategory&) {
152   return true;
153 }
154 
155 }  // namespace internal
156 }  // namespace PERFETTO_TRACK_EVENT_NAMESPACE
157 
158 // Normally all categories are defined statically at build-time (see
159 // PERFETTO_DEFINE_CATEGORIES). However, some categories are only used for
160 // testing, and we shouldn't publish them to the tracing service or include them
161 // in a production binary. Use this macro to define a list of prefixes for these
162 // types of categories. Note that trace points using these categories will be
163 // slightly less efficient compared to regular trace points.
164 #define PERFETTO_DEFINE_TEST_CATEGORY_PREFIXES(...)                       \
165   namespace PERFETTO_TRACK_EVENT_NAMESPACE {                              \
166   namespace internal {                                                    \
167   template <>                                                             \
168   constexpr bool IsDynamicCategory(const char* name) {                    \
169     return ::perfetto::internal::IsStringInPrefixList(name, __VA_ARGS__); \
170   }                                                                       \
171   } /* namespace internal */                                              \
172   } /* namespace PERFETTO_TRACK_EVENT_NAMESPACE */                        \
173   PERFETTO_INTERNAL_SWALLOW_SEMICOLON()
174 
175 // Register the set of available categories by passing a list of categories to
176 // this macro: perfetto::Category("cat1"), perfetto::Category("cat2"), ...
177 // `ns` is the name of the namespace in which the categories should be declared.
178 // `attrs` are linkage attributes for the underlying data source. See
179 // PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS_WITH_ATTRS.
180 //
181 // Implementation note: the extra namespace (PERFETTO_TRACK_EVENT_NAMESPACE) is
182 // kept here only for backward compatibility.
183 #define PERFETTO_DEFINE_CATEGORIES_IN_NAMESPACE_WITH_ATTRS(ns, attrs, ...) \
184   namespace ns {                                                           \
185   namespace PERFETTO_TRACK_EVENT_NAMESPACE {                               \
186   /* The list of category names */                                         \
187   PERFETTO_INTERNAL_DECLARE_CATEGORIES(attrs, __VA_ARGS__)                 \
188   /* The track event data source for this set of categories */             \
189   PERFETTO_INTERNAL_DECLARE_TRACK_EVENT_DATA_SOURCE(attrs);                \
190   } /* namespace PERFETTO_TRACK_EVENT_NAMESPACE  */                        \
191   using PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent;                        \
192   } /* namespace ns */                                                     \
193   PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS_WITH_ATTRS(                  \
194       attrs, ns::PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent,               \
195       ::perfetto::internal::TrackEventDataSourceTraits)
196 
197 // Register the set of available categories by passing a list of categories to
198 // this macro: perfetto::Category("cat1"), perfetto::Category("cat2"), ...
199 // `ns` is the name of the namespace in which the categories should be declared.
200 #define PERFETTO_DEFINE_CATEGORIES_IN_NAMESPACE(ns, ...) \
201   PERFETTO_DEFINE_CATEGORIES_IN_NAMESPACE_WITH_ATTRS(    \
202       ns, PERFETTO_COMPONENT_EXPORT, __VA_ARGS__)
203 
204 // Make categories in a given namespace the default ones used by track events
205 // for the current translation unit. Can only be used *once* in a given global
206 // or namespace scope.
207 #define PERFETTO_USE_CATEGORIES_FROM_NAMESPACE(ns)                         \
208   namespace PERFETTO_TRACK_EVENT_NAMESPACE {                               \
209   using ::ns::PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent;                  \
210   namespace internal {                                                     \
211   using ::ns::PERFETTO_TRACK_EVENT_NAMESPACE::internal::kCategoryRegistry; \
212   using ::ns::PERFETTO_TRACK_EVENT_NAMESPACE::internal::                   \
213       kConstExprCategoryRegistry;                                          \
214   } /* namespace internal */                                               \
215   } /* namespace PERFETTO_TRACK_EVENT_NAMESPACE */                         \
216   PERFETTO_INTERNAL_SWALLOW_SEMICOLON()
217 
218 // Make categories in a given namespace the default ones used by track events
219 // for the current block scope. Can only be used in a function or block scope.
220 #define PERFETTO_USE_CATEGORIES_FROM_NAMESPACE_SCOPED(ns) \
221   namespace PERFETTO_TRACK_EVENT_NAMESPACE = ns::PERFETTO_TRACK_EVENT_NAMESPACE
222 
223 // Register categories in the default (global) namespace. Warning: only one set
224 // of global categories can be defined in a single program. Create namespaced
225 // categories with PERFETTO_DEFINE_CATEGORIES_IN_NAMESPACE to work around this
226 // limitation.
227 #define PERFETTO_DEFINE_CATEGORIES(...)                           \
228   PERFETTO_DEFINE_CATEGORIES_IN_NAMESPACE(perfetto, __VA_ARGS__); \
229   PERFETTO_USE_CATEGORIES_FROM_NAMESPACE(perfetto)
230 
231 // Allocate storage for each category by using this macro once per track event
232 // namespace. `ns` is the name of the namespace in which the categories should
233 // be declared and `attrs` specify linkage attributes for the data source.
234 #define PERFETTO_TRACK_EVENT_STATIC_STORAGE_IN_NAMESPACE_WITH_ATTRS(ns, attrs) \
235   namespace ns {                                                               \
236   namespace PERFETTO_TRACK_EVENT_NAMESPACE {                                   \
237   PERFETTO_INTERNAL_CATEGORY_STORAGE(attrs)                                    \
238   PERFETTO_INTERNAL_DEFINE_TRACK_EVENT_DATA_SOURCE()                           \
239   } /* namespace PERFETTO_TRACK_EVENT_NAMESPACE */                             \
240   } /* namespace ns */                                                         \
241   PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS_WITH_ATTRS(                       \
242       attrs, ns::PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent,                   \
243       ::perfetto::internal::TrackEventDataSourceTraits)
244 
245 // Allocate storage for each category by using this macro once per track event
246 // namespace.
247 #define PERFETTO_TRACK_EVENT_STATIC_STORAGE_IN_NAMESPACE(ns)   \
248   PERFETTO_TRACK_EVENT_STATIC_STORAGE_IN_NAMESPACE_WITH_ATTRS( \
249       ns, PERFETTO_COMPONENT_EXPORT)
250 
251 // Allocate storage for each category by using this macro once per track event
252 // namespace.
253 #define PERFETTO_TRACK_EVENT_STATIC_STORAGE() \
254   PERFETTO_TRACK_EVENT_STATIC_STORAGE_IN_NAMESPACE(perfetto)
255 
256 // Ignore GCC warning about a missing argument for a variadic macro parameter.
257 #if defined(__GNUC__) || defined(__clang__)
258 #pragma GCC system_header
259 #endif
260 
261 // Begin a slice under |category| with the title |name|. Both strings must be
262 // static constants. The track event is only recorded if |category| is enabled
263 // for a tracing session.
264 //
265 // The slice is thread-scoped (i.e., written to the default track of the current
266 // thread) unless overridden with a custom track object (see Track).
267 //
268 // |name| must be a string with static lifetime (i.e., the same
269 // address must not be used for a different event name in the future). If you
270 // want to use a dynamically allocated name, do this:
271 //
272 //  TRACE_EVENT("category", nullptr, [&](perfetto::EventContext ctx) {
273 //    ctx.event()->set_name(dynamic_name);
274 //  });
275 //
276 // The following optional arguments can be passed to `TRACE_EVENT` to add extra
277 // information to events:
278 //
279 // TRACE_EVENT("cat", "name"[, track][, timestamp]
280 //                          [, "debug_name1", debug_value1]
281 //                          [, "debug_name2", debug_value2]
282 //                          ...
283 //                          [, "debug_nameN", debug_valueN]
284 //                          [, lambda]);
285 //
286 // Some examples of valid combinations:
287 //
288 // 1. A lambda for writing custom TrackEvent fields:
289 //
290 //   TRACE_EVENT("category", "Name", [&](perfetto::EventContext ctx) {
291 //     ctx.event()->set_custom_value(...);
292 //   });
293 //
294 // 2. A timestamp and a lambda:
295 //
296 //   TRACE_EVENT("category", "Name", time_in_nanoseconds,
297 //       [&](perfetto::EventContext ctx) {
298 //     ctx.event()->set_custom_value(...);
299 //   });
300 //
301 //   |time_in_nanoseconds| should be an uint64_t by default. To support custom
302 //   timestamp types,
303 //   |perfetto::TraceTimestampTraits<T>::ConvertTimestampToTraceTimeNs|
304 //   should be defined. See |ConvertTimestampToTraceTimeNs| for more details.
305 //
306 // 3. Arbitrary number of debug annotations:
307 //
308 //   TRACE_EVENT("category", "Name", "arg", value);
309 //   TRACE_EVENT("category", "Name", "arg", value, "arg2", value2);
310 //   TRACE_EVENT("category", "Name", "arg", value, "arg2", value2,
311 //                                   "arg3", value3);
312 //
313 //   See |TracedValue| for recording custom types as debug annotations.
314 //
315 // 4. Arbitrary number of debug annotations and a lambda:
316 //
317 //   TRACE_EVENT("category", "Name", "arg", value,
318 //       [&](perfetto::EventContext ctx) {
319 //     ctx.event()->set_custom_value(...);
320 //   });
321 //
322 // 5. An overridden track:
323 //
324 //   TRACE_EVENT("category", "Name", perfetto::Track(1234));
325 //
326 //   See |Track| for other types of tracks which may be used.
327 //
328 // 6. A track and a lambda:
329 //
330 //   TRACE_EVENT("category", "Name", perfetto::Track(1234),
331 //       [&](perfetto::EventContext ctx) {
332 //     ctx.event()->set_custom_value(...);
333 //   });
334 //
335 // 7. A track and a timestamp:
336 //
337 //   TRACE_EVENT("category", "Name", perfetto::Track(1234),
338 //       time_in_nanoseconds);
339 //
340 // 8. A track, a timestamp and a lambda:
341 //
342 //   TRACE_EVENT("category", "Name", perfetto::Track(1234),
343 //       time_in_nanoseconds, [&](perfetto::EventContext ctx) {
344 //     ctx.event()->set_custom_value(...);
345 //   });
346 //
347 // 9. A track and an arbitrary number of debug annotions:
348 //
349 //   TRACE_EVENT("category", "Name", perfetto::Track(1234),
350 //               "arg", value);
351 //   TRACE_EVENT("category", "Name", perfetto::Track(1234),
352 //               "arg", value, "arg2", value2);
353 //
354 #define TRACE_EVENT_BEGIN(category, name, ...)                  \
355   PERFETTO_INTERNAL_TRACK_EVENT(                                \
356       category, ::perfetto::internal::DecayEventNameType(name), \
357       ::perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_BEGIN, ##__VA_ARGS__)
358 
359 // End a slice under |category|.
360 #define TRACE_EVENT_END(category, ...) \
361   PERFETTO_INTERNAL_TRACK_EVENT(       \
362       category, /*name=*/nullptr,      \
363       ::perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_END, ##__VA_ARGS__)
364 
365 // Begin a slice which gets automatically closed when going out of scope.
366 #define TRACE_EVENT(category, name, ...) \
367   PERFETTO_INTERNAL_SCOPED_TRACK_EVENT(  \
368       category, ::perfetto::internal::DecayEventNameType(name), ##__VA_ARGS__)
369 
370 // Emit a slice which has zero duration.
371 #define TRACE_EVENT_INSTANT(category, name, ...)                \
372   PERFETTO_INTERNAL_TRACK_EVENT(                                \
373       category, ::perfetto::internal::DecayEventNameType(name), \
374       ::perfetto::protos::pbzero::TrackEvent::TYPE_INSTANT, ##__VA_ARGS__)
375 
376 // Efficiently determine if the given static or dynamic trace category or
377 // category group is enabled for tracing.
378 #define TRACE_EVENT_CATEGORY_ENABLED(category) \
379   PERFETTO_INTERNAL_CATEGORY_ENABLED(category)
380 
381 // Time-varying numeric data can be recorded with the TRACE_COUNTER macro:
382 //
383 //   TRACE_COUNTER("cat", counter_track[, timestamp], value);
384 //
385 // For example, to record a single value for a counter called "MyCounter":
386 //
387 //   TRACE_COUNTER("category", "MyCounter", 1234.5);
388 //
389 // This data is displayed as a counter track in the Perfetto UI.
390 //
391 // Both integer and floating point counter values are supported. Counters can
392 // also be annotated with additional information such as units, for example, for
393 // tracking the rendering framerate in terms of frames per second or "fps":
394 //
395 //   TRACE_COUNTER("category", perfetto::CounterTrack("Framerate", "fps"), 120);
396 //
397 // As another example, a memory counter that records bytes but accepts samples
398 // as kilobytes (to reduce trace binary size) can be defined like this:
399 //
400 //   perfetto::CounterTrack memory_track = perfetto::CounterTrack("Memory")
401 //       .set_unit("bytes")
402 //       .set_multiplier(1024);
403 //   TRACE_COUNTER("category", memory_track, 4 /* = 4096 bytes */);
404 //
405 // See /protos/perfetto/trace/track_event/counter_descriptor.proto
406 // for the full set of attributes for a counter track.
407 //
408 // To record a counter value at a specific point in time (instead of the current
409 // time), you can pass in a custom timestamp:
410 //
411 //   // First record the current time and counter value.
412 //   uint64_t timestamp = perfetto::TrackEvent::GetTraceTimeNs();
413 //   int64_t value = 1234;
414 //
415 //   // Later, emit a sample at that point in time.
416 //   TRACE_COUNTER("category", "MyCounter", timestamp, value);
417 //
418 #define TRACE_COUNTER(category, track, ...)                 \
419   PERFETTO_INTERNAL_TRACK_EVENT(                            \
420       category, /*name=*/nullptr,                           \
421       ::perfetto::protos::pbzero::TrackEvent::TYPE_COUNTER, \
422       ::perfetto::CounterTrack(track), ##__VA_ARGS__)
423 
424 // TODO(skyostil): Add flow events.
425 
426 #endif  // INCLUDE_PERFETTO_TRACING_TRACK_EVENT_H_
427