Skip to content

Commit 37befa3

Browse files
denrasebuenaflor
andauthored
docs(flutter): Update Flutter routing instrumentation for Router, GoRouter, and AutoRoute (#17153)
<!-- Use this checklist to make sure your PR is ready for merge. You may delete any sections you don't need. --> ## DESCRIBE YOUR PR Expands the routing instrumentation docs to cover all Flutter navigation approaches: imperative Navigator, declarative Router API, GoRouter, and auto_route. Clarifies that GoRouter falls back to the route path when no name is set, and that auto_route generates route names automatically. Closes getsentry/sentry-dart#3565 Closes getsentry/sentry-dart#3590 ## IS YOUR CHANGE URGENT? Help us prioritize incoming PRs by letting us know when the change needs to go live. - [ ] Urgent deadline (GA date, etc.): <!-- ENTER DATE HERE --> - [ ] Other deadline: <!-- ENTER DATE HERE --> - [x] None: Not urgent, can wait up to 1 week+ ## SLA - Teamwork makes the dream work, so please add a reviewer to your PRs. - Please give the docs team up to 1 week to review your PR unless you've added an urgent due date to it. Thanks in advance for your help! ## PRE-MERGE CHECKLIST *Make sure you've checked the following before merging your changes:* - [ ] Checked Vercel preview for correctness, including links - [ ] PR was reviewed and approved by any necessary SMEs (subject matter experts) - [ ] PR was reviewed and approved by a member of the [Sentry docs team](https://github.com/orgs/getsentry/teams/docs) --------- Co-authored-by: Giancarlo Buenaflor <giancarlo_buenaflor@yahoo.com>
1 parent fa6fba0 commit 37befa3

1 file changed

Lines changed: 126 additions & 20 deletions

File tree

includes/dart-integrations/routing-instrumentation.mdx

Lines changed: 126 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ platforms:
1111
---
1212

1313
Sentry's routing instrumentation for Flutter automatically tracks and reports page navigation events in your app.
14-
It supports both [traditional Flutter routing](https://docs.flutter.dev/ui/navigation) and the [GoRouter](https://pub.dev/packages/go_router) package.
14+
It supports imperative navigation (`Navigator.push()`), the declarative `Router` API (`MaterialApp.router`), and popular routing packages like [GoRouter](https://pub.dev/packages/go_router) and [auto_route](https://pub.dev/packages/auto_route).
1515

1616
<Alert>
1717

@@ -29,11 +29,12 @@ Before starting, ensure:
2929

3030
## Configure
3131

32-
### 1. Add `SentryNavigationObserver`
32+
### 1. Add `SentryNavigatorObserver`
3333

34-
Add an instance of `SentryNavigationObserver` to your application's `navigatorObservers`.
34+
How you add `SentryNavigatorObserver` depends on which navigation approach you use.
3535

36-
```dart {14-16} {tabTitle: Flutter Routing}
36+
37+
```dart {14-16} {tabTitle: Navigator}
3738
import 'package:flutter/material.dart';
3839
import 'package:sentry_flutter/sentry_flutter.dart';
3940
@@ -56,6 +57,52 @@ class MyApp extends StatelessWidget {
5657
}
5758
```
5859

60+
```dart {15} {tabTitle: Router}
61+
import 'package:flutter/material.dart';
62+
import 'package:sentry_flutter/sentry_flutter.dart';
63+
64+
// When using a custom RouterDelegate, pass the observer
65+
// to the Navigator you build inside the delegate's build() method.
66+
class MyRouterDelegate extends RouterDelegate<MyRoutePath>
67+
with ChangeNotifier, PopNavigatorRouterDelegateMixin<MyRoutePath> {
68+
@override
69+
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
70+
71+
@override
72+
Widget build(BuildContext context) {
73+
return Navigator(
74+
key: navigatorKey,
75+
observers: [SentryNavigatorObserver()],
76+
pages: [
77+
// Your pages based on app state
78+
],
79+
onDidRemovePage: (page) {
80+
// Update your app state based on the removed page
81+
notifyListeners();
82+
},
83+
);
84+
}
85+
86+
// ... implement setNewRoutePath and other required methods
87+
}
88+
89+
Future<void> main() async {
90+
await SentryFlutter.init((options) {
91+
options.dsn = '___DSN___';
92+
}, appRunner: () => runApp(SentryWidget(child: MyApp())));
93+
}
94+
95+
class MyApp extends StatelessWidget {
96+
@override
97+
Widget build(BuildContext context) {
98+
return MaterialApp.router(
99+
routerDelegate: MyRouterDelegate(),
100+
routeInformationParser: MyRouteInformationParser(),
101+
);
102+
}
103+
}
104+
```
105+
59106
```dart {9} {tabTitle: GoRouter}
60107
import 'package:flutter/material.dart';
61108
import 'package:sentry_flutter/sentry_flutter.dart';
@@ -82,54 +129,101 @@ class MyApp extends StatelessWidget {
82129
);
83130
}
84131
}
132+
```
133+
134+
```dart {19-21} {tabTitle: AutoRoute}
135+
import 'package:flutter/material.dart';
136+
import 'package:sentry_flutter/sentry_flutter.dart';
137+
import 'package:auto_route/auto_route.dart';
85138
139+
// Your generated router
140+
final _appRouter = AppRouter();
141+
142+
Future<void> main() async {
143+
await SentryFlutter.init((options) {
144+
options.dsn = '___DSN___';
145+
}, appRunner: () => runApp(SentryWidget(child: MyApp())));
146+
}
147+
148+
class MyApp extends StatelessWidget {
149+
@override
150+
Widget build(BuildContext context) {
151+
return MaterialApp.router(
152+
routerConfig: _appRouter.config(
153+
navigatorObservers: () => [
154+
SentryNavigatorObserver(),
155+
],
156+
),
157+
);
158+
}
159+
}
86160
```
87161

88162
### 2. Define Route Names
89163

90-
By default the application's main route name is `"/"`.
91-
The instrumentation sets the span `operation` to `navigation` and the span `name` to the provided route name.
92-
For transactions to be created and breadcrumbs to be added when navigation changes, you need to provide route names:
164+
The instrumentation sets the span `operation` to `ui.load` and the span `name` to the provided route name.
93165

94-
- Flutter routing: use `RouteSettings` and set the name in the constructor.
95-
- GoRouter: use the `name` parameter to set the route name.
166+
How you define route names depends on your navigation approach:
167+
168+
- **Navigator (imperative)**: Pass a `name` in the `RouteSettings` when pushing routes.
169+
- **Router**: Set the `name` on the `Page` objects you return in your `pages` list (for example, `MaterialPage(name: 'My Widget', child: ...)`).
170+
- **GoRouter**: GoRouter automatically uses the route `path` as the name. You can optionally set the `name` parameter on your `GoRoute` to override it.
171+
- **auto_route**: Route names are generated automatically from your `@RoutePage()` annotations — no extra configuration needed.
96172

97173
<Alert>
98174

99-
Make sure that you set the route name for all routes.
100-
If you do not set the route name, the SDK will not instrument performance insights such as [TTID](/platforms/dart/guides/flutter/integrations/routing-instrumentation/#time-to-initial-display) or [TTFD](/platforms/dart/guides/flutter/integrations/routing-instrumentation/#time-to-full-display) or create breadcrumbs for the route.
175+
If the SDK cannot determine a route name, it will not create transactions, breadcrumbs, or performance insights such as [TTID](/platforms/dart/guides/flutter/integrations/routing-instrumentation/#time-to-initial-display) or [TTFD](/platforms/dart/guides/flutter/integrations/routing-instrumentation/#time-to-full-display) for that route.
101176

102177
</Alert>
103178

104-
```dart {tabTitle: Flutter Routing}
179+
```dart {3} {tabTitle: Navigator}
105180
MaterialPageRoute(
106181
builder: (BuildContext context) => MyWidget(),
107182
settings: RouteSettings(name: 'My Widget'),
108183
)
109184
```
110185

111-
```dart {tabTitle: GoRouter}
112-
GoRoute(
113-
path: 'mywidget',
186+
```dart {3} {tabTitle: Router}
187+
// Set the name on the Page objects in your RouterDelegate's pages list.
188+
MaterialPage(
114189
name: 'My Widget',
190+
child: MyWidget(),
191+
)
192+
```
193+
194+
```dart {4-5} {tabTitle: GoRouter}
195+
// The path is used as the route name by default.
196+
// You can optionally set name to override it.
197+
GoRoute(
198+
path: '/mywidget',
199+
name: 'My Widget', // optional, falls back to path
115200
builder: (BuildContext context, GoRouterState state) {
116201
return const MyWidget();
117202
}
118203
)
119204
```
120205

206+
```dart {3} {tabTitle: AutoRoute}
207+
// Route names are auto-generated from your page annotations.
208+
// No additional configuration is needed.
209+
@RoutePage()
210+
class MyWidgetPage extends StatelessWidget {
211+
// ...
212+
}
213+
```
214+
121215
## Time to Initial Display
122216

123-
Time to initial display (TTID) provides insight into how long it takes your Widget to launch and draw their first frame.
124-
This is measured by adding a span for navigation to a Widget.
217+
Time to initial display (TTID) provides insight into how long it takes your Widget to launch and draw their first frame.
218+
This is measured by adding a span for navigation to a Widget.
125219
The SDK then sets the span operation to `ui.load.initial-display` and the span description to the Widget's route name, followed by initial display (for example, `MyWidget initial display`).
126220

127221
TTID is enabled by default.
128222

129223
## Time to Full Display
130224

131-
Time to full display (TTFD) provides insight into how long it would take your Widget to launch and load all of its content.
132-
This is measured by adding a span for each navigation to a Widget.
225+
Time to full display (TTFD) provides insight into how long it would take your Widget to launch and load all of its content.
226+
This is measured by adding a span for each navigation to a Widget.
133227
The SDK then sets the span operation to `ui.load.full-display` and the span description to the Widget's route name, followed by full display (for example, `MyWidget full display`).
134228

135229
TTFD is disabled by default. To enable TTFD measurements, follow these steps:
@@ -255,7 +349,7 @@ class MyWidgetState extends State<MyWidget> {
255349

256350
Use the navigator to transition to your widget. This should create and send a transaction named after the widget's route.
257351

258-
```dart {tabTitle: Flutter Routing}
352+
```dart {tabTitle: Navigator}
259353
import 'package:flutter/material.dart';
260354
import 'my_widget.dart';
261355
@@ -269,13 +363,25 @@ Navigator.push(
269363
);
270364
```
271365

366+
```dart {tabTitle: Router}
367+
// Update your delegate's state to trigger a page change.
368+
final delegate = Router.of(context).routerDelegate as MyRouterDelegate;
369+
delegate.showDetail();
370+
```
371+
272372
```dart {tabTitle: GoRouter}
273373
import 'package:go_router/go_router.dart';
274374
import 'package:sentry_flutter/sentry_flutter.dart';
275375
276376
context.push('/mywidget')
277377
```
278378

379+
```dart {tabTitle: AutoRoute}
380+
import 'package:auto_route/auto_route.dart';
381+
382+
context.pushRoute(const MyWidgetRoute());
383+
```
384+
279385
Log into [sentry.io](https://sentry.io) and open your project's performance page to see the transaction `MyWidget`.
280386

281387
## Additional Configuration

0 commit comments

Comments
 (0)