OnCall Error Tracking SDK for Dart and Flutter

pub package pub points likes popularity

Platform Supported
Android yes
iOS yes
Web yes
macOS yes
Windows yes
Linux yes

Capture and report errors from your Dart and Flutter applications to OnCall. OnCall's error tracking gives you full visibility into crashes and exceptions across all your apps with smart grouping, stack traces, breadcrumbs, and real-time alerts.

Features

  • Automatic error capture via FlutterError.onError and PlatformDispatcher.onError
  • Zone-based async error catching with runZonedGuarded — catches errors that escape try/catch
  • Navigation breadcrumbs via OnCallNavigatorObserver — see the user's route history leading up to a crash
  • Manual capturecaptureException() and captureMessage() for handled errors and diagnostics
  • Rich context — attach user info, tags, and custom data to every event
  • Breadcrumbs — ring buffer of 100 recent actions (navigation, HTTP, custom) sent with each error
  • Sampling — control volume with sampleRate (0.0–1.0)
  • beforeSend hook — filter or modify events before they leave the device
  • Retry with backoff — automatic retry (3x exponential backoff) on network failure
  • 429 rate limit handling — respects Retry-After headers from the server
  • Lightweight — ~8KB compressed, zero native dependencies

Getting Started

1. Install

dependencies:
  oncall_error_tracking: ^0.1.0

Then run:

flutter pub get

2. Get Your DSN

Create a project in OnCall under Developer Tools → Error Tracking → Projects. Copy the DSN — it looks like:

https://{publicKey}@errors.oncallteams.com/api/{projectId}/store

3. Initialize

import 'package:flutter/material.dart';
import 'package:oncall_error_tracking/oncall_error_tracking.dart';

void main() {
  final client = OnCallClient.init(OnCallOptions(
    dsn: 'https://{key}@errors.oncallteams.com/api/{projectId}/store',
    environment: 'production',
    release: '1.0.0+1',
  ));

  // Install Flutter framework error handler
  installFlutterErrorHandler(client);

  // Wrap your app in a zone to catch async errors
  runWithOnCall(client, () {
    runApp(MyApp());
  });
}

That's it — errors are now automatically captured and sent to OnCall.

Usage

Capture Exceptions Manually

For errors you handle in try/catch but still want to track:

try {
  await riskyOperation();
} catch (exception, stackTrace) {
  await OnCallClient.instance?.captureException(
    exception,
    stackTrace: stackTrace,
  );
}

Capture Messages

Log diagnostic messages at any level:

await OnCallClient.instance?.captureMessage(
  'User completed onboarding',
  level: 'info',
);

await OnCallClient.instance?.captureMessage(
  'Payment retry failed after 3 attempts',
  level: 'warning',
);

Set User Context

Identify the user so you can see which users are affected:

OnCallClient.instance?.setUser({
  'id': user.id,
  'email': user.email,
  'username': user.displayName,
});

Add Tags

Tags are indexed and searchable in the dashboard:

OnCallClient.instance?.setTag('plan', 'premium');
OnCallClient.instance?.setTag('locale', 'ar-KW');

Add Breadcrumbs

Breadcrumbs help you understand what the user did before the crash:

OnCallClient.instance?.addBreadcrumb(
  category: 'api',
  message: 'GET /api/orders returned 200',
  level: 'info',
  data: {'status': 200, 'duration_ms': 142},
);

Add OnCallNavigatorObserver to automatically track route changes:

MaterialApp(
  navigatorObservers: [
    OnCallNavigatorObserver(OnCallClient.instance!),
  ],
  // ...
);

Every push, pop, replace, and remove is recorded as a breadcrumb. When an error occurs, you'll see the full navigation history in your dashboard.

Configuration

All options are set via OnCallOptions:

final client = OnCallClient.init(OnCallOptions(
  // Required
  dsn: 'https://{key}@errors.oncallteams.com/api/{projectId}/store',

  // Environment (default: 'production')
  environment: 'production',

  // Release version (recommended — enables release tracking)
  release: '1.2.0+42',

  // Sample rate: 0.0 to 1.0 (default: 1.0 = 100%)
  sampleRate: 1.0,

  // Max breadcrumbs to keep (default: 100)
  maxBreadcrumbs: 100,

  // Max network retries (default: 3)
  maxRetries: 3,

  // Debug mode — logs SDK activity to console (default: false)
  debug: false,

  // Filter or modify events before sending
  beforeSend: (event) {
    // Drop events from specific screens
    // Return null to discard, or return a modified event
    return event;
  },
));

Tips for Catching Errors

Dart and Flutter have several error boundaries. For comprehensive coverage:

Error type How to catch This SDK
Flutter framework errors (build, layout, paint) FlutterError.onError installFlutterErrorHandler()
Uncaught async errors runZonedGuarded runWithOnCall()
Synchronous errors try/catch captureException()
Future errors .catchError() or try/catch with await captureException()
Platform errors (iOS/Android) PlatformDispatcher.instance.onError Covered by runWithOnCall()

For maximum coverage, combine all three in your main():

void main() {
  final client = OnCallClient.init(OnCallOptions(
    dsn: 'YOUR_DSN_HERE',
  ));

  installFlutterErrorHandler(client);

  runWithOnCall(client, () {
    runApp(MyApp());
  });
}

Requirements

Requirement Version
Dart SDK >= 3.0.0
Flutter >= 3.10.0
http ^1.0.0

Resources