bugban_flutter 1.1.0 copy "bugban_flutter: ^1.1.0" to clipboard
bugban_flutter: ^1.1.0 copied to clipboard

Bugban crash reporting and performance monitoring for Flutter — Flutter errors, real screenshots, an offline queue and start-up / screen-load timing.

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. Call BugbanFlutter.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

1
likes
130
points
149
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Bugban crash reporting and performance monitoring for Flutter — Flutter errors, real screenshots, an offline queue and start-up / screen-load timing.

Homepage
Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

bugban, device_info_plus, flutter, package_info_plus, shared_preferences

More

Packages that depend on bugban_flutter