| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "flutter/fml/trace_event.h" |
| |
| #include <algorithm> |
| #include <atomic> |
| #include <utility> |
| |
| #include "flutter/fml/ascii_trie.h" |
| #include "flutter/fml/build_config.h" |
| #include "flutter/fml/logging.h" |
| |
| namespace fml { |
| namespace tracing { |
| |
| #if FLUTTER_TIMELINE_ENABLED |
| |
| namespace { |
| |
| int64_t DefaultMicrosSource() { |
| return -1; |
| } |
| |
| AsciiTrie gAllowlist; |
| std::atomic<TimelineEventHandler> gTimelineEventHandler; |
| std::atomic<TimelineMicrosSource> gTimelineMicrosSource = DefaultMicrosSource; |
| |
| inline void FlutterTimelineEvent(const char* label, |
| int64_t timestamp0, |
| int64_t timestamp1_or_async_id, |
| intptr_t flow_id_count, |
| const int64_t* flow_ids, |
| Dart_Timeline_Event_Type type, |
| intptr_t argument_count, |
| const char** argument_names, |
| const char** argument_values) { |
| TimelineEventHandler handler = |
| gTimelineEventHandler.load(std::memory_order_relaxed); |
| if (handler && gAllowlist.Query(label)) { |
| handler(label, timestamp0, timestamp1_or_async_id, flow_id_count, flow_ids, |
| type, argument_count, argument_names, argument_values); |
| } |
| } |
| } // namespace |
| |
| void TraceSetAllowlist(const std::vector<std::string>& allowlist) { |
| gAllowlist.Fill(allowlist); |
| } |
| |
| void TraceSetTimelineEventHandler(TimelineEventHandler handler) { |
| gTimelineEventHandler = handler; |
| } |
| |
| bool TraceHasTimelineEventHandler() { |
| return static_cast<bool>( |
| gTimelineEventHandler.load(std::memory_order_relaxed)); |
| } |
| |
| int64_t TraceGetTimelineMicros() { |
| return gTimelineMicrosSource.load()(); |
| } |
| |
| void TraceSetTimelineMicrosSource(TimelineMicrosSource source) { |
| gTimelineMicrosSource = source; |
| } |
| |
| size_t TraceNonce() { |
| static std::atomic_size_t last_item; |
| return ++last_item; |
| } |
| |
| void TraceTimelineEvent(TraceArg category_group, |
| TraceArg name, |
| int64_t timestamp_micros, |
| TraceIDArg identifier, |
| size_t flow_id_count, |
| const uint64_t* flow_ids, |
| Dart_Timeline_Event_Type type, |
| const std::vector<const char*>& c_names, |
| const std::vector<std::string>& values) { |
| const auto argument_count = std::min(c_names.size(), values.size()); |
| |
| std::vector<const char*> c_values; |
| c_values.resize(argument_count, nullptr); |
| |
| for (size_t i = 0; i < argument_count; i++) { |
| c_values[i] = values[i].c_str(); |
| } |
| |
| FlutterTimelineEvent( |
| name, // label |
| timestamp_micros, // timestamp0 |
| identifier, // timestamp1_or_async_id |
| flow_id_count, // flow_id_count |
| reinterpret_cast<const int64_t*>(flow_ids), // flow_ids |
| type, // event type |
| argument_count, // argument_count |
| const_cast<const char**>(c_names.data()), // argument_names |
| c_values.data() // argument_values |
| ); |
| } |
| |
| void TraceTimelineEvent(TraceArg category_group, |
| TraceArg name, |
| TraceIDArg identifier, |
| size_t flow_id_count, |
| const uint64_t* flow_ids, |
| Dart_Timeline_Event_Type type, |
| const std::vector<const char*>& c_names, |
| const std::vector<std::string>& values) { |
| TraceTimelineEvent(category_group, // group |
| name, // name |
| gTimelineMicrosSource.load()(), // timestamp_micros |
| identifier, // identifier |
| flow_id_count, // flow_id_count |
| flow_ids, // flow_ids |
| type, // type |
| c_names, // names |
| values // values |
| ); |
| } |
| |
| void TraceEvent0(TraceArg category_group, |
| TraceArg name, |
| size_t flow_id_count, |
| const uint64_t* flow_ids) { |
| FlutterTimelineEvent(name, // label |
| gTimelineMicrosSource.load()(), // timestamp0 |
| 0, // timestamp1_or_async_id |
| flow_id_count, // flow_id_count |
| reinterpret_cast<const int64_t*>(flow_ids), // flow_ids |
| Dart_Timeline_Event_Begin, // event type |
| 0, // argument_count |
| nullptr, // argument_names |
| nullptr // argument_values |
| ); |
| } |
| |
| void TraceEvent1(TraceArg category_group, |
| TraceArg name, |
| size_t flow_id_count, |
| const uint64_t* flow_ids, |
| TraceArg arg1_name, |
| TraceArg arg1_val) { |
| const char* arg_names[] = {arg1_name}; |
| const char* arg_values[] = {arg1_val}; |
| FlutterTimelineEvent(name, // label |
| gTimelineMicrosSource.load()(), // timestamp0 |
| 0, // timestamp1_or_async_id |
| flow_id_count, // flow_id_count |
| reinterpret_cast<const int64_t*>(flow_ids), // flow_ids |
| Dart_Timeline_Event_Begin, // event type |
| 1, // argument_count |
| arg_names, // argument_names |
| arg_values // argument_values |
| ); |
| } |
| |
| void TraceEvent2(TraceArg category_group, |
| TraceArg name, |
| size_t flow_id_count, |
| const uint64_t* flow_ids, |
| TraceArg arg1_name, |
| TraceArg arg1_val, |
| TraceArg arg2_name, |
| TraceArg arg2_val) { |
| const char* arg_names[] = {arg1_name, arg2_name}; |
| const char* arg_values[] = {arg1_val, arg2_val}; |
| FlutterTimelineEvent(name, // label |
| gTimelineMicrosSource.load()(), // timestamp0 |
| 0, // timestamp1_or_async_id |
| flow_id_count, // flow_id_count |
| reinterpret_cast<const int64_t*>(flow_ids), // flow_ids |
| Dart_Timeline_Event_Begin, // event type |
| 2, // argument_count |
| arg_names, // argument_names |
| arg_values // argument_values |
| ); |
| } |
| |
| void TraceEventEnd(TraceArg name) { |
| FlutterTimelineEvent(name, // label |
| gTimelineMicrosSource.load()(), // timestamp0 |
| 0, // timestamp1_or_async_id |
| 0, // flow_id_count |
| nullptr, // flow_ids |
| Dart_Timeline_Event_End, // event type |
| 0, // argument_count |
| nullptr, // argument_names |
| nullptr // argument_values |
| ); |
| } |
| |
| void TraceEventAsyncBegin0(TraceArg category_group, |
| TraceArg name, |
| TraceIDArg id, |
| size_t flow_id_count, |
| const uint64_t* flow_ids) { |
| FlutterTimelineEvent(name, // label |
| gTimelineMicrosSource.load()(), // timestamp0 |
| id, // timestamp1_or_async_id |
| flow_id_count, // flow_id_count |
| reinterpret_cast<const int64_t*>(flow_ids), // flow_ids |
| Dart_Timeline_Event_Async_Begin, // event type |
| 0, // argument_count |
| nullptr, // argument_names |
| nullptr // argument_values |
| ); |
| } |
| |
| void TraceEventAsyncEnd0(TraceArg category_group, |
| TraceArg name, |
| TraceIDArg id) { |
| FlutterTimelineEvent(name, // label |
| gTimelineMicrosSource.load()(), // timestamp0 |
| id, // timestamp1_or_async_id |
| 0, // flow_id_count |
| nullptr, // flow_ids |
| Dart_Timeline_Event_Async_End, // event type |
| 0, // argument_count |
| nullptr, // argument_names |
| nullptr // argument_values |
| ); |
| } |
| |
| void TraceEventAsyncBegin1(TraceArg category_group, |
| TraceArg name, |
| TraceIDArg id, |
| size_t flow_id_count, |
| const uint64_t* flow_ids, |
| TraceArg arg1_name, |
| TraceArg arg1_val) { |
| const char* arg_names[] = {arg1_name}; |
| const char* arg_values[] = {arg1_val}; |
| FlutterTimelineEvent(name, // label |
| gTimelineMicrosSource.load()(), // timestamp0 |
| id, // timestamp1_or_async_id |
| flow_id_count, // flow_id_count |
| reinterpret_cast<const int64_t*>(flow_ids), // flow_ids |
| Dart_Timeline_Event_Async_Begin, // event type |
| 1, // argument_count |
| arg_names, // argument_names |
| arg_values // argument_values |
| ); |
| } |
| |
| void TraceEventAsyncEnd1(TraceArg category_group, |
| TraceArg name, |
| TraceIDArg id, |
| TraceArg arg1_name, |
| TraceArg arg1_val) { |
| const char* arg_names[] = {arg1_name}; |
| const char* arg_values[] = {arg1_val}; |
| FlutterTimelineEvent(name, // label |
| gTimelineMicrosSource.load()(), // timestamp0 |
| id, // timestamp1_or_async_id |
| 0, // flow_id_count |
| nullptr, // flow_ids |
| Dart_Timeline_Event_Async_End, // event type |
| 1, // argument_count |
| arg_names, // argument_names |
| arg_values // argument_values |
| ); |
| } |
| |
| void TraceEventInstant0(TraceArg category_group, |
| TraceArg name, |
| size_t flow_id_count, |
| const uint64_t* flow_ids) { |
| FlutterTimelineEvent(name, // label |
| gTimelineMicrosSource.load()(), // timestamp0 |
| 0, // timestamp1_or_async_id |
| flow_id_count, // flow_id_count |
| reinterpret_cast<const int64_t*>(flow_ids), // flow_ids |
| Dart_Timeline_Event_Instant, // event type |
| 0, // argument_count |
| nullptr, // argument_names |
| nullptr // argument_values |
| ); |
| } |
| |
| void TraceEventInstant1(TraceArg category_group, |
| TraceArg name, |
| size_t flow_id_count, |
| const uint64_t* flow_ids, |
| TraceArg arg1_name, |
| TraceArg arg1_val) { |
| const char* arg_names[] = {arg1_name}; |
| const char* arg_values[] = {arg1_val}; |
| FlutterTimelineEvent(name, // label |
| gTimelineMicrosSource.load()(), // timestamp0 |
| 0, // timestamp1_or_async_id |
| flow_id_count, // flow_id_count |
| reinterpret_cast<const int64_t*>(flow_ids), // flow_ids |
| Dart_Timeline_Event_Instant, // event type |
| 1, // argument_count |
| arg_names, // argument_names |
| arg_values // argument_values |
| ); |
| } |
| |
| void TraceEventInstant2(TraceArg category_group, |
| TraceArg name, |
| size_t flow_id_count, |
| const uint64_t* flow_ids, |
| TraceArg arg1_name, |
| TraceArg arg1_val, |
| TraceArg arg2_name, |
| TraceArg arg2_val) { |
| const char* arg_names[] = {arg1_name, arg2_name}; |
| const char* arg_values[] = {arg1_val, arg2_val}; |
| FlutterTimelineEvent(name, // label |
| gTimelineMicrosSource.load()(), // timestamp0 |
| 0, // timestamp1_or_async_id |
| flow_id_count, // flow_id_count |
| reinterpret_cast<const int64_t*>(flow_ids), // flow_ids |
| Dart_Timeline_Event_Instant, // event type |
| 2, // argument_count |
| arg_names, // argument_names |
| arg_values // argument_values |
| ); |
| } |
| |
| void TraceEventFlowBegin0(TraceArg category_group, |
| TraceArg name, |
| TraceIDArg id) { |
| FlutterTimelineEvent(name, // label |
| gTimelineMicrosSource.load()(), // timestamp0 |
| id, // timestamp1_or_async_id |
| 0, // flow_id_count |
| nullptr, // flow_ids |
| Dart_Timeline_Event_Flow_Begin, // event type |
| 0, // argument_count |
| nullptr, // argument_names |
| nullptr // argument_values |
| ); |
| } |
| |
| void TraceEventFlowStep0(TraceArg category_group, |
| TraceArg name, |
| TraceIDArg id) { |
| FlutterTimelineEvent(name, // label |
| gTimelineMicrosSource.load()(), // timestamp0 |
| id, // timestamp1_or_async_id |
| 0, // flow_id_count |
| nullptr, // flow_ids |
| Dart_Timeline_Event_Flow_Step, // event type |
| 0, // argument_count |
| nullptr, // argument_names |
| nullptr // argument_values |
| ); |
| } |
| |
| void TraceEventFlowEnd0(TraceArg category_group, TraceArg name, TraceIDArg id) { |
| FlutterTimelineEvent(name, // label |
| gTimelineMicrosSource.load()(), // timestamp0 |
| id, // timestamp1_or_async_id |
| 0, // flow_id_count |
| nullptr, // flow_ids |
| Dart_Timeline_Event_Flow_End, // event type |
| 0, // argument_count |
| nullptr, // argument_names |
| nullptr // argument_values |
| ); |
| } |
| |
| #else // FLUTTER_TIMELINE_ENABLED |
| |
| void TraceSetAllowlist(const std::vector<std::string>& allowlist) {} |
| |
| void TraceSetTimelineEventHandler(TimelineEventHandler handler) {} |
| |
| bool TraceHasTimelineEventHandler() { |
| return false; |
| } |
| |
| int64_t TraceGetTimelineMicros() { |
| return -1; |
| } |
| |
| void TraceSetTimelineMicrosSource(TimelineMicrosSource source) {} |
| |
| size_t TraceNonce() { |
| return 0; |
| } |
| |
| void TraceTimelineEvent(TraceArg category_group, |
| TraceArg name, |
| int64_t timestamp_micros, |
| TraceIDArg identifier, |
| size_t flow_id_count, |
| const uint64_t* flow_ids, |
| Dart_Timeline_Event_Type type, |
| const std::vector<const char*>& c_names, |
| const std::vector<std::string>& values) {} |
| |
| void TraceTimelineEvent(TraceArg category_group, |
| TraceArg name, |
| TraceIDArg identifier, |
| size_t flow_id_count, |
| const uint64_t* flow_ids, |
| Dart_Timeline_Event_Type type, |
| const std::vector<const char*>& c_names, |
| const std::vector<std::string>& values) {} |
| |
| void TraceEvent0(TraceArg category_group, |
| TraceArg name, |
| size_t flow_id_count, |
| const uint64_t* flow_ids) {} |
| |
| void TraceEvent1(TraceArg category_group, |
| TraceArg name, |
| size_t flow_id_count, |
| const uint64_t* flow_ids, |
| TraceArg arg1_name, |
| TraceArg arg1_val) {} |
| |
| void TraceEvent2(TraceArg category_group, |
| TraceArg name, |
| size_t flow_id_count, |
| const uint64_t* flow_ids, |
| TraceArg arg1_name, |
| TraceArg arg1_val, |
| TraceArg arg2_name, |
| TraceArg arg2_val) {} |
| |
| void TraceEventEnd(TraceArg name) {} |
| |
| void TraceEventAsyncComplete(TraceArg category_group, |
| TraceArg name, |
| TimePoint begin, |
| TimePoint end) {} |
| |
| void TraceEventAsyncBegin0(TraceArg category_group, |
| TraceArg name, |
| TraceIDArg id, |
| size_t flow_id_count, |
| const uint64_t* flow_ids) {} |
| |
| void TraceEventAsyncEnd0(TraceArg category_group, |
| TraceArg name, |
| TraceIDArg id) {} |
| |
| void TraceEventAsyncBegin1(TraceArg category_group, |
| TraceArg name, |
| TraceIDArg id, |
| size_t flow_id_count, |
| const uint64_t* flow_ids, |
| TraceArg arg1_name, |
| TraceArg arg1_val) {} |
| |
| void TraceEventAsyncEnd1(TraceArg category_group, |
| TraceArg name, |
| TraceIDArg id, |
| TraceArg arg1_name, |
| TraceArg arg1_val) {} |
| |
| void TraceEventInstant0(TraceArg category_group, |
| TraceArg name, |
| size_t flow_id_count, |
| const uint64_t* flow_ids) {} |
| |
| void TraceEventInstant1(TraceArg category_group, |
| TraceArg name, |
| size_t flow_id_count, |
| const uint64_t* flow_ids, |
| TraceArg arg1_name, |
| TraceArg arg1_val) {} |
| |
| void TraceEventInstant2(TraceArg category_group, |
| TraceArg name, |
| size_t flow_id_count, |
| const uint64_t* flow_ids, |
| TraceArg arg1_name, |
| TraceArg arg1_val, |
| TraceArg arg2_name, |
| TraceArg arg2_val) {} |
| |
| void TraceEventFlowBegin0(TraceArg category_group, |
| TraceArg name, |
| TraceIDArg id) {} |
| |
| void TraceEventFlowStep0(TraceArg category_group, |
| TraceArg name, |
| TraceIDArg id) {} |
| |
| void TraceEventFlowEnd0(TraceArg category_group, TraceArg name, TraceIDArg id) { |
| } |
| |
| #endif // FLUTTER_TIMELINE_ENABLED |
| |
| } // namespace tracing |
| } // namespace fml |