sarriaroman / FabricPlugin

Fabric.io plugin for Cordova or Phonegap
MIT License
197 stars 157 forks source link

How to send all error messages to Plugin (Ionic2)? #70

Open sleepybuddha opened 7 years ago

sleepybuddha commented 7 years ago

Hello ,

I can't figure out in the documentation how to send all crashes automatically to the plugin. I only see the loads in my Fabric Dashboard - saying I am 100 % crash free.

Unfortunately, that's not true, I had some native crashes and handled errors. How to send all of them to the plugin?

Thx a ton!

wodka commented 7 years ago

I created a custom ErrorHandler (the stacktrace part is only required for my pull request) - this will forward everything to fabric and will show a nice error message as of ionic2.rc3

in your providers (app.module.ts) add the following line:

{provide: ErrorHandler, useClass: FabricErrorHandler},
import {Injectable} from "@angular/core";
import {Analytics} from "./analytics";
import {IonicErrorHandler } from 'ionic-angular';
import * as stacktrace from 'stacktrace-js';

@Injectable()
export class FabricErrorHandler extends IonicErrorHandler {
    constructor (public analytics: Analytics) {
        super();
    }

    handleError(error) {
        // do something with the exception
        this.analytics.addLog('crash triggered');
        stacktrace.get().then(
            trace => this.analytics.sendNonFatalCrash(error.message, trace)
        );

        super.handleError(error);
    }
}
Iyashu5040 commented 7 years ago

@wodka Where did you get the module used in import {Analytics} from "./analytics"; to get typings? At the moment I'm using (<any>window).fabric.Crashlytics but your approach seems better.

wodka commented 7 years ago

@Iyashu5040 minimal ts file - I use the same injectable to collect other stuff for fabric Answers

import {Platform} from "ionic-angular";
import {Injectable} from "@angular/core";

@Injectable()
export class Analytics {
    private handler:any;

    constructor (public platform: Platform) {
        platform.ready().then(
            () => this.setup()
        )
    }

    private setup() {
        if (!(<any>window).fabric) {
            return;
        }

        this.handler = (<any>window).fabric;
    }

    setUserIdentifier(id:string) {
        if (!this.handler) {
            console.warn('fabric not available: setUserIdentifier', id);
            return;
        }

        this.handler.Crashlytics.setUserIdentifier(id);
    }

    setUserName(name:string) {
        if (!this.handler) {
            console.warn('fabric not available: setUserName', name);
            return;
        }

        this.handler.Crashlytics.setUserName(name);
    }

    setUserEmail(email:string) {
        if (!this.handler) {
            console.warn('fabric not available: setUserEmail', email);
            return;
        }

        this.handler.Crashlytics.setUserEmail(email);
    }

    addLog(message:string) {
        if (!this.handler) {
            console.warn('fabric not available: addLog', message);
            return;
        }

        this.handler.Crashlytics.addLog(message);
    }

    sendNonFatalCrash(message:string, stacktrace?: any) {
        if (!this.handler) {
            console.warn('fabric not available: sendNonFatalCrash', message, stacktrace);
            return;
        }

        this.handler.Crashlytics.sendNonFatalCrash(message, stacktrace);
    }

    sendSignUp(type:string, success:boolean, attributes?:any) {
        if (!this.handler) {
            console.warn('fabric not available: sendSignUp', type, success);
            return;
        }

        this.handler.Answers.sendSignUp(type, success, attributes);
    }
    sendLogin(type:string, success:boolean, attributes?:any) {
        if (!this.handler) {
            console.warn('fabric not available: sendLogin', type, success);
            return;
        }

        this.handler.Answers.sendLogIn(type, success, attributes);
    }

    sendCustomEvent(name:string, attributes?:any) {
        if (!this.handler) {
            console.warn('fabric not available: sendCustomEvent', name);
            return;
        }

        this.handler.Answers.sendCustomEvent(name, attributes);
    }

    sendStartCheckout(totalPrice:number, currency:string, itemCount:number, attributes?:any) {
        if (!this.handler) {
            console.warn('fabric not available: sendStartCheckout', totalPrice, currency ,itemCount);
            return;
        }

        this.handler.Answers.sendStartCheckout(totalPrice, currency, itemCount, attributes);
    }

    sendContentView(name:string, type:string, id:string, attributes?:any) {
        if (!this.handler) {
            console.warn('fabric not available: sendContentView', name, type, id);
            return;
        }

        this.handler.Answers.sendContentView(name, type, id, attributes);
    }
}
emcniece commented 6 years ago

The Javascript error catching is working well for me on all platforms, but Android does not report full app crashes in the same manner that iOS does. Further investigation required.

wodka commented 6 years ago

@emcniece what do you mean exactly?

emcniece commented 6 years ago

The error catching that you (@wodka) have provided works really well for "console" errors, or events that happen within the webview on each platform. However there are still events that do not result in console errors (like memory leaks) that can cause the webview itself to crash.

I am finding that while iOS Crashlytics is reporting full crashes properly, it is not reporting this on Android. All of my Android builds have a 100% crash-free statistic, even though I have witnessed the app dump many times.

Crashlytics can be configured to send in-thread crash events (sendNonFatalCrash() in your example) which I think requires Javascript to be executing, but I am not sure how Crashlytics sends a full crash report when the app exits completely. @sleepybuddha's question doesn't make a distinction between these two types of crash events.

Any ideas?

wodka commented 6 years ago

In theory the log should be sent when the app starts again. Regular messages are being sent from crashlytics?