While I've personally never written a buggy line of code in my life, odds are some of you out there have. And what's the golden rule of open source?
Identify and fix errors before your users have a chance to create a GitHub issue!
We've collectively taken many approaches to logging errors with our apps (be they web or mobile). In my past as a .NET web developer, I often took a rudimentary approach by leveraging the global Application_Error
event to have my app send a simple email with the error details. Meh 😐. It works, but doesn't provide the consolidated reporting required by enterprise-grade apps.
Times have changed and numerous, far more robust, "crash reporting" services have emerged. Some of the more popular ones being CrashProbe, Sentry.io, and Firebase Crashlytics.
Now if you're not using any error-reporting mechanism, my instinct is to shame you, but in reality I want to give you a hug and let you know it's going to be ok.
Today we are going to learn how to leverage Crashlytics (part of Firebase) to log and report on errors in our NativeScript apps for both iOS and Android.
TIP: NativeScript 5.2 came with vastly improved error logging improvements!
Quick history lesson: Crashlytics has been around since 2011. They were acquired by Twitter a couple of years later, and most recently acquired by Google for inclusion in their Firebase offering.
Not to get all marketingy on you, but if you're looking for a competitive, NativeScript-optimized serverless backend, take a look at Progress Kinvey.
While Firebase contains numerous services, the only one we care about today is Crashlytics. And what better way to utilize these services than via the NativeScript Firebase plugin!
To get started with Firebase, all you need to do is head over to the Firebase console and set up a new (free) account.
From here I would have you follow the simple instructions to get your first Firebase project set up and properly configured with your NativeScript app.
TIP: During plugin installation, the setup script will prompt you to activate one or more Firebase services. It's kinda important at this point to make sure you mark the
Crashlytics
services with a bigY
when prompted. Worst case scenario, you can always reconfigure the plugin by going to thenode_modules/nativescript-plugin-firebase
directory and runningnpm run config
.
Before you ask, note that the instructions provided allow for usage with NativeScript Core (i.e. plain JavaScript), Angular, or Vue.js!
With the Firebase plugin installed and Firebase initialized in your app, it's time to look more closely at Crashlytics.
NOTE: At this time, make sure your
firebase.nativescript.json
file has"crashlytics": true
and"crash_reporting": false
noted. This enables Crashlytics and disables the older Firebase crash reporting service. If you have to make a change to this file, remove theplatforms
folder in your app (it'll come back at the next build!).
Now at this point you can say, "I'M DONE!"...and you wouldn't be wrong. Crashlytics will start tracking app crashes and display them in your Firebase console:
But we can do better! It's a far better practice to catch errors before they crash your app and provide a meaningful error message to your users. Sometimes we can't predict error-prone spots, but when we have external dependencies that can change on us (like remote APIs for instance), we should play it safe, check for errors, and log them.
Anytime you want to explicitly log an error, you just need to plug in some tiny code snippets. You first need to import Firebase:
import * as firebase from 'nativescript-plugin-firebase';
Next, call the Firebase sendCrashLog
method to send a customized error log to your Firebase project:
firebase.sendCrashLog({
message: 'You screwed up! Here is the error: ' + error,
showInConsole: true
});
Not only can you compose a custom
message
to be logged in Firebase, but you can also optionally show the same message in your console.
A good example of this in practice is the fetch
module. Since fetch
can be configured to catch
an error response, we can log any errors quite easily:
fetch("https://httpbin.org/get")
.then((response) => response.json())
.then((r) => {
// do something with the data!
})
.catch((error) => {
// oh no!
firebase.sendCrashLog({
message: 'Error with that one API: ' + error,
showInConsole: true
});
}
);
It gets better though. Since sendCrashLog
returns a promise, we can also alert our users to a problem with some friendlier UI (in this case a native alert):
firebase.sendCrashLog({
message: "Error!",
showInConsole: true
}).then(
() => {
alert({
title: "Sorry!",
message: "Hey, we screwed up. Just thought you should know.",
okButtonText: "OK"
});
}
);
It's all fine and good to implement error logging in your apps, but how do we know it's working? Luckily it's pretty easy to fake a crash on both iOS and Android:
import { isIOS, isAndroid } from 'tns-core-modules/platform';
declare const Crashlytics: any;
public forceCrash(): void {
if (isIOS) {
// some nonsense code that is guaranteed to throw an exception :)
var __error = 1/0;
} else {
throw new java.lang.Exception("Forced an exception.");
}
}
With some crashes logged, it's time to head over to your handy Firebase console and check on your report!
Happy 🐛 squashing!