Using Crashlytics with React Native Android App

Karthik Pala
3 min readMay 31, 2018

Firebase Crashlytics is a lightweight, real-time crash reporter that helps you track, prioritize, and fix stability issues that erode the app quality. It also groups crashes and highlighting the circumstances that led up to them. We can find out if a particular crash is impacting a lot of users and get alerts when an issue suddenly increases in severity.

Awesome isn’t it?

Hold on..We are talking about react native applications which will generate both native and JSC- JavaScript Compiler crashes. As mentioned earlier, Crashlytics uses the method and crash line number to group crashes. So all your crashes are grouped together (even though they are different..sigh!) and it is very difficult to navigate among them.

Problem: All the JSC crashes are grouped together in crashlytics which would show crash origin as ExceptionsManagerModule.showOrThrowError (ExceptionsManagerModule.java:56) 😏

Solution: Use a custom error handler which overrides the global error handler of react native. You can have a function which overrides the global error handler and initialize this in a higher order component. Thanks to react-native-fabric 👍 ❤️ for this implementation.

In react-native-fabric, the original error handler is called again after logging the exception with a native module. This will create duplicate entries in your Crashlytics dashboard, one as a non fatal and other as a crash even though both would be referring to same error.

To avoid this we will not call the default error handler for any JSC errors and will replicate what it does in our native module.

Now you have to implement a Native module which our error handler will call in case of a java script crash. Before calling the native module, we will be using stacktrace-parser library(which react-native uses too ;)) to convert the stack trace of the java script error into an Array of frames.

Here is a sample implementation of the CrashlyticsRNHandler is a native module.

Observe that the native module is using the frameArray, then builds a stack trace from it and formats it using JSStackTrace.format().
This is set as exception title while throwing.

Basically we are trying to replicate the functionality of the native module com.facebook.react.modules.core.ExceptionsManagerModule which is called in case of a JSC exception by the default error handler in react-native.

Aaaaaaaand it is done 🙌 , If the error is fatal it will throw an exception which will have line numbers and columns set and hence will be categorized into different crashes in Crashlytics. If it is a non Fatal error, it is logged to Crashlytics using logException method in the API.

Bonus Problem: Since react-native obfuscates the code all the line numbers in the crash and exceptions absolutely makes no sense :(

Solution: Generate source maps while creating the binary and store it securely in a location. While throwing (or) logging the exception, we are basically formatting and set all the log into the title of the exception. Copy the log from the title in Crashlytics and use a tool such as stack-beautifier with your source maps to know the exact location of your JSC crash.

Thanks for taking time and reading this article. Please let me know any suggestions (or) possible code changes.

--

--