Installation
On this page
Introduction#
magic_sentry wires Sentry into a Magic application: a
web-safe zone-wrapped boot, HTTP failure reporting for magic's Http facade
(which never throws), a scope user kept in step with Auth.stateNotifier,
and a navigator observer on MagicRouter.
Sentry has to start BEFORE Magic.init, so a failure during boot is reported
too. That is the one place this package's install differs from a typical
Magic plugin: there is no magic.config_factory entry, because Config is
not loaded yet at the point Sentry needs its DSN.
Requirements#
- Dart SDK: 3.12.0 or higher
- Flutter: 3.44.0 or higher
- Magic Framework 0.0.22 or higher, installed and bootstrapped (
lib/config/app.dartpresent). 0.0.22 is the first release withEvent.listenAnyandReportsBreadcrumb, which the event breadcrumbs call
Installing the Package#
flutter pub add magic_sentry
Or add it manually to pubspec.yaml:
dependencies:
magic_sentry: ^0.0.7
Then fetch dependencies:
flutter pub get
Running the Install Command#
This package ships no package-specific CLI provider; fluttersdk_artisan's
generic manifest installer reads its install.yaml directly:
dart run <app>:artisan plugin:install magic_sentry
The command performs the following steps:
- Creates
lib/config/sentry.dartfrom the bundled stub. - Injects
SentryServiceProviderinto theproviderslist inlib/config/app.dart.
Wiring main()#
MagicSentry.run replaces the whole body of main(). It opens one zone,
initialises Sentry's widgets binding (SentryWidgetsFlutterBinding, which
frame tracking needs), loads .env, then starts Sentry and hands control to
your existing boot function as appRunner. Do not call
WidgetsFlutterBinding.ensureInitialized() before it: a binding that already
exists is kept, and frame tracking then disables itself.
import 'package:flutter/material.dart';
import 'package:magic/magic.dart';
import 'package:magic_sentry/magic_sentry.dart';
import 'config/app.dart';
import 'config/sentry.dart'; // injected by install
void main() {
MagicSentry.run(configure: configureSentry, appRunner: _boot);
}
Future<void> _boot() async {
// Tags a build error that replaced the interface, distinguishing it from
// an exception that merely got logged. Call it before the first widget
// builds.
MagicSentry.installErrorWidgetBreadcrumb();
await Magic.init(
configFactories: [
() => appConfig,
],
);
runApp(MagicApplication(title: 'My App'));
}
configureSentry comes from the published lib/config/sentry.dart and reads
.env directly (see Configuration Reference
below). Write your own configure callback instead when the standard keys
are not enough.
Registering the Service Provider#
If you ran plugin:install, the provider was already injected with no type
argument and no user callbacks, which is a valid, working default (the
network interceptor and the navigator observer wire up; user reporting is
skipped). Edit lib/config/app.dart to add your own user model:
import 'package:magic/magic.dart';
import 'package:magic_sentry/magic_sentry.dart'; // injected by install
import '../app/models/user.dart';
final appConfig = {
'app': {
'providers': [
(app) => RouteServiceProvider(app),
(app) => AppServiceProvider(app),
(app) => SentryServiceProvider<User>(
app,
userId: (user) => user.id,
userEmail: (user) => user.email,
// Optional: anything else worth tagging once a user is reported.
userExtras: (user) => {
if (user.currentTeam?.id case final String teamId)
'team_id': teamId,
},
), // injected by install, edit the type argument and callbacks by hand
],
},
};
Configuration Reference#
The generated lib/config/sentry.dart reads these .env keys:
| Key | Default | Purpose |
|---|---|---|
SENTRY_DSN |
'' (disabled) |
Your project's DSN. Empty leaves the SDK inert; appRunner still runs. |
SENTRY_ENVIRONMENT |
'local' |
Tags every event, e.g. production, staging. |
SENTRY_RELEASE |
'' (unset) |
Attached to every event. Required on web, which has no package manifest to auto-detect a release from; set it via --dart-define at build time. |
SENTRY_TRACES_SAMPLE_RATE |
0.2 |
Fraction of transactions traced. Client spans continue into the API through sentry_dio's propagated sentry-trace header, so raising this multiplies server spans too. |
Two things configureSentry does NOT read from .env, on purpose:
sendDefaultPiistaysfalse. Flipping it sends the user's IP address and request bodies with every event. An app that needs it enables it in its ownconfigurecallback, explicitly, rather than through a stray environment variable.- Session replay is never enabled. It has no Flutter web implementation and its own PII review; add it yourself if your app needs it.
Release Health#
configureSentry turns on enableAutoSessionTracking, but a session is only
recorded when SentryNavigatorObserver sees a NAMED route change (it reads
RouteSettings.name). SentryServiceProvider registers the observer for
you; make sure your own routes carry a name, or release health silently
stays empty while error reporting keeps working.
Next Steps#
- HTTP reporting:
SentryNetworkInterceptorreports a 5xx or a dead connection (MagicError.statusCode == 0) as an event, a 4xx as a breadcrumb, and deduplicates repeats within a session. Seelib/src/sentry_network_interceptor.dart. - User context:
SentryUserContext<T>followsAuth.stateNotifier; seelib/src/sentry_user_context.dartfor the id/email/extras contract. - Event breadcrumbs: any package or app event that implements magic's
ReportsBreadcrumb(breadcrumbCategory,breadcrumbMessage,breadcrumbData) shows up in the breadcrumb trail automatically, no extra wiring required.magic_deeplink'sDeeplinkOpenedandDeeplinkNavigatingare two examples. Seelib/src/event_breadcrumbs.dart.