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#include "flutter/fml/trace_event.h"
6
7#include <algorithm>
8#include <atomic>
9#include <utility>
10
11#include "flutter/fml/ascii_trie.h"
12#include "flutter/fml/build_config.h"
13#include "flutter/fml/logging.h"
14
15namespace fml {
16namespace tracing {
17
18#if FLUTTER_TIMELINE_ENABLED
19
20namespace {
21
22int64_t DefaultMicrosSource() {
23 return -1;
24}
25
26AsciiTrie gAllowlist;
27std::atomic<TimelineEventHandler> gTimelineEventHandler;
28std::atomic<TimelineMicrosSource> gTimelineMicrosSource = DefaultMicrosSource;
29
30inline void FlutterTimelineEvent(const char* label,
31 int64_t timestamp0,
32 int64_t timestamp1_or_async_id,
33 intptr_t flow_id_count,
34 const int64_t* flow_ids,
35 Dart_Timeline_Event_Type type,
36 intptr_t argument_count,
37 const char** argument_names,
38 const char** argument_values) {
39 TimelineEventHandler handler =
40 gTimelineEventHandler.load(m: std::memory_order_relaxed);
41 if (handler && gAllowlist.Query(argument: label)) {
42 handler(label, timestamp0, timestamp1_or_async_id, flow_id_count, flow_ids,
43 type, argument_count, argument_names, argument_values);
44 }
45}
46} // namespace
47
48void TraceSetAllowlist(const std::vector<std::string>& allowlist) {
49 gAllowlist.Fill(entries: allowlist);
50}
51
52void TraceSetTimelineEventHandler(TimelineEventHandler handler) {
53 gTimelineEventHandler = handler;
54}
55
56bool TraceHasTimelineEventHandler() {
57 return static_cast<bool>(
58 gTimelineEventHandler.load(m: std::memory_order_relaxed));
59}
60
61int64_t TraceGetTimelineMicros() {
62 return gTimelineMicrosSource.load()();
63}
64
65void TraceSetTimelineMicrosSource(TimelineMicrosSource source) {
66 gTimelineMicrosSource = source;
67}
68
69size_t TraceNonce() {
70 static std::atomic_size_t last_item;
71 return ++last_item;
72}
73
74void TraceTimelineEvent(TraceArg category_group,
75 TraceArg name,
76 int64_t timestamp_micros,
77 TraceIDArg identifier,
78 size_t flow_id_count,
79 const uint64_t* flow_ids,
80 Dart_Timeline_Event_Type type,
81 const std::vector<const char*>& c_names,
82 const std::vector<std::string>& values) {
83 const auto argument_count = std::min(a: c_names.size(), b: values.size());
84
85 std::vector<const char*> c_values;
86 c_values.resize(sz: argument_count, x: nullptr);
87
88 for (size_t i = 0; i < argument_count; i++) {
89 c_values[i] = values[i].c_str();
90 }
91
92 FlutterTimelineEvent(
93 label: name, // label
94 timestamp0: timestamp_micros, // timestamp0
95 timestamp1_or_async_id: identifier, // timestamp1_or_async_id
96 flow_id_count, // flow_id_count
97 flow_ids: reinterpret_cast<const int64_t*>(flow_ids), // flow_ids
98 type, // event type
99 argument_count, // argument_count
100 argument_names: const_cast<const char**>(c_names.data()), // argument_names
101 argument_values: c_values.data() // argument_values
102 );
103}
104
105void TraceTimelineEvent(TraceArg category_group,
106 TraceArg name,
107 TraceIDArg identifier,
108 size_t flow_id_count,
109 const uint64_t* flow_ids,
110 Dart_Timeline_Event_Type type,
111 const std::vector<const char*>& c_names,
112 const std::vector<std::string>& values) {
113 TraceTimelineEvent(category_group, // group
114 name, // name
115 timestamp_micros: gTimelineMicrosSource.load()(), // timestamp_micros
116 identifier, // identifier
117 flow_id_count, // flow_id_count
118 flow_ids, // flow_ids
119 type, // type
120 c_names, // names
121 values // values
122 );
123}
124
125void TraceEvent0(TraceArg category_group,
126 TraceArg name,
127 size_t flow_id_count,
128 const uint64_t* flow_ids) {
129 FlutterTimelineEvent(label: name, // label
130 timestamp0: gTimelineMicrosSource.load()(), // timestamp0
131 timestamp1_or_async_id: 0, // timestamp1_or_async_id
132 flow_id_count, // flow_id_count
133 flow_ids: reinterpret_cast<const int64_t*>(flow_ids), // flow_ids
134 type: Dart_Timeline_Event_Begin, // event type
135 argument_count: 0, // argument_count
136 argument_names: nullptr, // argument_names
137 argument_values: nullptr // argument_values
138 );
139}
140
141void TraceEvent1(TraceArg category_group,
142 TraceArg name,
143 size_t flow_id_count,
144 const uint64_t* flow_ids,
145 TraceArg arg1_name,
146 TraceArg arg1_val) {
147 const char* arg_names[] = {arg1_name};
148 const char* arg_values[] = {arg1_val};
149 FlutterTimelineEvent(label: name, // label
150 timestamp0: gTimelineMicrosSource.load()(), // timestamp0
151 timestamp1_or_async_id: 0, // timestamp1_or_async_id
152 flow_id_count, // flow_id_count
153 flow_ids: reinterpret_cast<const int64_t*>(flow_ids), // flow_ids
154 type: Dart_Timeline_Event_Begin, // event type
155 argument_count: 1, // argument_count
156 argument_names: arg_names, // argument_names
157 argument_values: arg_values // argument_values
158 );
159}
160
161void TraceEvent2(TraceArg category_group,
162 TraceArg name,
163 size_t flow_id_count,
164 const uint64_t* flow_ids,
165 TraceArg arg1_name,
166 TraceArg arg1_val,
167 TraceArg arg2_name,
168 TraceArg arg2_val) {
169 const char* arg_names[] = {arg1_name, arg2_name};
170 const char* arg_values[] = {arg1_val, arg2_val};
171 FlutterTimelineEvent(label: name, // label
172 timestamp0: gTimelineMicrosSource.load()(), // timestamp0
173 timestamp1_or_async_id: 0, // timestamp1_or_async_id
174 flow_id_count, // flow_id_count
175 flow_ids: reinterpret_cast<const int64_t*>(flow_ids), // flow_ids
176 type: Dart_Timeline_Event_Begin, // event type
177 argument_count: 2, // argument_count
178 argument_names: arg_names, // argument_names
179 argument_values: arg_values // argument_values
180 );
181}
182
183void TraceEventEnd(TraceArg name) {
184 FlutterTimelineEvent(label: name, // label
185 timestamp0: gTimelineMicrosSource.load()(), // timestamp0
186 timestamp1_or_async_id: 0, // timestamp1_or_async_id
187 flow_id_count: 0, // flow_id_count
188 flow_ids: nullptr, // flow_ids
189 type: Dart_Timeline_Event_End, // event type
190 argument_count: 0, // argument_count
191 argument_names: nullptr, // argument_names
192 argument_values: nullptr // argument_values
193 );
194}
195
196void TraceEventAsyncBegin0(TraceArg category_group,
197 TraceArg name,
198 TraceIDArg id,
199 size_t flow_id_count,
200 const uint64_t* flow_ids) {
201 FlutterTimelineEvent(label: name, // label
202 timestamp0: gTimelineMicrosSource.load()(), // timestamp0
203 timestamp1_or_async_id: id, // timestamp1_or_async_id
204 flow_id_count, // flow_id_count
205 flow_ids: reinterpret_cast<const int64_t*>(flow_ids), // flow_ids
206 type: Dart_Timeline_Event_Async_Begin, // event type
207 argument_count: 0, // argument_count
208 argument_names: nullptr, // argument_names
209 argument_values: nullptr // argument_values
210 );
211}
212
213void TraceEventAsyncEnd0(TraceArg category_group,
214 TraceArg name,
215 TraceIDArg id) {
216 FlutterTimelineEvent(label: name, // label
217 timestamp0: gTimelineMicrosSource.load()(), // timestamp0
218 timestamp1_or_async_id: id, // timestamp1_or_async_id
219 flow_id_count: 0, // flow_id_count
220 flow_ids: nullptr, // flow_ids
221 type: Dart_Timeline_Event_Async_End, // event type
222 argument_count: 0, // argument_count
223 argument_names: nullptr, // argument_names
224 argument_values: nullptr // argument_values
225 );
226}
227
228void TraceEventAsyncBegin1(TraceArg category_group,
229 TraceArg name,
230 TraceIDArg id,
231 size_t flow_id_count,
232 const uint64_t* flow_ids,
233 TraceArg arg1_name,
234 TraceArg arg1_val) {
235 const char* arg_names[] = {arg1_name};
236 const char* arg_values[] = {arg1_val};
237 FlutterTimelineEvent(label: name, // label
238 timestamp0: gTimelineMicrosSource.load()(), // timestamp0
239 timestamp1_or_async_id: id, // timestamp1_or_async_id
240 flow_id_count, // flow_id_count
241 flow_ids: reinterpret_cast<const int64_t*>(flow_ids), // flow_ids
242 type: Dart_Timeline_Event_Async_Begin, // event type
243 argument_count: 1, // argument_count
244 argument_names: arg_names, // argument_names
245 argument_values: arg_values // argument_values
246 );
247}
248
249void TraceEventAsyncEnd1(TraceArg category_group,
250 TraceArg name,
251 TraceIDArg id,
252 TraceArg arg1_name,
253 TraceArg arg1_val) {
254 const char* arg_names[] = {arg1_name};
255 const char* arg_values[] = {arg1_val};
256 FlutterTimelineEvent(label: name, // label
257 timestamp0: gTimelineMicrosSource.load()(), // timestamp0
258 timestamp1_or_async_id: id, // timestamp1_or_async_id
259 flow_id_count: 0, // flow_id_count
260 flow_ids: nullptr, // flow_ids
261 type: Dart_Timeline_Event_Async_End, // event type
262 argument_count: 1, // argument_count
263 argument_names: arg_names, // argument_names
264 argument_values: arg_values // argument_values
265 );
266}
267
268void TraceEventInstant0(TraceArg category_group,
269 TraceArg name,
270 size_t flow_id_count,
271 const uint64_t* flow_ids) {
272 FlutterTimelineEvent(label: name, // label
273 timestamp0: gTimelineMicrosSource.load()(), // timestamp0
274 timestamp1_or_async_id: 0, // timestamp1_or_async_id
275 flow_id_count, // flow_id_count
276 flow_ids: reinterpret_cast<const int64_t*>(flow_ids), // flow_ids
277 type: Dart_Timeline_Event_Instant, // event type
278 argument_count: 0, // argument_count
279 argument_names: nullptr, // argument_names
280 argument_values: nullptr // argument_values
281 );
282}
283
284void TraceEventInstant1(TraceArg category_group,
285 TraceArg name,
286 size_t flow_id_count,
287 const uint64_t* flow_ids,
288 TraceArg arg1_name,
289 TraceArg arg1_val) {
290 const char* arg_names[] = {arg1_name};
291 const char* arg_values[] = {arg1_val};
292 FlutterTimelineEvent(label: name, // label
293 timestamp0: gTimelineMicrosSource.load()(), // timestamp0
294 timestamp1_or_async_id: 0, // timestamp1_or_async_id
295 flow_id_count, // flow_id_count
296 flow_ids: reinterpret_cast<const int64_t*>(flow_ids), // flow_ids
297 type: Dart_Timeline_Event_Instant, // event type
298 argument_count: 1, // argument_count
299 argument_names: arg_names, // argument_names
300 argument_values: arg_values // argument_values
301 );
302}
303
304void TraceEventInstant2(TraceArg category_group,
305 TraceArg name,
306 size_t flow_id_count,
307 const uint64_t* flow_ids,
308 TraceArg arg1_name,
309 TraceArg arg1_val,
310 TraceArg arg2_name,
311 TraceArg arg2_val) {
312 const char* arg_names[] = {arg1_name, arg2_name};
313 const char* arg_values[] = {arg1_val, arg2_val};
314 FlutterTimelineEvent(label: name, // label
315 timestamp0: gTimelineMicrosSource.load()(), // timestamp0
316 timestamp1_or_async_id: 0, // timestamp1_or_async_id
317 flow_id_count, // flow_id_count
318 flow_ids: reinterpret_cast<const int64_t*>(flow_ids), // flow_ids
319 type: Dart_Timeline_Event_Instant, // event type
320 argument_count: 2, // argument_count
321 argument_names: arg_names, // argument_names
322 argument_values: arg_values // argument_values
323 );
324}
325
326void TraceEventFlowBegin0(TraceArg category_group,
327 TraceArg name,
328 TraceIDArg id) {
329 FlutterTimelineEvent(label: name, // label
330 timestamp0: gTimelineMicrosSource.load()(), // timestamp0
331 timestamp1_or_async_id: id, // timestamp1_or_async_id
332 flow_id_count: 0, // flow_id_count
333 flow_ids: nullptr, // flow_ids
334 type: Dart_Timeline_Event_Flow_Begin, // event type
335 argument_count: 0, // argument_count
336 argument_names: nullptr, // argument_names
337 argument_values: nullptr // argument_values
338 );
339}
340
341void TraceEventFlowStep0(TraceArg category_group,
342 TraceArg name,
343 TraceIDArg id) {
344 FlutterTimelineEvent(label: name, // label
345 timestamp0: gTimelineMicrosSource.load()(), // timestamp0
346 timestamp1_or_async_id: id, // timestamp1_or_async_id
347 flow_id_count: 0, // flow_id_count
348 flow_ids: nullptr, // flow_ids
349 type: Dart_Timeline_Event_Flow_Step, // event type
350 argument_count: 0, // argument_count
351 argument_names: nullptr, // argument_names
352 argument_values: nullptr // argument_values
353 );
354}
355
356void TraceEventFlowEnd0(TraceArg category_group, TraceArg name, TraceIDArg id) {
357 FlutterTimelineEvent(label: name, // label
358 timestamp0: gTimelineMicrosSource.load()(), // timestamp0
359 timestamp1_or_async_id: id, // timestamp1_or_async_id
360 flow_id_count: 0, // flow_id_count
361 flow_ids: nullptr, // flow_ids
362 type: Dart_Timeline_Event_Flow_End, // event type
363 argument_count: 0, // argument_count
364 argument_names: nullptr, // argument_names
365 argument_values: nullptr // argument_values
366 );
367}
368
369#else // FLUTTER_TIMELINE_ENABLED
370
371void TraceSetAllowlist(const std::vector<std::string>& allowlist) {}
372
373void TraceSetTimelineEventHandler(TimelineEventHandler handler) {}
374
375bool TraceHasTimelineEventHandler() {
376 return false;
377}
378
379int64_t TraceGetTimelineMicros() {
380 return -1;
381}
382
383void TraceSetTimelineMicrosSource(TimelineMicrosSource source) {}
384
385size_t TraceNonce() {
386 return 0;
387}
388
389void TraceTimelineEvent(TraceArg category_group,
390 TraceArg name,
391 int64_t timestamp_micros,
392 TraceIDArg identifier,
393 size_t flow_id_count,
394 const uint64_t* flow_ids,
395 Dart_Timeline_Event_Type type,
396 const std::vector<const char*>& c_names,
397 const std::vector<std::string>& values) {}
398
399void TraceTimelineEvent(TraceArg category_group,
400 TraceArg name,
401 TraceIDArg identifier,
402 size_t flow_id_count,
403 const uint64_t* flow_ids,
404 Dart_Timeline_Event_Type type,
405 const std::vector<const char*>& c_names,
406 const std::vector<std::string>& values) {}
407
408void TraceEvent0(TraceArg category_group,
409 TraceArg name,
410 size_t flow_id_count,
411 const uint64_t* flow_ids) {}
412
413void TraceEvent1(TraceArg category_group,
414 TraceArg name,
415 size_t flow_id_count,
416 const uint64_t* flow_ids,
417 TraceArg arg1_name,
418 TraceArg arg1_val) {}
419
420void TraceEvent2(TraceArg category_group,
421 TraceArg name,
422 size_t flow_id_count,
423 const uint64_t* flow_ids,
424 TraceArg arg1_name,
425 TraceArg arg1_val,
426 TraceArg arg2_name,
427 TraceArg arg2_val) {}
428
429void TraceEventEnd(TraceArg name) {}
430
431void TraceEventAsyncComplete(TraceArg category_group,
432 TraceArg name,
433 TimePoint begin,
434 TimePoint end) {}
435
436void TraceEventAsyncBegin0(TraceArg category_group,
437 TraceArg name,
438 TraceIDArg id,
439 size_t flow_id_count,
440 const uint64_t* flow_ids) {}
441
442void TraceEventAsyncEnd0(TraceArg category_group,
443 TraceArg name,
444 TraceIDArg id) {}
445
446void TraceEventAsyncBegin1(TraceArg category_group,
447 TraceArg name,
448 TraceIDArg id,
449 size_t flow_id_count,
450 const uint64_t* flow_ids,
451 TraceArg arg1_name,
452 TraceArg arg1_val) {}
453
454void TraceEventAsyncEnd1(TraceArg category_group,
455 TraceArg name,
456 TraceIDArg id,
457 TraceArg arg1_name,
458 TraceArg arg1_val) {}
459
460void TraceEventInstant0(TraceArg category_group,
461 TraceArg name,
462 size_t flow_id_count,
463 const uint64_t* flow_ids) {}
464
465void TraceEventInstant1(TraceArg category_group,
466 TraceArg name,
467 size_t flow_id_count,
468 const uint64_t* flow_ids,
469 TraceArg arg1_name,
470 TraceArg arg1_val) {}
471
472void TraceEventInstant2(TraceArg category_group,
473 TraceArg name,
474 size_t flow_id_count,
475 const uint64_t* flow_ids,
476 TraceArg arg1_name,
477 TraceArg arg1_val,
478 TraceArg arg2_name,
479 TraceArg arg2_val) {}
480
481void TraceEventFlowBegin0(TraceArg category_group,
482 TraceArg name,
483 TraceIDArg id) {}
484
485void TraceEventFlowStep0(TraceArg category_group,
486 TraceArg name,
487 TraceIDArg id) {}
488
489void TraceEventFlowEnd0(TraceArg category_group, TraceArg name, TraceIDArg id) {
490}
491
492#endif // FLUTTER_TIMELINE_ENABLED
493
494} // namespace tracing
495} // namespace fml
496

source code of flutter_engine/flutter/fml/trace_event.cc