1

I am building a NativeScript mobile app and among other things I am capturing for analytics purposes, I need to capture "app crashes" possibly with errors/reasons it crashed.

I came across this SO post but there it was in the response of a question on how not to let the app crash. Following was suggested to catch crash events:

var application = require("application");

application.on(application.uncaughtErrorEvent, function (args) {
    if (args.android) {
        // For Android applications, args.android is an NativeScriptError.
        console.log("NativeScriptError: " + args.android);
    } else if (args.ios) {
        // For iOS applications, args.ios is NativeScriptError.
        console.log("NativeScriptError: " + args.ios);
    }
});

If I go by the above then I have the following questions. Would appreciate if somebody can confirm if this means every-time the app is crashing it will generate this application.uncaughtErrorEvent event? Can I rely on it? If it is true then maybe I can make a REST call to my backend and store date, time and whatever is in args.android or args.ios.

If above is not the correct way then can somebody please help me on how to go about doing this?

Any help is highly appreciated. Thank you!

Gauzy
  • 711
  • 3
  • 13
  • 26
  • https://github.com/danielgek/nativescript-sentry Sentry works well for this, there are several other logging options for nativescript that wrap native SDKs. I think someone has published a Fabric plugin, not sure. Personally, I use sentry in several projects and it works really well, good free-tier also. – Brad Martin May 08 '18 at 18:56
  • Thanks for the reply @BradMartin, appreciated. I will check that link for sentry. Thanks again! **Edit** I have updated my question with something I found. What do you think about it? – Gauzy May 08 '18 at 19:09

1 Answers1

3

The application.onUncaughtError will be hit probably 95-98% of the time during a crash; it is pretty reliable. I have seen the app crash without any notice at all it just goes poof, but I'm not sure any reporting system can handle that one.

The way I do it is during the app startup I register a couple things:

  1. I create a global.error function; this is used for anything (like try/catch, promise/catch) that needs to send the errors through to be logged remotely. So anywhere in my codebase I can do a global.error(theError); and it will be handled; this way I do NOT have to worry about trying to load or require things while an error is taking place, as that can cause other errors.
  2. I use the onUncaughtError event to catch anything that is not normally caught, and then notify the user that an error has occurred and quit the app. (in this case, trying to recover is not recommended as you have no idea where the error was thrown from...)
  3. If I use a worker thread, When I startup a worker I register the worker.onerror to forward its data to the main threads global.error function AND I have a specific message from the workers' version of the global.error that sends the error back to the primary thread. This way if the worker itself calls global.error that message is passed back to the main thread and then to the global.error on the main thread which handles everything properly.

This technique allows me to catch pretty much all errors that can occur. The main global.error function and the onUncaughtError both use a simple reporting library that I built that reports all the data back to one of my servers, IF the device is online. If the device is offline, it can optionally save the data to a reporting file to be uploaded later; or just ignore it.

It also has safety checks to verify the error isn't a network error (we don't want the error reporting to go into a loop, i.e. trying to report the error causes an error, which then tries to report the error; so in the event it is a certain type of network error; it will ignore those. )

Nathanael
  • 5,369
  • 18
  • 23
  • Nathanael - thanks for taking the time out to put down the approach. Highly appreciated! I did think about it but I thought it will be considered kind of a old way of handling this. [Good catch with network error, it didn't come to me. I would have done it after getting stuck in that loop probably. :) ] I thought NativeScript will have some thing (plugin, etc.) to do this. I am new to NativeScript and wanted to check what the community is doing. Thanks again for your detailed reply, very much appreciated. – Gauzy May 11 '18 at 13:08
  • There are several plugins that handle some of these pretty easily; but they are designed around services. I understood you were wanting to push the information to your own servers; so in that case it is way simpler to create your own plugin to do it. You only really have to tie into the `onUncaughtError` function and worker.onerror (if using workers). – Nathanael May 12 '18 at 03:01
  • Nathanael - the cost will definitely play a role but I think I am open to plugins that provides this functionality so that we don't end of creating and managing this data. Having said that, I think this functionality is not implemented in a way I am trying to and most like being done in house. Otherwise, we would have had replies by now. :) Thanks again for your kind help, very much appreciated. I will mark yours as an answer. – Gauzy May 17 '18 at 21:17
  • @Nathanael where do you put this error handling logic? Inside the constructor of the main `app.component`? Also, I'm wondering how I might test that this is working locally. Is there a good way to trigger a crash manually? These might be good things to add to your answer. Thank you! – Corey Cole Aug 23 '18 at 20:46
  • I've learned that `application.onUncaughtError` does not get called when I try to call a function that does not exist. I only get an error on the debug console `ERROR TypeError: _co.login2 is not a function`. This is a known issue tracked [here](https://github.com/NickIliev/NS-Issues-2017/blob/master/NativeScript/issue_2309/app/main-page.ts#L8). How could I capture an error like this to send it to my server? – Corey Cole Aug 24 '18 at 23:14
  • First, I have a separate file that I require in the main app.js file that sets up the error stuff. Second item,the `onUncaughtError` should catch it if you have the setting set for discardUncaughtJsExceptions set to true. (See: my blog http://fluentreports.com/blog/?p=581) – Nathanael Aug 26 '18 at 02:26