Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support the new MaterialApp.router navigation #827

Closed
4 of 11 tasks
stx opened this issue Apr 11, 2022 · 24 comments
Closed
4 of 11 tasks

Support the new MaterialApp.router navigation #827

stx opened this issue Apr 11, 2022 · 24 comments

Comments

@stx
Copy link

stx commented Apr 11, 2022

Platform:

  • Dart
  • Flutter Android or iOS
  • Flutter Web

IDE:

  • VSCode
  • IntelliJ/AS
  • XCode
  • Other, which one?

split-debug-info and obfuscate (Flutter Android or iOS) or CanvasKit (Flutter Web):

  • Enabled
  • Disabled

Platform installed with:

  • pub.dev
  • GitHub

Output of the command flutter doctor -v below:

[✓] Flutter (Channel stable, 2.10.4, on macOS 12.3.1 21E258 darwin-arm, locale en-US)
    • Flutter version 2.10.4 at /Users/james/Development/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision c860cba910 (3 weeks ago), 2022-03-25 00:23:12 -0500
    • Engine revision 57d3bac3dd
    • Dart version 2.16.2
    • DevTools version 2.9.2

[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
    • Android SDK at /Users/james/Library/Android/sdk
    • Platform android-31, build-tools 31.0.0
    • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.11+0-b60-7772763)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 13.2.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • CocoaPods version 1.11.2

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2021.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.11+0-b60-7772763)

[✓] VS Code (version 1.66.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.32.0

[✓] Connected device (2 available)
    • Apollo (mobile) • da060dc78ac99566c39cb688206b34cb424a5ee1 • ios            • iOS 15.3.1 19D52
    • Chrome (web)    • chrome                                   • web-javascript • Google Chrome 100.0.4896.75

[✓] HTTP Host Availability
    • All required HTTP hosts are available

• No issues found!

The version of the SDK (See pubspec.lock):
6.5.0-beta.1


I have the following issue:

Performance monitoring never records any transactions for anything. Error tracking works great.

This is the exact same issue as #720.

Steps to reproduce:

  SentryFlutter.init(
    (SentryFlutterOptions options) {
      options
        ..dsn = 'https://[removed]'
        ..tracesSampleRate = 1.0
        ..tracesSampler = ((_) => 1)
        ..debug = true;
    },
    appRunner: () async {
      runApp(
        DefaultAssetBundle(
          bundle: SentryAssetBundle(),
          child: const App(),
        ),
      );
    },
  );

In addition to the AssetBundle instrumentation installed above, and the expected automatic instrumentation like app start, we also have routing instrumentation installed via:

GoRouter(
  observers: <NavigatorObserver>[
    SentryNavigatorObserver(),
  ],
);

Actual result:

Sentry - debug:: No tracesSampleRate and tracesSampler set. Will not start SentryPerformanceTrackingIntegration.

No performance transaction is ever recorded on debug or in production.

Error tracking works great.

Expected result:

Performance tracking also works.

@marandaneto
Copy link
Contributor

@stx Please have a look at https://docs.sentry.io/platforms/flutter/performance/
You cannot use tracesSampleRate and tracesSampler, its either one or the other.
Can you double-check and copy-paste the full logging?

@marandaneto
Copy link
Contributor

Also look at https://docs.sentry.io/platforms/flutter/performance/instrumentation/automatic-instrumentation/#routing-instumentation
SentryNavigatorObserver is added to navigatorObservers, I'm not sure it works with GoRouter, I suspect you are using https://pub.dev/packages/go_router ?

@stx
Copy link
Author

stx commented Apr 12, 2022

@marandaneto Thanks for looking into this. Yes, I only added tracesSampler when the sampleRate also didn’t work.

Correct, it’s attached to the navigatorObserver in the GoRouter package (the new Flutter Navigator has no navigatorObserver in MaterialApp.) Sentry appears to track changes correctly as routing breadcrumbs show up in error tracing.

If this isn’t supported, do you know how to attach Sentry to the new Flutter navigation? You can see it at https://api.flutter.dev/flutter/material/MaterialApp/MaterialApp.router.html for reference.

I’ll post the full log tomorrow.

@stx stx closed this as completed Apr 12, 2022
@stx stx reopened this Apr 12, 2022
@marandaneto
Copy link
Contributor

@ueman
Copy link
Collaborator

ueman commented Apr 12, 2022

I suspect that the SentryNavigatorObserver just works with GoRouter, after all it's basically a convenience layer around Flutters routing.

@stx
Copy link
Author

stx commented Apr 12, 2022

@marandaneto Your link is for the old Flutter navigation - the new Flutter navigation is instantiated via https://api.flutter.dev/flutter/material/MaterialApp/MaterialApp.router.html which doesn't have navigatorObservers (they are delegated to other handlers, like GoRouter.)

Here are the logs using the below configuration:

      options
        ..dsn = 'https://[removed]'
        ..tracesSampleRate = 1.0
        ..debug = true;
Sentry - debug:: SDK initialized! Version: 7.11.0
Sentry - debug:: Integration installed: SentryCrashIntegration
Sentry - debug:: Integration installed: SentryANRTrackingIntegration
Sentry - debug:: Integration installed: SentryFramesTrackingIntegration
Sentry - debug:: Add breadcrumb: <SentryBreadcrumb: 0x2817a39c0>
Sentry - debug:: Integration installed: SentryAutoBreadcrumbTrackingIntegration
Sentry - debug:: Reading timestamp of last in foreground at: [/var/mobile/Containers/Data/Application/0CE2D1EC-F79B-40AB-A631-1E20A086663F/Library/Caches/io.sentry/0074e9491e47e2d30ee8d6e02002b49498dc0278/lastInForeground.timestamp]()
Sentry - debug:: No lastInForeground found.
Sentry - debug:: Reading from session: [/var/mobile/Containers/Data/Application/0CE2D1EC-F79B-40AB-A631-1E20A086663F/Library/Caches/io.sentry/0074e9491e47e2d30ee8d6e02002b49498dc0278/session.current]()
Sentry - debug:: No cached session to close.
Sentry - debug:: Integration installed: SentryAutoSessionTrackingIntegration
Sentry - debug:: Integration installed: SentryAppStartTrackingIntegration
Sentry - debug:: Integration installed: SentryOutOfMemoryTrackingIntegration
Sentry - debug:: No tracesSampleRate and tracesSampler set. Will not start SentryPerformanceTrackingIntegration.
Sentry - debug:: Integration installed: SentryPerformanceTrackingIntegration
Sentry - debug:: Not going to enable NetworkTracking because isTracingEnabled is disabled.
Sentry - debug:: Integration installed: SentryNetworkTrackingIntegration
Sentry - debug:: Not going to enable FileIOTracking because tracing is disabled.
Sentry - debug:: Integration installed: SentryFileIOTrackingIntegration
Sentry - debug:: Not going to enable CoreData tracking because tracing is disabled.
Sentry - debug:: Integration installed: SentryCoreDataTrackingIntegration
[sentry] [debug] release: [removed]
Sentry - debug:: Add breadcrumb: <SentryBreadcrumb: 0x28179ac80>
Sentry - debug:: Add breadcrumb: <SentryBreadcrumb: 0x28178c500>

@ueman
Copy link
Collaborator

ueman commented Apr 12, 2022

That looks like the logs from the native iOS Sentry SDK, which means native performance tracing isn't enabled. The Dart/Flutter performance tracing features should still work though. Have you verified that, by creating and capturing a manual performance trace?

I can see how that could confuse people. I wonder if that can be improved somehow.

@stx
Copy link
Author

stx commented Apr 12, 2022

@ueman Our Sentry performance views are literally empty - no transactions, no cold startup time, no warm startup time, no slow frames, no frozen frames.

I assume something is supposed to show up here else I'm not sure exactly what performance monitoring is. According to these docs...

https://docs.sentry.io/platforms/flutter/performance/instrumentation/automatic-instrumentation/#app-start-instrumentation
https://docs.sentry.io/platforms/flutter/performance/instrumentation/automatic-instrumentation/#slow-and-frozen-frames
https://docs.sentry.io/platforms/flutter/performance/instrumentation/automatic-instrumentation/#assetbundle-instrumentation

I would expect at least these items to show up, since they are either enabled by default (app start/slow frames), or we've added the code as instructed in AssetBundle's case.

Are we misunderstanding how this is supposed to work? We'll try a manual trace and see if that works.

@stx
Copy link
Author

stx commented Apr 12, 2022

Manual performance traces work correctly viaSentry.startTransaction('testTransaction', 'task'). We can see one transaction now but all other performance data is still empty.

@ueman
Copy link
Collaborator

ueman commented Apr 12, 2022

The integrations for AssetBundle, http and Dio just create child spans if there's a transaction bound to the scope. They don't create root transactions themselves.

Just the SentryNavigatorObserver creates root transactions (transactions which are bound to the scope). As said, I assume that it works with GoRouter but haven't tried it myself. Please note, that only Routes with names are considered as there's no way to identify and differentiate between different routes if they have no name. It should be logged, though, if a route hase no name.

The observer is also doing the app start and frame time thingies. Those metrics are contained within the repsective transactions initiated by the observer.

The name limitation should probably be more highlighted in the docs.

I'm not quite sure if that answers your question but nevertheless, I hope that it helped.

@stx
Copy link
Author

stx commented Apr 12, 2022

@ueman That helps a ton!

100% of our routes have names. They use URL paths like "/settings". Seems like the root issue is that the SentryNavigatorObserver isn't recording app start/frames on GoRouter or possibly Flutter Navigation 2.0 (Router) - that explains the missing metrics and allows everything we're seeing to make perfect sense.

Looking at GoRouter's code, it looks like it's passing observers directly to Navigator, so I presume the issue is not specific to this package:

https://github.com/flutter/packages/blob/c017156a022cf8c1fad45397073baf6ecd6c326b/packages/go_router/lib/src/go_router_delegate.dart#L690

We also see that navigation traces are showing up in issues, so the non-performance measurements appear to be working.

Is there anything else we can do to help identify the issue?

@marandaneto marandaneto changed the title Flutter Performance Monitoring doesn't work at all Support the new MaterialApp.router navigation Apr 13, 2022
@marandaneto
Copy link
Contributor

marandaneto commented Apr 13, 2022

Ok so this is not really a bug then, it's likely the lack of support of the new API MaterialApp.router.
Our docs mention support for the navigatorObservers only -> https://docs.sentry.io/platforms/flutter/performance/instrumentation/automatic-instrumentation/#routing-instumentation
For now, while we don't figure out a way around it, please use the custom instrumentation https://docs.sentry.io/platforms/flutter/performance/instrumentation/custom-instrumentation/ API

Slow and frozen frames won't work since it depends on the navigatorObservers as described in the docs https://docs.sentry.io/platforms/flutter/performance/instrumentation/automatic-instrumentation/#slow-and-frozen-frames

@marandaneto
Copy link
Contributor

I've tested it out with the MaterialApp.router and GoRouter objects and everything worked out.

I only I've added the observers to this example: https://github.com/flutter/packages/blob/3af45c77f9d04f9100b94dada152ecf629039d0c/packages/go_router/example/lib/main.dart#L25-L38

  final GoRouter _router = GoRouter(
    routes: <GoRoute>[
      GoRoute(
        path: '/',
        builder: (BuildContext context, GoRouterState state) =>
            const Page1Screen(),
      ),
      GoRoute(
        path: '/page2',
        builder: (BuildContext context, GoRouterState state) =>
            const Page2Screen(),
      ),
    ],
    observers: [SentryNavigatorObserver()],
  );

SDK init as simple as:

Future<void> main() async {
  await SentryFlutter.init(
    (options) {
      options.dsn =
          'my_dsn...';
      options.tracesSampleRate = 1.0;
      options.debug = true;
    },
    // Init your App.
    appRunner: () => runApp(
      DefaultAssetBundle(
        bundle: SentryAssetBundle(enableStructuredDataTracing: true),
        child: App(),
      ),
    ),
  );

Slow and frozen frames and App start worked out, @stx if that does not work for you, please provide a minimal reproducible example.

@marandaneto
Copy link
Contributor

@stx
Copy link
Author

stx commented Apr 13, 2022

@marandaneto Found the issue!

Works - transaction submitted:

GoRoute(
  path: '/',
  builder: (_, GoRouterState state) => Page1Screen(),
),

Doesn't work - no transaction submitted:

GoRoute(
  path: '/',
  pageBuilder: (_, GoRouterState state) => MaterialPage<dynamic>(
    key: state.pageKey,
    name: state.name,
    child: Page1Screen(),
  ),
),

Fix: Change the route name to the full URL path:

name: state.name -> name: state.fullpath

After we changed this, everything started to show up!

Closing as this seems to be an edge case. However, it could be super helpful to have an error/notice message in the logs if SentryNavigatorObserver() is enabled and the route is invalid (name is missing/invalid, etc.) Something like "Error: Route name invalid. Route names are required to log transactions." or something to that effect.

Thanks very much for your help in narrowing this down. 🙏

@stx stx closed this as completed Apr 13, 2022
@VasyaSmolyar
Copy link

How to put SentryNavigatorObserver() into MaterialApp.router?

@humber-z
Copy link

I have the same Issue, my project runs on Android and Web, I cant get to set up automated performance.

  Widget build(BuildContext context) => MaterialApp.router(
        routeInformationProvider: _router.routeInformationProvider,
        routeInformationParser: _router.routeInformationParser,
        routerDelegate: _router.routerDelegate,
        title: title,
      );
  final GoRouter _router = GoRouter(routes: <GoRoute>[
    GoRoute(
        path: '/',
        pageBuilder: (BuildContext context, GoRouterState state) =>
            MaterialPage<dynamic>(
                name: state.fullPath,
                key: state.pageKey,
                child: Page1Screen())),
    GoRoute(
        path: '/page2',
        pageBuilder: (BuildContext context, GoRouterState state) =>
            MaterialPage<dynamic>(
                name: state.fullPath,
                key: state.pageKey,
                child: Page2Screen())),
  ], observers: [
    SentryNavigatorObserver()
  ]);
}

I have already tried yout previous example @marandaneto like this:

  @override
  Widget build(BuildContext context) => MaterialApp.router(
        routerConfig: _router,
        title: title,
      );
  
  final GoRouter _router = GoRouter(routes: <GoRoute>[
    GoRoute(
      path: '/',
      builder: (BuildContext context, GoRouterState state) =>
          const Page1Screen(),
    ),
    GoRoute(
      path: '/page2',
      builder: (BuildContext context, GoRouterState state) =>
          const Page2Screen(),
    ),
  ], observers: [
    SentryNavigatorObserver()
  ]);
}

Still no frozen frame, app start or any vitals, only erros and custom transactions,
any help would be much appreciated.

@denrase
Copy link
Collaborator

denrase commented Sep 12, 2023

@humber-z I'll take a look and come back to you.

@denrase
Copy link
Collaborator

denrase commented Sep 12, 2023

@humber-z So I took a look and the latter example works as expected. Maybe there are no traces because there are no child spans or you are running on web?

Transactions will be bound to the scope if no other transaction is currently bound to it.

If the transaction has no spans, the transaction will be dropped and not sent to Sentry, the reason is that there's no callback to identify when the screen has been loaded, so we rely on the child spans.

https://docs.sentry.io/platforms/flutter/performance/instrumentation/automatic-instrumentation/?original_referrer=https%3A%2F%2Fwww.google.com%2F

@bahag-mortazavim
Copy link

bahag-mortazavim commented Dec 22, 2023

We are using Flutter(mobile app) and also using the GoRoute package as our navigation package.
based on the Sentry documentations for Setup Flutter and also Automatic Instrumentation, we just need to automatically track the Navigations of the different screen and not the Dio or Http request.
We already set all the configurations up for this purpose based on the documentation as below:

await SentryFlutter.init(
    (options) async {
      options.dsn = !isZebraDevice && Environment.useCrashlytics
          ? 'https://dsn-url'
          : '';
      options.tracesSampleRate = 1;
      options.profilesSampleRate = 0.2;
      options.autoAppStart = true;
      options.enableAutoSessionTracking = true;
      options.enableAutoPerformanceTracing = true;
      options.enableAppLifecycleBreadcrumbs = true;
      options.enableAutoNativeBreadcrumbs = true;
      options.enableBrightnessChangeBreadcrumbs = true;
      options.enableNativeCrashHandling = true;
      options.enableWatchdogTerminationTracking = true;
      options.enablePrintBreadcrumbs = true;
      options.attachStacktrace = true;
      options.enableTracing = true;
      options.environment = Environment.channel;
    },

and also we set the SentryObserver like this:

    static final rootNode = ShellRoute(
    navigatorKey: Constants.shellNavigatorKey,
    builder: (context, state, child) => BaseScreen(child: child),
    observers: [
    SentryNavigatorObserver(),
    ],
    routes: [
      HomeRoutes.homeNode,
      CategoryRoutes.categoryNode,
      CartRoutes.cartNode,
      ProfileRoutes.profileNode,
      LoginRoutes.loginRouteNode,
    ],
  );
}

Now we expect to see at least some data in the Performance section at Sentry Dashboard, but we couldn't get any data until now. Is it possible in Sentry to just track the navigations or it is not possible? Or does SentryObserver works fine with GoRoute ? since we are already using GoogelAnalyticsObserver and it works fine with GoRoute. We are also using the last version of Sentry.
It would be appreciated if you can help us

@buenaflor
Copy link
Contributor

buenaflor commented Dec 22, 2023

Hi, the SentryNavigatorObserver works fine with GoRouter.

Is it possible in Sentry to just track the navigations or it is not possible?

Unfortunately no, if the navigation transaction has no child spans, it will be dropped. the reason is that there's no callback to identify when the screen has been loaded, so we rely on the child spans.

So unless you attach child spans to the navigation transaction after the screen has been pushed Sentry won't send the transaction. This could happen manually or via auto instrumentation

e.g manually:

final activeSpan = Sentry.getSpan();
final childSpan = activeSpan?.startChild('complex operation',
    description: 'running a complex operation');
// do work
childSpan?.finish();

If you still have an issue pls open up a separate issue for better visibility

@buenaflor
Copy link
Contributor

Also If I understand you correctly, I assume you are asking for a Time to Initial Display feature since you only want to track the navigation.

@Ronakmewara
Copy link

We are using Flutter(mobile app) and also using the GoRoute package as our navigation package. based on the Sentry documentations for Setup Flutter and also Automatic Instrumentation, we just need to automatically track the Navigations of the different screen and not the Dio or Http request. We already set all the configurations up for this purpose based on the documentation as below:

await SentryFlutter.init(
    (options) async {
      options.dsn = !isZebraDevice && Environment.useCrashlytics
          ? 'https://dsn-url'
          : '';
      options.tracesSampleRate = 1;
      options.profilesSampleRate = 0.2;
      options.autoAppStart = true;
      options.enableAutoSessionTracking = true;
      options.enableAutoPerformanceTracing = true;
      options.enableAppLifecycleBreadcrumbs = true;
      options.enableAutoNativeBreadcrumbs = true;
      options.enableBrightnessChangeBreadcrumbs = true;
      options.enableNativeCrashHandling = true;
      options.enableWatchdogTerminationTracking = true;
      options.enablePrintBreadcrumbs = true;
      options.attachStacktrace = true;
      options.enableTracing = true;
      options.environment = Environment.channel;
    },

and also we set the SentryObserver like this:

    static final rootNode = ShellRoute(
    navigatorKey: Constants.shellNavigatorKey,
    builder: (context, state, child) => BaseScreen(child: child),
    observers: [
    SentryNavigatorObserver(),
    ],
    routes: [
      HomeRoutes.homeNode,
      CategoryRoutes.categoryNode,
      CartRoutes.cartNode,
      ProfileRoutes.profileNode,
      LoginRoutes.loginRouteNode,
    ],
  );
}

Now we expect to see at least some data in the Performance section at Sentry Dashboard, but we couldn't get any data until now. Is it possible in Sentry to just track the navigations or it is not possible? Or does SentryObserver works fine with GoRoute ? since we are already using GoogelAnalyticsObserver and it works fine with GoRoute. We are also using the last version of Sentry. It would be appreciated if you can help us

did u get any solution?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Development

No branches or pull requests

9 participants