Customizing error reports

In order to quickly reproduce and fix errors, it is often helpful to send additional application-specific diagnostic “metadata” to your Bugsnag dashboard to provide a rich context that is also available for searching and filtering.

You can also amend the events captured by Bugsnag to adjust the information shown on the dashboard and even choose not to send the event at all.

These docs are for the @bugsnag/react-native package, which supports React Native v0.60 and above.

If you’re using the previous bugsnag-react-native package, we recommend upgrading to the latest release, unless you’re using a version of React Native older than 0.60. Documentation for bugsnag-react-native can be found on our legacy pages.

Updating events using callbacks

If you’d like to add diagnostic data to reports, or adjust event data conditionally, you can register a callback to be run before an error is delivered to your Bugsnag dashboard:

Bugsnag.start({
  onError: function (event) {
    // Add additional diagnostic information
    event.addMetadata('account', {
      name: 'Acme Co.',
      paying_customer: true
    })

    // Return `false` if you'd like to stop this error being reported
    return true
  }
})
Configuration config = Configuration.load(this);
config.addOnError(new OnErrorCallback() {
    @Override
    public boolean onError(Event event) {
        // Add additional diagnostic information
        event.addMetadata("account", "name", "Acme Co.");
        event.addMetadata("account", "paying_customer", true);

        // Return `false` if you'd like to stop this error being reported
        return true;
    }
});
Bugsnag.start(this, config);
BugsnagConfiguration *config = [BugsnagConfiguration loadConfig];
[config addOnSendErrorBlock:^BOOL (BugsnagEvent *event) {
    // Add additional diagnostic information
    [event addMetadata:@"Acme Co." withKey:@"name" toSection:@"account"];
    [event addMetadata:@(YES) withKey:@"paying_customer" toSection:@"account"];

    // Return `NO` if you'd like to stop this error being reported
    return YES;
}];
[Bugsnag startWithConfiguration:config];

The callback gives you access to the Event object, so you can inspect and modify the error event which is about to be sent to Bugsnag. The return value from these callbacks allows you to discard an event before it is sent.

Callbacks set in JavaScript will only be triggered for JavaScript errors whereas native callbacks are run for all errors and after any JavaScript callbacks have completed.

JavaScript supports asynchronous onError callbacks.

Crash-time vs. Delivery-time callbacks

In JavaScript and Android, these callbacks are executed at the time of the crash. However due to the runtime restrictions placed on an exception handler in iOS, the OnSendErrorBlock block is executed when the app next launches and has network connectivity. They are invoked on a dedicated background queue, which will be different from the queue where the block was originally added.

This means the state of the app and device are likely to be different to how they were when the crash occurred and so care must be taken when reading or adding external data in a callback on iOS. See Crash-time handler in our iOS guide for information on capturing data during a crash.

NDK callbacks on Android

A callback mechanism is also available for the NDK layer on Android - see Updating events using callbacks in our Android guide for more information.

For more information about adding callbacks and metadata, see our platform-specific guides:

Global metadata

If you have metadata that is applicable to all captured events, it can be set globally on the Bugsnag client and will be set on all subsequently generated events. To ensure that events contain metadata as soon as Bugsnag starts capturing events, use the metadata configuration options.

In JavaScript, this data is added as a map where the top-level key is displayed as a tab in the Bugsnag dashboard:

Bugsnag.start({
  metadata: {
    company: {
      {
        name: 'Acme Co.',
        country: 'uk'
      }
    }
  }
})

In iOS and Android, data is added to a specified “section”, which is displayed as a tab in the Bugsnag dashboard, and can either be added individually or as a map of key-value pairs:

Android:

Configuration config = Configuration.load(this);
config.addMetadata("account", "name", "Acme Co.");
config.addMetadata("basket", new HashMap<String, Object>() {{
  put("delivery", "express");
  put("sale", "spring");
}});
Bugsnag.start(this, config);

iOS:

BugsnagConfiguration *config = [BugsnagConfiguration loadConfig];
[config addMetadata:@"Acme Co." withKey:@"name" toSection:@"account"];
[config addMetadata:@{ @"delivery": @"express", @"sale": @"spring" }
          toSection:@"basket"];
[Bugsnag startWithConfiguration:config];

Feature flags and experiments

If your app uses feature flags or you run experiments you can configure Bugsnag to include feature and experiment membership information, and then use search and segmentation to learn if a particular feature or experiment is the cause of errors.

It is recommended to add feature and experiment membership information in an array and then create an array custom filter in the Bugsnag dashboard:

Bugsnag.start({
  metadata: {
    experiments: {
      experiments: ["new_onboarding", "search_v2", "chat_feature"]
    }
  }
})
Configuration config = Configuration.load(this);
config.addMetadata("experiments", "experiments", new ArrayList<String>() {{
    add("new_onboarding");
    add("search_v2");
    add("chat_feature");
}});
Bugsnag.start(this, config);
BugsnagConfiguration *config = [BugsnagConfiguration loadConfig];
[config addMetadata:@[@"new_onboarding", @"search_v2", @"chat_feature"]
    withKey:@"experiments" toSection:@"experiments"];
[Bugsnag startWithConfiguration:config];

For more information about managing global metadata, see our platform-specific guides:

Adding user data

Information about the user affected by errors can be added to events sent to your Bugsnag dashboard by setting the user ID, email and name in configuration when Bugsnag starts:

Bugsnag.start({ 
  user: {
    id: '3',
    name: 'Bugs Nag',
    email: 'bugs.nag@bugsnag.com'
  }
})
Configuration config = Configuration.load(this);
config.setUser("3", "bugs.nag@bugsnag.com", "Bugs Nag");
Bugsnag.start(this, config);
BugsnagConfiguration *config = [BugsnagConfiguration loadConfig];
[config setUser:@"3" withEmail:@"bugs.nag@bugsnag.com" andName:@"Bugs Nag"];
[Bugsnag startWithConfiguration:config];

When the persistUser configuration option is set to true, this user information will also be set in subsequent application launches.

If the user changes whilst the application is running, for example if a user signs in, you can update the user data on the Bugsnag client for all subsequent events:

Bugsnag.setUser('3', 'bugs.nag@bugsnag.com', 'Bugs Nag')
Bugsnag.setUser("3", "bugs.nag@bugsnag.com", "Bugs Nag");
[Bugsnag setUser:@"3" withEmail:@"bugs.nag@bugsnag.com" andName:@"Bugs Nag"];

Alternatively, you can set the user for each event through a callback. However, please note that iOS callbacks occur on a subsequent launch of the app.

For more information about adding user data, see our platform-specific guides:

You can use metadata to add additional user information to the “user” section.

Setting context

Bugsnag uses the concept of “contexts” to help display and group your errors. The context represents what was happening in your application at the time an error occurs and is given high visual prominence in the dashboard.

By default this is set this to the foreground Activity on Android and the top most UIViewController, code location, or method on iOS. If you would like to set this value manually, you can set it with an initial value in configuration when Bugsnag starts:

Bugsnag.start({ context: 'InitialTutorialStep' })
Configuration config = Configuration.load(this);
config.setContext("InitialTutorialStep");
Bugsnag.start(this, config);
BugsnagConfiguration *config = [BugsnagConfiguration loadConfig];
config.context = @"InitialTutorialStep";
[Bugsnag startWithConfiguration:config];

The context can then be amended on the Bugsnag client as/when it changes for all subsequent events:

Bugsnag.setContext('SecondTutorialStep')
Bugsnag.setContext("SecondTutorialStep");
[Bugsnag setContext:@"SecondTutorialStep"];

Alternatively, you can set the context for each event through a callback. However, please note that iOS callbacks occur on a subsequent launch of the app.

For more information about setting context information, see our platform-specific guides:

The Event object

The event callbacks available to the three libraries provide an “event” parameter that represents an error captured by Bugsnag. The object contains properties and methods for you to query and update the captured data.

For full details, see our platform-specific guides: