From e3ee384af6d5eca151cbe45b339413a07e2a2ef4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Wed, 6 Oct 2021 18:19:50 +0200 Subject: [PATCH 1/2] Add tracing for routes --- flutter/example/lib/main.dart | 15 ++-- .../navigation/sentry_navigator_observer.dart | 68 ++++++++++++++++++- 2 files changed, 75 insertions(+), 8 deletions(-) diff --git a/flutter/example/lib/main.dart b/flutter/example/lib/main.dart index a707ad782d..702d28734a 100644 --- a/flutter/example/lib/main.dart +++ b/flutter/example/lib/main.dart @@ -32,11 +32,6 @@ class MyApp extends StatefulWidget { } class _MyAppState extends State { - @override - void initState() { - super.initState(); - } - @override Widget build(BuildContext context) { return feedback.BetterFeedback( @@ -45,7 +40,7 @@ class _MyAppState extends State { child: Builder( builder: (context) => MaterialApp( navigatorObservers: [ - SentryNavigatorObserver(), + SentryNavigatorObserver(enableTracing: true), ], theme: Provider.of(context).theme, home: const MainScaffold(), @@ -473,11 +468,15 @@ class SecondaryScaffold extends StatelessWidget { } Future makeWebRequest(BuildContext context) async { + /* + SentryNavigatorObserver already startet a transaction, + so we don't have to start another one final transaction = Sentry.startTransaction( 'flutterwebrequest', 'request', bindToScope: true, ); + */ final client = SentryHttpClient( captureFailedRequests: true, @@ -488,7 +487,9 @@ Future makeWebRequest(BuildContext context) async { // In case of an exception, let it get caught and reported to Sentry final response = await client.get(Uri.parse('https://flutter.dev/')); - await transaction.finish(status: SpanStatus.ok()); + // SentryNavigatorObserver already startet a transaction, + // so we don't have to finish the one + //await transaction.finish(status: SpanStatus.ok()); await showDialog( context: context, diff --git a/flutter/lib/src/navigation/sentry_navigator_observer.dart b/flutter/lib/src/navigation/sentry_navigator_observer.dart index 917bc67c08..ef66e97643 100644 --- a/flutter/lib/src/navigation/sentry_navigator_observer.dart +++ b/flutter/lib/src/navigation/sentry_navigator_observer.dart @@ -6,6 +6,9 @@ import '../../sentry_flutter.dart'; /// See https://develop.sentry.dev/sdk/event-payloads/breadcrumbs/ const _navigationKey = 'navigation'; +/// Used as value for [SentrySpanContext.operation] +const _transactionOp = 'page_view'; + /// This is a navigation observer to record navigational breadcrumbs. /// For now it only records navigation events and no gestures. /// @@ -35,10 +38,20 @@ const _navigationKey = 'navigation'; /// - [RouteObserver](https://api.flutter.dev/flutter/widgets/RouteObserver-class.html) /// - [Navigating with arguments](https://flutter.dev/docs/cookbook/navigation/navigate-with-arguments) class SentryNavigatorObserver extends RouteObserver> { - SentryNavigatorObserver({Hub? hub}) : hub = hub ?? HubAdapter(); + SentryNavigatorObserver({Hub? hub, this.enableTracing = false}) + : hub = hub ?? HubAdapter(); final Hub hub; + /// Create a new transaction, which gets bound to the scope, on each + /// navigation event. + /// [RouteSettings] are added as extras. The [RouteSettings.name] is used as + /// a name. + final bool enableTracing; + + ISentrySpan? _currentTransaction; + ISentrySpan? _currentSpan; + @override void didPush(Route route, Route? previousRoute) { super.didPush(route, previousRoute); @@ -47,6 +60,11 @@ class SentryNavigatorObserver extends RouteObserver> { from: previousRoute?.settings, to: route.settings, ); + if (route is PopupRoute) { + _startSpan(route); + } else { + _startTrace(route); + } } @override @@ -58,6 +76,14 @@ class SentryNavigatorObserver extends RouteObserver> { from: oldRoute?.settings, to: newRoute?.settings, ); + if (oldRoute is ModalRoute) { + _currentSpan?.finish(); + } + if (newRoute is PopupRoute) { + _startSpan(newRoute); + } else { + _startTrace(newRoute); + } } @override @@ -69,6 +95,10 @@ class SentryNavigatorObserver extends RouteObserver> { from: route.settings, to: previousRoute?.settings, ); + if (previousRoute is ModalRoute) { + _currentSpan?.finish(); + } + _startTrace(previousRoute); } void _addBreadcrumb({ @@ -82,6 +112,42 @@ class SentryNavigatorObserver extends RouteObserver> { to: to, )); } + + Future _startTrace(Route? route) async { + if (!enableTracing) { + return; + } + await _currentTransaction?.finish(); + + var span = hub.startTransaction( + route?.settings.name ?? 'unnamed page', + _transactionOp, + bindToScope: true, + ); + + final arguments = route?.settings.arguments; + if (arguments != null) { + span.setData('route_settings_arguments', arguments); + } + + _currentTransaction = span; + } + + Future _startSpan(PopupRoute? route) async { + if (!enableTracing) { + return; + } + await _currentSpan?.finish(); + final span = _currentTransaction?.startChild( + _transactionOp, + description: route?.settings.name ?? 'unnamed popup', + ); + final arguments = route?.settings.arguments; + if (arguments != null) { + span?.setData('route_settings_arguments', arguments); + } + _currentSpan = span; + } } /// This class makes it easier to record breadcrumbs for events of Flutters From 743e6a850c618acd9f01c167816a47f59751161b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Uek=C3=B6tter?= Date: Thu, 7 Oct 2021 08:38:41 +0200 Subject: [PATCH 2/2] Update flutter/lib/src/navigation/sentry_navigator_observer.dart Co-authored-by: Manoel Aranda Neto <5731772+marandaneto@users.noreply.github.com> --- flutter/lib/src/navigation/sentry_navigator_observer.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flutter/lib/src/navigation/sentry_navigator_observer.dart b/flutter/lib/src/navigation/sentry_navigator_observer.dart index ef66e97643..eb2aaf9efc 100644 --- a/flutter/lib/src/navigation/sentry_navigator_observer.dart +++ b/flutter/lib/src/navigation/sentry_navigator_observer.dart @@ -7,7 +7,7 @@ import '../../sentry_flutter.dart'; const _navigationKey = 'navigation'; /// Used as value for [SentrySpanContext.operation] -const _transactionOp = 'page_view'; +const _transactionOp = 'ui.load'; /// This is a navigation observer to record navigational breadcrumbs. /// For now it only records navigation events and no gestures.