Flutter Engine
trace_event.h
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
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 FLUTTER_FML_TRACE_EVENT_H_
6 #define FLUTTER_FML_TRACE_EVENT_H_
7 
8 #include <functional>
9 
10 #include "flutter/fml/build_config.h"
11 
12 #if defined(OS_FUCHSIA)
13 
14 // Forward to the system tracing mechanism on Fuchsia.
15 
16 #include <lib/trace/event.h>
17 
18 // TODO(DNO-448): This is disabled because the Fuchsia counter id json parsing
19 // only handles ints whereas this can produce ints or strings.
20 #define FML_TRACE_COUNTER(a, b, c, arg1, ...) \
21  ::fml::tracing::TraceCounterNopHACK((a), (b), (c), (arg1), __VA_ARGS__);
22 
23 #define FML_TRACE_EVENT(a, b, args...) TRACE_DURATION(a, b)
24 
25 #define TRACE_EVENT0(a, b) TRACE_DURATION(a, b)
26 #define TRACE_EVENT1(a, b, c, d) TRACE_DURATION(a, b, c, d)
27 #define TRACE_EVENT2(a, b, c, d, e, f) TRACE_DURATION(a, b, c, d, e, f)
28 #define TRACE_EVENT_ASYNC_BEGIN0(a, b, c) TRACE_ASYNC_BEGIN(a, b, c)
29 #define TRACE_EVENT_ASYNC_END0(a, b, c) TRACE_ASYNC_END(a, b, c)
30 #define TRACE_EVENT_ASYNC_BEGIN1(a, b, c, d, e) TRACE_ASYNC_BEGIN(a, b, c, d, e)
31 #define TRACE_EVENT_ASYNC_END1(a, b, c, d, e) TRACE_ASYNC_END(a, b, c, d, e)
32 #define TRACE_EVENT_INSTANT0(a, b) TRACE_INSTANT(a, b, TRACE_SCOPE_THREAD)
33 #define TRACE_EVENT_INSTANT1(a, b, k1, v1) \
34  TRACE_INSTANT(a, b, TRACE_SCOPE_THREAD, k1, v1)
35 #define TRACE_EVENT_INSTANT2(a, b, k1, v1, k2, v2) \
36  TRACE_INSTANT(a, b, TRACE_SCOPE_THREAD, k1, v1, k2, v2)
37 
38 #endif // defined(OS_FUCHSIA)
39 
40 #include <cstddef>
41 #include <cstdint>
42 #include <string>
43 #include <type_traits>
44 #include <vector>
45 
46 #include "flutter/fml/macros.h"
47 #include "flutter/fml/time/time_point.h"
48 #include "third_party/dart/runtime/include/dart_tools_api.h"
49 
50 #if (FLUTTER_RELEASE && !defined(OS_FUCHSIA) && !defined(FML_OS_ANDROID))
51 #define FLUTTER_TIMELINE_ENABLED 0
52 #else
53 #define FLUTTER_TIMELINE_ENABLED 1
54 #endif
55 
56 #if !defined(OS_FUCHSIA)
57 #ifndef TRACE_EVENT_HIDE_MACROS
58 
59 #define __FML__TOKEN_CAT__(x, y) x##y
60 #define __FML__TOKEN_CAT__2(x, y) __FML__TOKEN_CAT__(x, y)
61 #define __FML__AUTO_TRACE_END(name) \
62  ::fml::tracing::ScopedInstantEnd __FML__TOKEN_CAT__2(__trace_end_, \
63  __LINE__)(name);
64 
65 // This macro has the FML_ prefix so that it does not collide with the macros
66 // from lib/trace/event.h on Fuchsia.
67 //
68 // TODO(chinmaygarde): All macros here should have the FML prefix.
69 #define FML_TRACE_COUNTER(category_group, name, counter_id, arg1, ...) \
70  ::fml::tracing::TraceCounter((category_group), (name), (counter_id), (arg1), \
71  __VA_ARGS__);
72 
73 // Avoid using the same `name` and `argX_name` for nested traces, which can
74 // lead to double free errors. E.g. the following code should be avoided:
75 //
76 // ```cpp
77 // {
78 // TRACE_EVENT1("flutter", "Foo::Bar", "count", "initial_count_value");
79 // ...
80 // TRACE_EVENT_INSTANT1("flutter", "Foo::Bar",
81 // "count", "updated_count_value");
82 // }
83 // ```
84 //
85 // Instead, either use different `name` or `arg1` parameter names.
86 #define FML_TRACE_EVENT(category_group, name, ...) \
87  ::fml::tracing::TraceEvent((category_group), (name), __VA_ARGS__); \
88  __FML__AUTO_TRACE_END(name)
89 
90 #define TRACE_EVENT0(category_group, name) \
91  ::fml::tracing::TraceEvent0(category_group, name); \
92  __FML__AUTO_TRACE_END(name)
93 
94 #define TRACE_EVENT1(category_group, name, arg1_name, arg1_val) \
95  ::fml::tracing::TraceEvent1(category_group, name, arg1_name, arg1_val); \
96  __FML__AUTO_TRACE_END(name)
97 
98 #define TRACE_EVENT2(category_group, name, arg1_name, arg1_val, arg2_name, \
99  arg2_val) \
100  ::fml::tracing::TraceEvent2(category_group, name, arg1_name, arg1_val, \
101  arg2_name, arg2_val); \
102  __FML__AUTO_TRACE_END(name)
103 
104 #define TRACE_EVENT_ASYNC_BEGIN0(category_group, name, id) \
105  ::fml::tracing::TraceEventAsyncBegin0(category_group, name, id);
106 
107 #define TRACE_EVENT_ASYNC_END0(category_group, name, id) \
108  ::fml::tracing::TraceEventAsyncEnd0(category_group, name, id);
109 
110 #define TRACE_EVENT_ASYNC_BEGIN1(category_group, name, id, arg1_name, \
111  arg1_val) \
112  ::fml::tracing::TraceEventAsyncBegin1(category_group, name, id, arg1_name, \
113  arg1_val);
114 
115 #define TRACE_EVENT_ASYNC_END1(category_group, name, id, arg1_name, arg1_val) \
116  ::fml::tracing::TraceEventAsyncEnd1(category_group, name, id, arg1_name, \
117  arg1_val);
118 
119 #define TRACE_EVENT_INSTANT0(category_group, name) \
120  ::fml::tracing::TraceEventInstant0(category_group, name);
121 
122 #define TRACE_EVENT_INSTANT1(category_group, name, arg1_name, arg1_val) \
123  ::fml::tracing::TraceEventInstant1(category_group, name, arg1_name, arg1_val);
124 
125 #define TRACE_EVENT_INSTANT2(category_group, name, arg1_name, arg1_val, \
126  arg2_name, arg2_val) \
127  ::fml::tracing::TraceEventInstant2(category_group, name, arg1_name, \
128  arg1_val, arg2_name, arg2_val);
129 
130 #define TRACE_FLOW_BEGIN(category, name, id) \
131  ::fml::tracing::TraceEventFlowBegin0(category, name, id);
132 
133 #define TRACE_FLOW_STEP(category, name, id) \
134  ::fml::tracing::TraceEventFlowStep0(category, name, id);
135 
136 #define TRACE_FLOW_END(category, name, id) \
137  ::fml::tracing::TraceEventFlowEnd0(category, name, id);
138 
139 #endif // TRACE_EVENT_HIDE_MACROS
140 #endif // !defined(OS_FUCHSIA)
141 
142 namespace fml {
143 namespace tracing {
144 
145 using TraceArg = const char*;
146 using TraceIDArg = int64_t;
147 
148 void TraceSetAllowlist(const std::vector<std::string>& allowlist);
149 
150 typedef void (*TimelineEventHandler)(const char*,
151  int64_t,
152  int64_t,
153  Dart_Timeline_Event_Type,
154  intptr_t,
155  const char**,
156  const char**);
157 
158 using TimelineMicrosSource = int64_t (*)();
159 
161 
163 
165 
166 int64_t TraceGetTimelineMicros();
167 
168 void TraceTimelineEvent(TraceArg category_group,
169  TraceArg name,
170  int64_t timestamp_micros,
171  TraceIDArg id,
172  Dart_Timeline_Event_Type type,
173  const std::vector<const char*>& names,
174  const std::vector<std::string>& values);
175 
176 void TraceTimelineEvent(TraceArg category_group,
177  TraceArg name,
178  TraceIDArg id,
179  Dart_Timeline_Event_Type type,
180  const std::vector<const char*>& names,
181  const std::vector<std::string>& values);
182 
183 inline std::string TraceToString(const char* string) {
184  return std::string{string};
185 }
186 
187 inline std::string TraceToString(std::string string) {
188  return string;
189 }
190 
191 inline std::string TraceToString(TimePoint point) {
192  return std::to_string(point.ToEpochDelta().ToNanoseconds());
193 }
194 
196 std::string TraceToString(T string) {
197  return std::to_string(string);
198 }
199 
200 inline void SplitArgumentsCollect(std::vector<const char*>& keys,
201  std::vector<std::string>& values) {}
202 
203 template <typename Key, typename Value, typename... Args>
204 void SplitArgumentsCollect(std::vector<const char*>& keys,
205  std::vector<std::string>& values,
206  Key key,
207  Value value,
208  Args... args) {
209  keys.emplace_back(key);
210  values.emplace_back(TraceToString(value));
211  SplitArgumentsCollect(keys, values, args...);
212 }
213 
214 inline std::pair<std::vector<const char*>, std::vector<std::string>>
216  return {};
217 }
218 
219 template <typename Key, typename Value, typename... Args>
220 std::pair<std::vector<const char*>, std::vector<std::string>>
221 SplitArguments(Key key, Value value, Args... args) {
222  std::vector<const char*> keys;
223  std::vector<std::string> values;
224  SplitArgumentsCollect(keys, values, key, value, args...);
225  return std::make_pair(std::move(keys), std::move(values));
226 }
227 
228 size_t TraceNonce();
229 
230 template <typename... Args>
231 void TraceCounter(TraceArg category,
232  TraceArg name,
233  TraceIDArg identifier,
234  Args... args) {
235 #if FLUTTER_TIMELINE_ENABLED
236  auto split = SplitArguments(args...);
237  TraceTimelineEvent(category, name, identifier, Dart_Timeline_Event_Counter,
238  split.first, split.second);
239 #endif // FLUTTER_TIMELINE_ENABLED
240 }
241 
242 // HACK: Used to NOP FML_TRACE_COUNTER macro without triggering unused var
243 // warnings at usage sites.
244 template <typename... Args>
246  TraceArg name,
247  TraceIDArg identifier,
248  Args... args) {}
249 
250 template <typename... Args>
251 void TraceEvent(TraceArg category, TraceArg name, Args... args) {
252 #if FLUTTER_TIMELINE_ENABLED
253  auto split = SplitArguments(args...);
254  TraceTimelineEvent(category, name, 0, Dart_Timeline_Event_Begin, split.first,
255  split.second);
256 #endif // FLUTTER_TIMELINE_ENABLED
257 }
258 
259 void TraceEvent0(TraceArg category_group, TraceArg name);
260 
261 void TraceEvent1(TraceArg category_group,
262  TraceArg name,
263  TraceArg arg1_name,
264  TraceArg arg1_val);
265 
266 void TraceEvent2(TraceArg category_group,
267  TraceArg name,
268  TraceArg arg1_name,
269  TraceArg arg1_val,
270  TraceArg arg2_name,
271  TraceArg arg2_val);
272 
273 void TraceEventEnd(TraceArg name);
274 
275 template <typename... Args>
276 void TraceEventAsyncComplete(TraceArg category_group,
277  TraceArg name,
278  TimePoint begin,
279  TimePoint end,
280  Args... args) {
281 #if FLUTTER_TIMELINE_ENABLED
282  auto identifier = TraceNonce();
283  const auto split = SplitArguments(args...);
284 
285  if (begin > end) {
286  std::swap(begin, end);
287  }
288 
289  const int64_t begin_micros = begin.ToEpochDelta().ToMicroseconds();
290  const int64_t end_micros = end.ToEpochDelta().ToMicroseconds();
291 
292  TraceTimelineEvent(category_group, // group
293  name, // name
294  begin_micros, // timestamp_micros
295  identifier, // identifier
296  Dart_Timeline_Event_Async_Begin, // type
297  split.first, // names
298  split.second // values
299  );
300 
301  TraceTimelineEvent(category_group, // group
302  name, // name
303  end_micros, // timestamp_micros
304  identifier, // identifier
305  Dart_Timeline_Event_Async_End, // type
306  split.first, // names
307  split.second // values
308  );
309 #endif // FLUTTER_TIMELINE_ENABLED
310 }
311 
312 void TraceEventAsyncBegin0(TraceArg category_group,
313  TraceArg name,
314  TraceIDArg id);
315 
316 void TraceEventAsyncEnd0(TraceArg category_group, TraceArg name, TraceIDArg id);
317 
318 void TraceEventAsyncBegin1(TraceArg category_group,
319  TraceArg name,
320  TraceIDArg id,
321  TraceArg arg1_name,
322  TraceArg arg1_val);
323 
324 void TraceEventAsyncEnd1(TraceArg category_group,
325  TraceArg name,
326  TraceIDArg id,
327  TraceArg arg1_name,
328  TraceArg arg1_val);
329 
330 void TraceEventInstant0(TraceArg category_group, TraceArg name);
331 
332 void TraceEventInstant1(TraceArg category_group,
333  TraceArg name,
334  TraceArg arg1_name,
335  TraceArg arg1_val);
336 
337 void TraceEventInstant2(TraceArg category_group,
338  TraceArg name,
339  TraceArg arg1_name,
340  TraceArg arg1_val,
341  TraceArg arg2_name,
342  TraceArg arg2_val);
343 
344 void TraceEventFlowBegin0(TraceArg category_group,
345  TraceArg name,
346  TraceIDArg id);
347 
348 void TraceEventFlowStep0(TraceArg category_group, TraceArg name, TraceIDArg id);
349 
350 void TraceEventFlowEnd0(TraceArg category_group, TraceArg name, TraceIDArg id);
351 
353  public:
354  explicit ScopedInstantEnd(const char* str) : label_(str) {}
355 
357 
358  private:
359  const char* label_;
360 
361  FML_DISALLOW_COPY_AND_ASSIGN(ScopedInstantEnd);
362 };
363 
364 // A move-only utility object that creates a new flow with a unique ID and
365 // automatically ends it when it goes out of scope. When tracing using multiple
366 // overlapping flows, it often gets hard to make sure to end the flow
367 // (especially with early returns), or, end/step on the wrong flow. This
368 // leads to corrupted or missing traces in the UI.
369 class TraceFlow {
370  public:
371  explicit TraceFlow(const char* label) : label_(label), nonce_(TraceNonce()) {
372  TraceEventFlowBegin0("flutter", label_, nonce_);
373  }
374 
375  ~TraceFlow() { End(label_); }
376 
377  TraceFlow(TraceFlow&& other) : label_(other.label_), nonce_(other.nonce_) {
378  other.nonce_ = 0;
379  }
380 
381  void Step(const char* label = nullptr) const {
382  TraceEventFlowStep0("flutter", label ? label : label_, nonce_);
383  }
384 
385  void End(const char* label = nullptr) {
386  if (nonce_ != 0) {
387  TraceEventFlowEnd0("flutter", label ? label : label_, nonce_);
388  nonce_ = 0;
389  }
390  }
391 
392  private:
393  const char* label_;
394  size_t nonce_;
395 
397 };
398 
399 } // namespace tracing
400 } // namespace fml
401 
402 #endif // FLUTTER_FML_TRACE_EVENT_H_
int64_t TraceGetTimelineMicros()
Definition: trace_event.cc:323
G_BEGIN_DECLS FlValue * args
void TraceEventInstant1(TraceArg category_group, TraceArg name, TraceArg arg1_name, TraceArg arg1_val)
Definition: trace_event.cc:391
void TraceEventAsyncEnd0(TraceArg category_group, TraceArg name, TraceIDArg id)
Definition: trace_event.cc:373
void TraceCounter(TraceArg category, TraceArg name, TraceIDArg identifier, Args... args)
Definition: trace_event.h:231
bool TraceHasTimelineEventHandler()
Definition: trace_event.cc:319
void TraceEventEnd(TraceArg name)
Definition: trace_event.cc:362
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data observatory The hostname IP address on which the Dart Observatory should be served If not defaults to or::depending on whether ipv6 is specified disable Disable the Dart Observatory The observatory is never available in release mode Bind to the IPv6 localhost address for the Dart Observatory Ignored if observatory host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets Path to the Flutter assets directory enable service port Allow the VM service to fallback to automatic port selection if binding to a specified port fails trace Trace early application lifecycle Automatically switches to an endless trace buffer trace skia allowlist
Definition: switches.h:143
int64_t(*)() TimelineMicrosSource
Definition: trace_event.h:158
TraceFlow(TraceFlow &&other)
Definition: trace_event.h:377
enum flutter::testing::@1969::KeyboardChange::Type type
TraceFlow(const char *label)
Definition: trace_event.h:371
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
void TraceEventFlowBegin0(TraceArg category_group, TraceArg name, TraceIDArg id)
Definition: trace_event.cc:403
TimeDelta ToEpochDelta() const
Definition: time_point.h:52
void TraceTimelineEvent(TraceArg category_group, TraceArg name, int64_t timestamp_micros, TraceIDArg identifier, Dart_Timeline_Event_Type type, const std::vector< const char *> &c_names, const std::vector< std::string > &values)
Definition: trace_event.cc:333
void swap(scoped_nsprotocol< C > &p1, scoped_nsprotocol< C > &p2)
Definition: ascii_trie.cc:9
void TraceEvent1(TraceArg category_group, TraceArg name, TraceArg arg1_name, TraceArg arg1_val)
Definition: trace_event.cc:350
const char * TraceArg
Definition: trace_event.h:145
void TraceEventFlowEnd0(TraceArg category_group, TraceArg name, TraceIDArg id)
Definition: trace_event.cc:411
void TraceEventInstant0(TraceArg category_group, TraceArg name)
Definition: trace_event.cc:389
uint8_t value
std::pair< std::vector< const char * >, std::vector< std::string > > SplitArguments()
Definition: trace_event.h:215
constexpr int64_t ToMicroseconds() const
Definition: time_delta.h:62
void TraceEventAsyncEnd1(TraceArg category_group, TraceArg name, TraceIDArg id, TraceArg arg1_name, TraceArg arg1_val)
Definition: trace_event.cc:383
void End(const char *label=nullptr)
Definition: trace_event.h:385
void Step(const char *label=nullptr) const
Definition: trace_event.h:381
void TraceEventFlowStep0(TraceArg category_group, TraceArg name, TraceIDArg id)
Definition: trace_event.cc:407
void(* TimelineEventHandler)(const char *, int64_t, int64_t, Dart_Timeline_Event_Type, intptr_t, const char **, const char **)
Definition: trace_event.h:150
void TraceSetTimelineEventHandler(TimelineEventHandler handler)
Definition: trace_event.cc:317
void TraceCounterNopHACK(TraceArg category, TraceArg name, TraceIDArg identifier, Args... args)
Definition: trace_event.h:245
ScopedInstantEnd(const char *str)
Definition: trace_event.h:354
constexpr int64_t ToNanoseconds() const
Definition: time_delta.h:61
int64_t TraceIDArg
Definition: trace_event.h:146
void TraceSetAllowlist(const std::vector< std::string > &allowlist)
Definition: trace_event.cc:315
void TraceSetTimelineMicrosSource(TimelineMicrosSource source)
Definition: trace_event.cc:327
void TraceEvent2(TraceArg category_group, TraceArg name, TraceArg arg1_name, TraceArg arg1_val, TraceArg arg2_name, TraceArg arg2_val)
Definition: trace_event.cc:355
void TraceEventAsyncBegin0(TraceArg category_group, TraceArg name, TraceIDArg id)
Definition: trace_event.cc:369
void TraceEvent(TraceArg category, TraceArg name, Args... args)
Definition: trace_event.h:251
std::string TraceToString(const char *string)
Definition: trace_event.h:183
void SplitArgumentsCollect(std::vector< const char *> &keys, std::vector< std::string > &values)
Definition: trace_event.h:200
void TraceEventInstant2(TraceArg category_group, TraceArg name, TraceArg arg1_name, TraceArg arg1_val, TraceArg arg2_name, TraceArg arg2_val)
Definition: trace_event.cc:396
void TraceEventAsyncComplete(TraceArg category_group, TraceArg name, TimePoint begin, TimePoint end)
Definition: trace_event.cc:364
size_t TraceNonce()
Definition: trace_event.cc:329
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: macros.h:27
void TraceEvent0(TraceArg category_group, TraceArg name)
Definition: trace_event.cc:348
void TraceEventAsyncBegin1(TraceArg category_group, TraceArg name, TraceIDArg id, TraceArg arg1_name, TraceArg arg1_val)
Definition: trace_event.cc:377