bugban_flutter
Crash reporting and performance monitoring for Flutter, from Bugban.
flutter pub add bugban_flutter
import 'package:bugban_flutter/bugban_flutter.dart';
void main() {
BugbanFlutter.run(
options: BugbanOptions(
apiKey: 'bb_your_project_key',
host: 'https://bugban.online',
environment: 'production',
release: '1.0.0',
),
appRunner: () => runApp(const MyApp()),
);
}
Why run and not just init
Flutter has four separate error paths, and an integration that wires up only the obvious one silently misses whole classes of crash:
| Path | Catches |
|---|---|
FlutterError.onError |
errors inside build, layout and paint |
PlatformDispatcher.instance.onError |
uncaught async errors (Flutter 3.3+) |
runZonedGuarded |
everything else on the zone |
Isolate.current.addErrorListener |
crashes on a background isolate |
BugbanFlutter.run installs all four. runZonedGuarded only catches errors
raised inside its callback, so initialising outside the zone and calling
runApp inside it loses async errors without a word — which is why run owns
both steps.
If your app already has its own zone, use BugbanFlutter.init(...) instead and
keep the zone handler yourself:
await BugbanFlutter.init(options);
runZonedGuarded(() => runApp(const MyApp()), (e, s) {
Bugban.capture(e, stackTrace: s, handled: false);
});
Every handler is chained, never replaced. In debug the existing one draws the red screen and in release your app may have its own reporter on it; taking either away silently is not something a monitoring SDK gets to do.
Screen names
MaterialApp(
navigatorObservers: [BugbanNavigatorObserver()],
routes: {'/': (_) => const HomePage(), '/checkout': (_) => const CheckoutPage()},
)
Without it a report names a widget class; with it, it says it broke on
/checkout. The same observer times screen transitions (SCREEN_LOAD).
Screenshots
Off by default, and that default is deliberate: a screenshot is pixels, so once it is taken nothing downstream can tell a password field from any other grey rectangle. Masking has to happen before the capture.
// 1. opt in
BugbanOptions(/* ... */, captureScreenshots: true)
// 2. mark what to capture
RepaintBoundary(key: BugbanScreenshot.rootKey, child: MaterialApp(/* ... */))
// 3. cover what must not be seen
BugbanMask(child: TextField(obscureText: true))
No extra package needed — Flutter's own RepaintBoundary rasterises the tree.
Performance
Core Web Vitals do not translate to a phone; these do:
APP_START— how long until the app is usable. CallBugbanFlutter.markAppReady()when your first screen has its data; if you never do, the first frame is used instead.SCREEN_LOAD— time to move to another screen (from the navigator observer).JANK— the longest stuttering frame.
Offline queue
On by default, backed by shared_preferences. A phone loses signal in a lift
and a crash can end the process before a single request completes, so events
are written to disk before the request goes out and cleared only once the
server has taken them.
Not covered yet
Native crashes (ANR, SIGSEGV) never reach the Dart layer and are not captured. Dart errors, async errors, isolate crashes and caught exceptions all are.
Licence
MIT
Libraries
- bugban_flutter
- Bugban for Flutter.