flutter_sentry 0.3.3

  • Readme
  • Changelog
  • Example
  • Installing
  • 88

pub package flutter build code coverage

NOTE: While sentry package provides a low-level functionality to report exceptions from Dart/Flutter code, flutter_sentry plugin (which also uses sentry package behind the scenes!) aims at full integration with Flutter ecosystem, automatically including Flutter application details in reports and catching crashes in native code, including other Flutter plugins and Flutter itself.

Setup #

  1. Add flutter_sentry to your pubspec.yaml:

    dependencies:
      flutter_sentry: ^0.3.3
    
  2. Find out a DSN value from Sentry.io and add it to native platforms:

    NOTE: if you forget to add DSN to the platform code, or do it incorrectly, the application will encounter a fatal crash on startup on that platform.

    • iOS: in ios/Runner/Info.plist:

      <dict>
        ... existing configuration parameters ...
        <key>SentryDSN</key>
        <string>value you got from sentry.io</string>
      </dict>
      
    • Android: in android/app/src/main/AndroidManifest.xml:

      <application>
        <meta-data
            android:name="io.sentry.dsn"
            android:value="value you got from sentry.io" />
      

      You can also enable debug logging for Sentry Android library if it's not working as intended:

        <meta-data
            android:name="io.sentry.debug"
            android:value="true" />
      

      NOTE: make sure to add <meta-data> tag directly under <application> (and not for example <activity>).

  3. Finally, wrap your runApp() call in FlutterSentry.wrap() like this:

    import 'package:flutter_sentry/flutter_sentry.dart';
    
    Future<void> main() => FlutterSentry.wrap(
         () async {
           // Optionally other initializers, like Firebase.
    
           runApp(App());
         },
         dsn: 'value you got from sentry.io',
       );
    

Why do I have to specify DSN in multiple places? #

You might be wondering why a DSN value can't be specified in a single place and then exchanged between platforms and Dart/Flutter code via a MethodChannel. The reason for that is, native code and Flutter initialize in parallel, before MethodChannel is available, and if a crash happens before MethodChannel is ready... that part of application is on its own.

That said, we want to minimize the installation burden. While the plugin is still in development, we may eventually introduce a way to configure the value once and have it copied to all platforms at build time. Stay tuned!

0.3.3 #

  • Always add stackTrace for captureException, using StackTrace.current if unset.
  • Put ErrorSummary.value diagnostics node into message when FlutterError is passed to captureException.

0.3.2 #

  • Fix detection of flutter_driver for events other than the first.
  • Add locale to environmentAttributes in FlutterSentry.wrap().

0.3.1 #

  • Do not report "arguments: null" in breadcrumb for a route without arguments.
  • Add FlutterSentry.initializeWithClient() method to share an existing SentryClient and to use in tests.
  • Add extra to FlutterSentry.captureException() for supplying additional event-related data.

0.3.0 #

  • Add timezone and screen dimensions to report.
  • Do not require FlutterSentry.wrap<T>() template parameter T to be a Future.
  • Intercept print() via ZoneSpecification instead of overriding debugPrint() which is only a wrapper around print().
  • Add userContext on FlutterSentry.instance which allows setting custom context. It does not propagate to platform code (yet), so fatal exceptions will still lack this data.
  • Try to get most recent device parameters (such as screen size) at the time of reporting an error, and fall back to the values fetched at initialize().
  • Use FlutterSentry.instance.breadcrumbs as a breadcrumb tracker for navigator observer, if unspecified.
  • Add "app" context (including app name and version) to events reported via captureException().
  • Add "os" context to events reported via captureException().
  • Detect "driver" environment for flutter_driver.

0.2.1 #

  • Update README with new flutter_sentry version.
  • Filter package:flutter stack trace frames by default.
  • Remove the use of deprecated method getFlutterEngine.

0.2.0 #

  • Intercept debugPrint() in wrap() and add the message to breadcrumbs for the next event to upload.
  • Enable environment attributes in Dart exceptions.

0.1.0 #

  • Remove pubspec.lock from version control.
  • Add FlutterSentry.breadcrumbs tracker to save a limited number of most recent breadcrumbs, which will be sent to Sentry.io with the next error report.
  • Add FlutterSentryNavigatorObserver allowing to track navigation events in application.
  • Send device information to Sentry.io when reporting an event.

0.0.2 #

  • Add initilize method with dsn to init SentryClient.
  • Make FlutterSentry a Singleton.

0.0.1+2 #

  • Update examples in README.
  • Update plugin description.
  • Add API documentation.

0.0.1+1 #

  • Add badges to README.

0.0.1 #

  • Initial release.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter_sentry/flutter_sentry.dart';
import 'package:sentry/sentry.dart';

void main() => FlutterSentry.wrap(
      () {
        runApp(const MyApp());
      },
      dsn: 'https://420a0b0766e9450fbd3a456346c6eed2@sentry.io/1867468',
    );

/// Main application widget class.
@immutable
class MyApp extends StatelessWidget {
  /// New instance of MyApp widget.
  const MyApp({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) => MaterialApp(
        navigatorObservers: [
          FlutterSentryNavigatorObserver(),
        ],
        home: Scaffold(
          appBar: AppBar(
            title: const Text('Flutter Sentry plugin example app'),
          ),
          body: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 40),
            child: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: <Widget>[
                  RaisedButton(
                    onPressed: () {
                      FlutterSentry.instance.userContext = const User(
                        id: '0123456789',
                        email: 'test@example.com',
                        extras: <String, dynamic>{
                          // This can be anything you like.
                          'purchased': true,
                          'signInMethod': 'Anonymous',
                          'currentConfig': {
                            'minApplicationVersion': '2.5',
                            'sharingFeatureEnabled': false,
                          },
                        },
                      );
                    },
                    child: const Text('Sign in'),
                  ),
                  const Divider(),
                  const RaisedButton(
                    onPressed: FlutterSentry.nativeCrash,
                    child: Text('Cause a native crash'),
                  ),
                  RaisedButton(
                    onPressed: () => FlutterSentry.instance.captureException(
                      exception: Exception('Event'),
                      extra: <String, dynamic>{
                        'extra Data': 'hello, world!',
                      },
                    ),
                    child: const Text('Report an event to Sentry.io'),
                  ),
                  const Center(
                    child: Padding(
                      padding: EdgeInsets.symmetric(vertical: 10),
                      child: Text('The following works in release mode only:'),
                    ),
                  ),
                  RaisedButton(
                    onPressed: () {
                      debugPrint('Throwing an uncaught exception');
                      throw Exception('Uncaught exception');
                    },
                    child: const Text('Throw uncaught exception'),
                  ),
                  RaisedButton(
                    onPressed: () {
                      // Will fail because Scaffold is below current context:
                      // https://link.medium.com/TyUYuWoer5.
                      Scaffold.of(context);
                    },
                    child: const Text('Cause and report a FlutterError'),
                  ),
                ],
              ),
            ),
          ),
        ),
      );
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  flutter_sentry: ^0.3.3

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:flutter_sentry/flutter_sentry.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
76
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
88
Learn more about scoring.

We analyzed this package on Apr 6, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.7.1
  • pana: 0.13.6
  • Flutter: 1.12.13+hotfix.8

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.1.0 <3.0.0
device_info ^0.4.1 0.4.2+1
flutter 0.0.0
package_info >=0.4.0 <2.0.0 0.4.0+16
sentry ^3.0.1 3.0.1
Transitive dependencies
async 2.4.1
charcode 1.1.3
collection 1.14.11 1.14.12
http 0.12.0+4
http_parser 3.1.4
meta 1.1.8
path 1.6.4
pedantic 1.9.0
sky_engine 0.0.99
source_span 1.7.0
stack_trace 1.9.3
string_scanner 1.0.5
term_glyph 1.1.0
typed_data 1.1.6
usage 3.4.1
vector_math 2.0.8
Dev dependencies
flutter_test
mockito ^3.0.0
test ^1.9.4