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 PERFETTO_INTERNAL_DEFINE_TRACK_EVENT_DATA_SOURCE() \
191 } /* namespace PERFETTO_TRACK_EVENT_NAMESPACE */ \
192 PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS( \
193 PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent, \
194 perfetto::internal::TrackEventDataSourceTraits)
195
196 // Ignore GCC warning about a missing argument for a variadic macro parameter.
197 #if defined(__GNUC__) || defined(__clang__)
198 #pragma GCC system_header
199 #endif
200
201 // Begin a slice under |category| with the title |name|. Both strings must be
202 // static constants. The track event is only recorded if |category| is enabled
203 // for a tracing session.
204 //
205 // The slice is thread-scoped (i.e., written to the default track of the current
206 // thread) unless overridden with a custom track object (see Track).
207 //
208 // |name| must be a string with static lifetime (i.e., the same
209 // address must not be used for a different event name in the future). If you
210 // want to use a dynamically allocated name, do this:
211 //
212 // TRACE_EVENT("category", nullptr, [&](perfetto::EventContext ctx) {
213 // ctx.event()->set_name(dynamic_name);
214 // });
215 //
216 // The following optional arguments can be passed to `TRACE_EVENT` to add extra
217 // information to events:
218 //
219 // TRACE_EVENT("cat", "name"[, track][, timestamp]
220 // [, "debug_name1", debug_value1]
221 // [, "debug_name2", debug_value2]
222 // ...
223 // [, "debug_nameN", debug_valueN]
224 // [, lambda]);
225 //
226 // Some examples of valid combinations:
227 //
228 // 1. A lambda for writing custom TrackEvent fields:
229 //
230 // TRACE_EVENT("category", "Name", [&](perfetto::EventContext ctx) {
231 // ctx.event()->set_custom_value(...);
232 // });
233 //
234 // 2. A timestamp and a lambda:
235 //
236 // TRACE_EVENT("category", "Name", time_in_nanoseconds,
237 // [&](perfetto::EventContext ctx) {
238 // ctx.event()->set_custom_value(...);
239 // });
240 //
241 // |time_in_nanoseconds| should be an uint64_t by default. To support custom
242 // timestamp types,
243 // |perfetto::TraceTimestampTraits<T>::ConvertTimestampToTraceTimeNs|
244 // should be defined. See |ConvertTimestampToTraceTimeNs| for more details.
245 //
246 // 3. Arbitrary number of debug annotations:
247 //
248 // TRACE_EVENT("category", "Name", "arg", value);
249 // TRACE_EVENT("category", "Name", "arg", value, "arg2", value2);
250 // TRACE_EVENT("category", "Name", "arg", value, "arg2", value2,
251 // "arg3", value3);
252 //
253 // See |TracedValue| for recording custom types as debug annotations.
254 //
255 // 4. Arbitrary number of debug annotations and a lambda:
256 //
257 // TRACE_EVENT("category", "Name", "arg", value,
258 // [&](perfetto::EventContext ctx) {
259 // ctx.event()->set_custom_value(...);
260 // });
261 //
262 // 5. An overridden track:
263 //
264 // TRACE_EVENT("category", "Name", perfetto::Track(1234));
265 //
266 // See |Track| for other types of tracks which may be used.
267 //
268 // 6. A track and a lambda:
269 //
270 // TRACE_EVENT("category", "Name", perfetto::Track(1234),
271 // [&](perfetto::EventContext ctx) {
272 // ctx.event()->set_custom_value(...);
273 // });
274 //
275 // 7. A track and a timestamp:
276 //
277 // TRACE_EVENT("category", "Name", perfetto::Track(1234),
278 // time_in_nanoseconds);
279 //
280 // 8. A track, a timestamp and a lambda:
281 //
282 // TRACE_EVENT("category", "Name", perfetto::Track(1234),
283 // time_in_nanoseconds, [&](perfetto::EventContext ctx) {
284 // ctx.event()->set_custom_value(...);
285 // });
286 //
287 // 9. A track and an arbitrary number of debug annotions:
288 //
289 // TRACE_EVENT("category", "Name", perfetto::Track(1234),
290 // "arg", value);
291 // TRACE_EVENT("category", "Name", perfetto::Track(1234),
292 // "arg", value, "arg2", value2);
293 //
294 #define TRACE_EVENT_BEGIN(category, name, ...) \
295 PERFETTO_INTERNAL_TRACK_EVENT( \
296 category, ::perfetto::internal::GetStaticString(name), \
297 ::perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_BEGIN, ##__VA_ARGS__)
298
299 // End a slice under |category|.
300 #define TRACE_EVENT_END(category, ...) \
301 PERFETTO_INTERNAL_TRACK_EVENT( \
302 category, /*name=*/nullptr, \
303 ::perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_END, ##__VA_ARGS__)
304
305 // Begin a slice which gets automatically closed when going out of scope.
306 #define TRACE_EVENT(category, name, ...) \
307 PERFETTO_INTERNAL_SCOPED_TRACK_EVENT(category, name, ##__VA_ARGS__)
308
309 // Emit a slice which has zero duration.
310 #define TRACE_EVENT_INSTANT(category, name, ...) \
311 PERFETTO_INTERNAL_TRACK_EVENT( \
312 category, ::perfetto::internal::GetStaticString(name), \
313 ::perfetto::protos::pbzero::TrackEvent::TYPE_INSTANT, ##__VA_ARGS__)
314
315 // Efficiently determine if the given static or dynamic trace category or
316 // category group is enabled for tracing.
317 #define TRACE_EVENT_CATEGORY_ENABLED(category) \
318 PERFETTO_INTERNAL_CATEGORY_ENABLED(category)
319
320 // Time-varying numeric data can be recorded with the TRACE_COUNTER macro:
321 //
322 // TRACE_COUNTER("cat", counter_track[, timestamp], value);
323 //
324 // For example, to record a single value for a counter called "MyCounter":
325 //
326 // TRACE_COUNTER("category", "MyCounter", 1234.5);
327 //
328 // This data is displayed as a counter track in the Perfetto UI.
329 //
330 // Both integer and floating point counter values are supported. Counters can
331 // also be annotated with additional information such as units, for example, for
332 // tracking the rendering framerate in terms of frames per second or "fps":
333 //
334 // TRACE_COUNTER("category", perfetto::CounterTrack("Framerate", "fps"), 120);
335 //
336 // As another example, a memory counter that records bytes but accepts samples
337 // as kilobytes (to reduce trace binary size) can be defined like this:
338 //
339 // perfetto::CounterTrack memory_track = perfetto::CounterTrack("Memory")
340 // .set_unit("bytes")
341 // .set_multiplier(1024);
342 // TRACE_COUNTER("category", memory_track, 4 /* = 4096 bytes */);
343 //
344 // See /protos/perfetto/trace/track_event/counter_descriptor.proto
345 // for the full set of attributes for a counter track.
346 //
347 // To record a counter value at a specific point in time (instead of the current
348 // time), you can pass in a custom timestamp:
349 //
350 // // First record the current time and counter value.
351 // uint64_t timestamp = perfetto::TrackEvent::GetTraceTimeNs();
352 // int64_t value = 1234;
353 //
354 // // Later, emit a sample at that point in time.
355 // TRACE_COUNTER("category", "MyCounter", timestamp, value);
356 //
357 #define TRACE_COUNTER(category, track, ...) \
358 PERFETTO_INTERNAL_TRACK_EVENT( \
359 category, /*name=*/nullptr, \
360 ::perfetto::protos::pbzero::TrackEvent::TYPE_COUNTER, \
361 ::perfetto::CounterTrack(track), ##__VA_ARGS__)
362
363 // TODO(skyostil): Add flow events.
364
365 #endif // INCLUDE_PERFETTO_TRACING_TRACK_EVENT_H_
366