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