Customizing breadcrumbs

This guide explains adding custom breadcrumbs to improve error reproduction steps and removing unneeded automatic breadcrumbs.

This documentation is for version 4 of the BugSnag Android notifier. We recommend upgrading to the latest release using our Upgrade guide. Documentation for the current release can be found here.

In order to understand what happened in your application before each crash, it can be helpful to leave short log statements that we call breadcrumbs. The last several breadcrumbs are attached to a crash to help diagnose what events lead to the error.

Breadcrumbs for common actions and device changes are captured by default.

Adding custom breadcrumbs

Append simple breadcrumbs with a message using leaveBreadcrumb or bugsnag_leave_breadcrumb_env using the Native API:

Bugsnag.leaveBreadcrumb("App loaded");
Bugsnag.leaveBreadcrumb("User clicked a button");
Bugsnag.leaveBreadcrumb("App loaded")
Bugsnag.leaveBreadcrumb("User clicked a button")
bugsnag_leave_breadcrumb_env(env, "App loaded", BSG_CRUMB_STATE);

BugSnag tracks the time when a breadcrumb is logged, and shows the message and timestamp on your dashboard.

Individual breadcrumb size is limited to 4kb after serialization. Any larger breadcrumbs will be dropped from the payload while logging a warning.

Attaching metadata

Additional data can be attached to breadcrumbs by using the longer form of leaveBreadcrumb.

Breadcrumb types can be used to differentiate different types of events, such as user activity and changes in application state. See the BreadcrumbType enumeration for a complete list of the breadcrumb types available to Java or Kotlin code, and the Native API header for C/C++ code.

Additional data added to breadcrumbs will be presented on the BugSnag dashboard alongside the breadcrumb name and type.

Bugsnag.leaveBreadcrumb("Preference updated", BreadcrumbType.STATE, new HashMap<String, String>() {{
  put("from", "moka");
  put("to", "french press");
}});
Bugsnag.leaveBreadcrumb("Preference updated", BreadcrumbType.STATE, hashMapOf(
  "from" to "moka",
  "to" to "french press"
))
if (useFrenchPress) {
  sprintf(message, "Updated pref: %s", "french press");
  bugsnag_leave_breadcrumb_env(env, message, BSG_CRUMB_STATE);
}

Note: There is no Native API equivalent for adding metadata to breadcrumbs.

Tracking fragment lifecycles

If you wish to log Breadcrumbs for the Fragment Lifecycle, we suggest that you use FragmentLifecycleCallbacks for all the activities which you wish to track.

Example: Using FragmentLifecycleCallbacks to log navigation events
public class MyActivity extends FragmentActivity {
    @Override
    protected void onStart() {
        super.onStart();
        getSupportFragmentManager()
            .registerFragmentLifecycleCallbacks(new FragmentBreadcrumbLogger(), true);
    }
}

public class FragmentBreadcrumbLogger extends FragmentManager.FragmentLifecycleCallbacks {

    private static final String FRAG_LIFECYCLE_CALLBACK = "FragmentLifecycleCallback";

    @Override
    public void onFragmentCreated(FragmentManager fm, Fragment f, Bundle savedInstanceState) {
        leaveLifecycleBreadcrumb(f, "onFragmentCreated()");
    }

    // leave Breadcrumbs in other lifecycle callbacks if needed

    private void leaveLifecycleBreadcrumb(Fragment fragment, String lifecycleCallback) {
        // note - if proguard is enabled you may want to use a different method of obtaining
        // the current fragment's name
        String fragmentName = fragment.getClass().getSimpleName();

        Map<String, String> metadata = new HashMap<>();
        metadata.put(FRAG_LIFECYCLE_CALLBACK, lifecycleCallback);
        Bugsnag.leaveBreadcrumb(fragmentName, BreadcrumbType.NAVIGATION, metadata);
    }
}
class MyActivity : FragmentActivity() {
    override fun onStart() {
        super.onStart()
        supportFragmentManager
                .registerFragmentLifecycleCallbacks(FragmentBreadcrumbLogger(), true)
    }
}

class FragmentBreadcrumbLogger : FragmentManager.FragmentLifecycleCallbacks() {

    override fun onFragmentCreated(fm: FragmentManager?, f: Fragment?, savedInstanceState: Bundle?) {
        f?.let { leaveLifecycleBreadcrumb(it, "onFragmentCreated()") }
    }

    // leave Breadcrumbs in other lifecycle callbacks if needed

    private fun leaveLifecycleBreadcrumb(fragment: Fragment, lifecycleCallback: String) {
        // note - if proguard is enabled you may want to use a different method of obtaining
        // the current fragment's name
        val fragmentName = fragment.javaClass.simpleName

        val metadata = HashMap<String, String>()
        metadata.put("FragmentLifecycleCallback", lifecycleCallback)
        Bugsnag.leaveBreadcrumb(fragmentName, BreadcrumbType.NAVIGATION, metadata)
    }
}

Removing breadcrumbs

You can register a callback which is executed each time a breadcrumb is captured using beforeRecordBreadcrumb. This can be helpful if you wish to filter out certain automatic breadcrumbs from your application.

Bugsnag.beforeRecordBreadcrumb(new BeforeRecordBreadcrumb() {
    @Override
    public boolean shouldReport(@NonNull Breadcrumb breadcrumb) {
        if (breadcrumb.getName().equals("Noisy breadcrumb")) {
            return false; // ignore the breadcrumb
        } else {
            return true; // capture the breadcrumb
        }
    }
});
Bugsnag.beforeRecordBreadcrumb { breadcrumb ->
    if (breadcrumb.name == "Noisy breadcrumb") {
        false // ignore the breadcrumb
    } else {
        true // capture the breadcrumb
    }
}

Note: There is no Native API equivalent for removing breadcrumbs.