Error Reporting

Error Reporting With Sentry

Introduction

While one always tries to create apps that are free of bugs, they’re sure to crop up from time to time. Since buggy apps lead to unhappy users and customers, it’s important to understand how often your users experience bugs and where those bugs occur. That way, you can prioritize the bugs with the highest impact and work to fix them.

Whenever an error occurs, create a report containing the error that occurred and the associated stack trace. You can then send the report to an error tracking service, such as Sentry, Rollbar, or Firebase Crashlytics.

The error tracking service aggregates all of the crashes your users experience and groups them together. This allows you to know how often your app fails and where your users run into trouble.

In this guide, learn how to report Stream Chat errors to the Sentry crash reporting service using the following steps.

1. Get a DSN From Sentry

Before reporting errors to Sentry, you need a “DSN” to uniquely identify your app with the Sentry service: To get a DSN, use the following steps:

2. Import the Sentry package

Import the sentry_flutter package into your app. The sentry package makes it easier to send error reports to the Sentry error tracking service.

dependencies:
  sentry_flutter: <latest_version>

3. Initialize the Sentry SDK

Initialize the SDK to capture different unhandled errors automatically.

import 'package:sentry_flutter/sentry_flutter.dart';

Future<void> main() async {
  await SentryFlutter.init(
    (options) => options.dsn = 'https://example@sentry.io/example',
    appRunner: () => runApp(const MyApp()),
  );
}

Or, if you want to run your app in your own error zone, use runZonedGuarded:

void main() async {
  /// Captures errors reported by the Flutter framework.
  FlutterError.onError = (FlutterErrorDetails details) {
    if (kDebugMode) {
      // In development mode, simply print to console.
      FlutterError.dumpErrorToConsole(details);
    } else {
      // In production mode, report to the application zone to report to Sentry.
      Zone.current.handleUncaughtError(details.exception, details.stack!);
    }
  };

  Future<void> _reportError(dynamic error, StackTrace stackTrace) async {
    // Print the exception to the console.
    if (kDebugMode) {
      // Print the full stack trace in debug mode.
      print(stackTrace);
      return;
    } else {
      // Send the Exception and Stacktrace to sentry in Production mode.
      await Sentry.captureException(error, stackTrace: stackTrace);
    }
  }

  runZonedGuarded(
    () async {
      await SentryFlutter.init(
        (options) => options.dsn = 'https://example@sentry.io/example',
      );
      runApp(const MyApp());
    },
    _reportError,
  );
}

Alternatively, you can pass the DSN to Flutter using the dart-define tag:

--dart-define SENTRY_DSN=https://example@sentry.io/example

4. Integration With StreamChat Applications

Override the default logHandlerFunction to send errors to Sentry.

void sampleAppLogHandler(LogRecord record) async {
  if (kDebugMode) StreamChatClient.defaultLogHandler(record);

  // Report errors to Sentry
  if (record.error != null || record.stackTrace != null) {
    await Sentry.captureException(
      record.error,
      stackTrace: record.stackTrace,
    );
  }
}

StreamChatClient buildStreamChatClient(
  String apiKey, {
  Level logLevel = Level.SEVERE,
}) {
  return StreamChatClient(
    apiKey,
    logLevel: logLevel,
    logHandlerFunction: sampleAppLogHandler, // Pass the overridden logHandlerFunction
  );
}

5. Capture Errors Programmatically

Besides the automatic error reporting that Sentry generates by importing and initializing the SDK, you can use the API to manually report errors to Sentry:

await Sentry.captureException(exception, stackTrace: stackTrace);

For more information, see the Sentry API docs on Pub.

Complete Example

To view a working example, see the Stream Sample app.

Learn More

Extensive documentation about using the Sentry SDK can be found on Sentry’s site.

© Getstream.io, Inc. All Rights Reserved.