// 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 #include #include #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 gTimelineEventHandler; std::atomic 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& allowlist) { gAllowlist.Fill(allowlist); } void TraceSetTimelineEventHandler(TimelineEventHandler handler) { gTimelineEventHandler = handler; } bool TraceHasTimelineEventHandler() { return static_cast( 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& c_names, const std::vector& values) { const auto argument_count = std::min(c_names.size(), values.size()); std::vector 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(flow_ids), // flow_ids type, // event type argument_count, // argument_count const_cast(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& c_names, const std::vector& 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(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(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(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(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(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(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(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(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& 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& c_names, const std::vector& 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& c_names, const std::vector& 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