From 178baee29ede5676069bf26c4228b37e1df7fdf3 Mon Sep 17 00:00:00 2001 From: Martin Haintz Date: Mon, 12 Aug 2024 13:41:20 +0200 Subject: [PATCH] add ignoreRoutes parameter to SentryNavigatorObserver (#2218) * add ignoreRoutes parameter to SentryNavigatorObserver * add unitTest for ignoreRoutes * add changelog entry for ignoreRoutes in the SentryNaviagtorObserver * add for ignore routes, that not TTID and TTFD spans are created Co-authored-by: Giancarlo Buenaflor * add further tests for ignore routes * fix changelog and move ignoreRoutes to unreleased --------- Co-authored-by: Giancarlo Buenaflor --- CHANGELOG.md | 11 ++++ .../navigation/sentry_navigator_observer.dart | 23 +++++++ .../test/sentry_navigator_observer_test.dart | 62 +++++++++++++++++++ 3 files changed, 96 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e3bd891c6..75d9fe9e24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## Unreleased + +### Features + +- Add `ignoreRoutes` parameter to `SentryNavigatorObserver`. ([#2218](https://github.com/getsentry/sentry-dart/pull/2218)) + - This will ignore the Routes and prevent the Route from being pushed to the Sentry server. + - Ignored routes will also create no TTID and TTFD spans. +```dart +SentryNavigatorObserver(ignoreRoutes: ["/ignoreThisRoute"]), +``` + ## 8.7.0 ### Features diff --git a/flutter/lib/src/navigation/sentry_navigator_observer.dart b/flutter/lib/src/navigation/sentry_navigator_observer.dart index 1a6b156377..db91098407 100644 --- a/flutter/lib/src/navigation/sentry_navigator_observer.dart +++ b/flutter/lib/src/navigation/sentry_navigator_observer.dart @@ -80,12 +80,14 @@ class SentryNavigatorObserver extends RouteObserver> { RouteNameExtractor? routeNameExtractor, AdditionalInfoExtractor? additionalInfoProvider, @visibleForTesting TimeToDisplayTracker? timeToDisplayTracker, + List? ignoreRoutes, }) : _hub = hub ?? HubAdapter(), _enableAutoTransactions = enableAutoTransactions, _autoFinishAfter = autoFinishAfter, _setRouteNameAsTransaction = setRouteNameAsTransaction, _routeNameExtractor = routeNameExtractor, _additionalInfoProvider = additionalInfoProvider, + _ignoreRoutes = ignoreRoutes ?? [], _native = SentryFlutter.native { _isCreated = true; if (enableAutoTransactions) { @@ -113,6 +115,7 @@ class SentryNavigatorObserver extends RouteObserver> { final RouteNameExtractor? _routeNameExtractor; final AdditionalInfoExtractor? _additionalInfoProvider; final SentryNativeBinding? _native; + final List _ignoreRoutes; static TimeToDisplayTracker? _timeToDisplayTracker; @internal @@ -141,6 +144,11 @@ class SentryNavigatorObserver extends RouteObserver> { void didPush(Route route, Route? previousRoute) { super.didPush(route, previousRoute); + if (_isRouteIgnored(route) || + previousRoute != null && _isRouteIgnored(previousRoute)) { + return; + } + _setCurrentRouteName(route); _setCurrentRouteNameAsTransaction(route); @@ -160,6 +168,11 @@ class SentryNavigatorObserver extends RouteObserver> { void didReplace({Route? newRoute, Route? oldRoute}) { super.didReplace(newRoute: newRoute, oldRoute: oldRoute); + if (newRoute != null && _isRouteIgnored(newRoute) || + oldRoute != null && _isRouteIgnored(oldRoute)) { + return; + } + _setCurrentRouteName(newRoute); _setCurrentRouteNameAsTransaction(newRoute); @@ -174,6 +187,11 @@ class SentryNavigatorObserver extends RouteObserver> { void didPop(Route route, Route? previousRoute) { super.didPop(route, previousRoute); + if (_isRouteIgnored(route) || + previousRoute != null && _isRouteIgnored(previousRoute)) { + return; + } + _setCurrentRouteName(previousRoute); _setCurrentRouteNameAsTransaction(previousRoute); @@ -376,6 +394,11 @@ class SentryNavigatorObserver extends RouteObserver> { @internal static const String rootScreenName = 'root /'; + + bool _isRouteIgnored(Route route) { + return _ignoreRoutes.isNotEmpty && + _ignoreRoutes.contains(_getRouteName(route)); + } } /// This class makes it easier to record breadcrumbs for events of Flutters diff --git a/flutter/test/sentry_navigator_observer_test.dart b/flutter/test/sentry_navigator_observer_test.dart index bc9971cb9c..9a64d65414 100644 --- a/flutter/test/sentry_navigator_observer_test.dart +++ b/flutter/test/sentry_navigator_observer_test.dart @@ -975,6 +975,66 @@ void main() { observer.didReplace(newRoute: route(to), oldRoute: route(previous)); expect(hub.scope.transaction, 'to_test'); }); + + test('ignores Route and prevents recognition of this route for didPush', + () async { + final firstRoute = route(RouteSettings(name: 'default')); + final secondRoute = route(RouteSettings(name: 'testRoute')); + + final hub = _MockHub(); + + final sut = fixture.getSut(hub: hub, ignoreRoutes: ["testRoute"]); + + sut.didPush(firstRoute, null); + expect( + SentryNavigatorObserver.currentRouteName, firstRoute.settings.name); + sut.didPush(secondRoute, firstRoute); + expect( + SentryNavigatorObserver.currentRouteName, firstRoute.settings.name); + sut.didPush(firstRoute, secondRoute); + expect( + SentryNavigatorObserver.currentRouteName, firstRoute.settings.name); + }); + + test('ignores Route and prevents recognition of this route for didPop', + () async { + final firstRoute = route(RouteSettings(name: 'default')); + final secondRoute = route(RouteSettings(name: 'testRoute')); + + final hub = _MockHub(); + + final sut = fixture.getSut(hub: hub, ignoreRoutes: ["testRoute"]); + + sut.didPush(firstRoute, null); + expect( + SentryNavigatorObserver.currentRouteName, firstRoute.settings.name); + sut.didPush(secondRoute, firstRoute); + expect( + SentryNavigatorObserver.currentRouteName, firstRoute.settings.name); + sut.didPop(firstRoute, secondRoute); + expect( + SentryNavigatorObserver.currentRouteName, firstRoute.settings.name); + }); + + test('ignores Route and prevents recognition of this route for didReplace', + () async { + final firstRoute = route(RouteSettings(name: 'default')); + final secondRoute = route(RouteSettings(name: 'testRoute')); + + final hub = _MockHub(); + + final sut = fixture.getSut(hub: hub, ignoreRoutes: ["testRoute"]); + + sut.didReplace(newRoute: firstRoute); + expect( + SentryNavigatorObserver.currentRouteName, firstRoute.settings.name); + sut.didReplace(newRoute: secondRoute, oldRoute: firstRoute); + expect( + SentryNavigatorObserver.currentRouteName, firstRoute.settings.name); + sut.didReplace(newRoute: firstRoute, oldRoute: secondRoute); + expect( + SentryNavigatorObserver.currentRouteName, firstRoute.settings.name); + }); }); } @@ -987,6 +1047,7 @@ class Fixture { RouteNameExtractor? routeNameExtractor, AdditionalInfoExtractor? additionalInfoProvider, bool enableTimeToFullDisplayTracing = false, + List? ignoreRoutes, }) { final frameCallbackHandler = FakeFrameCallbackHandler(); final timeToInitialDisplayTracker = @@ -1003,6 +1064,7 @@ class Fixture { routeNameExtractor: routeNameExtractor, additionalInfoProvider: additionalInfoProvider, timeToDisplayTracker: timeToDisplayTracker, + ignoreRoutes: ignoreRoutes, ); }