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