Join us in person and online for Firebase Summit on October 18, 2022. Learn how Firebase can help you accelerate app development, release your app with confidence, and scale with ease. Register now

Customize your Firebase Crashlytics crash reports

Stay organized with collections Save and categorize content based on your preferences.

This guide describes how to customize your crash reports using Crashlytics APIs. By default, Crashlytics automatically collects platform-native crash reports for all your app's users (you can also turn off automatic crash reporting and enable opt-in reporting for your users instead). Crashlytics provides five logging mechanisms out of the box: custom keys, custom logs, user identifiers, caught and uncaught exceptions.

For Flutter apps, fatal reports are sent to Crashlytics in real-time without the need for the user to restart the application. Non-fatal reports are written to disk to be sent along with the next fatal report or when the app restarts.

Report uncaught exceptions

You can automatically catch all errors that are thrown within the Flutter framework by overriding FlutterError.onError with FirebaseCrashlytics.instance.recordFlutterFatalError:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await Firebase.initializeApp();

  // Pass all uncaught errors from the framework to Crashlytics.
  FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterFatalError;

  runApp(MyApp());
}

Zoned errors

Not all errors are caught by Flutter. Sometimes, errors are instead caught by Zones. A common case where relying on Flutter to catch errors would not be enough is when an exception happens inside the onPressed handler of a button:

ElevatedButton(
  onPressed: () {
    throw Error();
  }
  ...
)

To catch such errors, you can use runZonedGuarded:

void main() async {
  runZonedGuarded<Future<void>>(() async {
    WidgetsFlutterBinding.ensureInitialized();
    await Firebase.initializeApp();
    // The following lines are the same as previously explained in "Handling uncaught errors"
    FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterFatalError;

    runApp(MyApp());
  }, (error, stack) => FirebaseCrashlytics.instance.recordError(error, stack, fatal: true));
}

Errors outside of Flutter

To catch errors that happen outside of the Flutter context, install an error listener on the current Isolate:

Isolate.current.addErrorListener(RawReceivePort((pair) async {
  final List<dynamic> errorAndStacktrace = pair;
  await FirebaseCrashlytics.instance.recordError(
    errorAndStacktrace.first,
    errorAndStacktrace.last,
    fatal: true,
  );
}).sendPort);

Report caught exceptions

In addition to automatically reporting your app’s crashes, Crashlytics lets you record non-fatal exceptions and sends them to you the next time a fatal event is reported or when the app restarts.

Use the recordError method to record non-fatal exceptions in your app's catch blocks. For example:

await FirebaseCrashlytics.instance.recordError(
  error,
  stackTrace,
  reason: 'a non-fatal error'
);

These exceptions appear as non-fatal issues in the Firebase console. The issue summary contains all the state information you normally get from crashes, along with breakdowns by version and hardware device.

Crashlytics processes exceptions on a dedicated background thread to minimize the performance impact to your app. To reduce your users’ network traffic, Crashlytics will rate-limit the number of reports sent off device, if necessary.

Add custom keys

Custom keys help you get the specific state of your app leading up to a crash. You can associate arbitrary key/value pairs with your crash reports, then use the custom keys to search and filter crash reports in the Firebase console.

  • In the Crashlytics dashboard, you can search for issues that match a custom key.

  • When you're reviewing a specific issue in the console, you can view the associated custom keys for each event (Keys subtab) and even filter the events by custom keys (Filter menu at the top of the page).

Use the setCustomKey instance method to set key/value pairs. Here are some examples:

// Set a key to a string.
FirebaseCrashlytics.instance.setCustomKey('str_key', 'hello');

// Set a key to a boolean.
FirebaseCrashlytics.instance.setCustomKey("bool_key", true);

// Set a key to an int.
FirebaseCrashlytics.instance.setCustomKey("int_key", 1);

// Set a key to a long.
FirebaseCrashlytics.instance.setCustomKey("int_key", 1L);

// Set a key to a float.
FirebaseCrashlytics.instance.setCustomKey("float_key", 1.0f);

// Set a key to a double.
FirebaseCrashlytics.instance.setCustomKey("double_key", 1.0);

Add custom log messages

To give yourself more context for the events leading up to a crash, you can add custom Crashlytics logs to your app. Crashlytics associates the logs with your crash data and displays them in the Firebase console, under the Crashlytics Logs tab.

Use log to help pinpoint issues. For example:

FirebaseCrashlytics.instance.log("Higgs-Boson detected! Bailing out");

Set user identifiers

To diagnose an issue, it’s often helpful to know which of your users experienced a given crash. Crashlytics includes a way to anonymously identify users in your crash reports.

To add user IDs to your reports, assign each user a unique identifier in the form of an ID number, token, or hashed value:

FirebaseCrashlytics.instance.setUserIdentifier("12345");

If you ever need to clear a user identifier after you set it, reset the value to a blank string. Clearing a user identifier does not remove existing Crashlytics records. If you need to delete records associated with a user ID, contact Firebase support.

Enable opt-in reporting

By default, Crashlytics automatically collects crash reports for all your app's users. To give users more control over the data they send, you can enable opt-in reporting by disabling automatic reporting and only sending data to Crashlytics when you choose to in your code:

  1. Turn off automatic collection natively:

    Apple platforms

    Add a new key to your Info.plist file:

    • Key: FirebaseCrashlyticsCollectionEnabled
    • Value: false

    Android

    In the application block of your AndroidManifest.xml file, add a meta-data tag to turn off automatic collection:

    <meta-data
        android:name="firebase_crashlytics_collection_enabled"
        android:value="false" />
    
  2. Enable collection for select users by calling the Crashlytics data collection override at runtime.

    The override value persists across launches of your app so Crashlytics can automatically collect reports. To opt out of automatic crash reporting, pass false as the override value. When set to false, the new value does not apply until the next run of the app.

    FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true);
    

Manage Crash Insights data

Crash Insights helps you resolve issues by comparing your anonymized stack traces to traces from other Firebase apps and letting you know if your issue is part of a larger trend. For many issues, Crash Insights even provides resources to help you debug the crash.

Crash Insights uses aggregated crash data to identify common stability trends. If you’d prefer not to share your app's data, you can opt-out of Crash Insights from the Crash Insights menu at the top of your Crashlytics issue list in the Firebase console.