Skip to content

Installation

View raw .md
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.dart present). 0.0.22 is the first release with Event.listenAny and ReportsBreadcrumb, which the event breadcrumbs call

Installing the Package#

bash
flutter pub add magic_sentry

Or add it manually to pubspec.yaml:

yaml
dependencies:
  magic_sentry: ^0.0.7

Then fetch dependencies:

bash
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:

bash
dart run <app>:artisan plugin:install magic_sentry

The command performs the following steps:

  1. Creates lib/config/sentry.dart from the bundled stub.
  2. Injects SentryServiceProvider into the providers list in lib/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.

dart
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:

dart
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:

  • sendDefaultPii stays false. Flipping it sends the user's IP address and request bodies with every event. An app that needs it enables it in its own configure callback, 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: SentryNetworkInterceptor reports a 5xx or a dead connection (MagicError.statusCode == 0) as an event, a 4xx as a breadcrumb, and deduplicates repeats within a session. See lib/src/sentry_network_interceptor.dart.
  • User context: SentryUserContext<T> follows Auth.stateNotifier; see lib/src/sentry_user_context.dart for 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's DeeplinkOpened and DeeplinkNavigating are two examples. See lib/src/event_breadcrumbs.dart.
esc

Search index did not load.

No match for "".

Try a class like rounded-lg or a widget like WButton.