I have a project that uses Fabric/crashlytics. In order to be able to detect all runtime errors in production, I want to send (non-fatal) exceptions to Crashlytics using:
Crashlytics.logException(new RuntimeException("some identifiable error message");
I want to add this logic to our existing Log-class in the project that is loaded via gradle as a separate "utilities-module". Since this module doesn't hold a reference to Crashlytics (and I can't seem to find a good way of forwarding this reference from the main module), I have solved it by introducing an interface, implemented from the main application:
if (!BuildConfig.APP_BUILD_VERSION.equals("local")) {
UtilitiesConfig.setExternalLogger(new Logger.ExternalLogger() {
@Override
public void reportError(String tag, String message, Throwable throwable) {
Crashlytics.logException(new RuntimeException(TextUtils.isEmpty(tag) ? message : tag + ": " + message));
}
});
}
This works fine, only problem is that all reports in Fabric are being grouped as one similar exception, since the top rows of the stack trace are similar (i.e. the interface and the application). For example:
Non-fatal Exception: java.lang.RuntimeException: c: onNetworkError, type: CANT_ACCESS_SERVER
at my.package.Application$3.reportError(Application.java:234)
at my.package.utilities.Logger.e(Logger.java:34)
at my.package.utilities.net.CallbackCallable.onNetworkError(CallbackCallable.java:76)
at my.package.utilities.net.MsgCallable.onNetworkError(MsgCallable.java:250)
at my.package.utilities.net.CancellableCallable.call(CancellableCallable.java:80)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:776)
...and this:
Non-fatal Exception: java.lang.RuntimeException: u: Cannot update
at my.package.Application$3.reportError(Application.java:234)
at my.package.utilities.Logger.e(Logger.java:43)
at my.package.NTPManager$SyncTimeAsyncTask.doInBackground(NTPManager.java:150)
at my.package.NTPManager$SyncTimeAsyncTask.doInBackground(NTPManager.java:133)
at android.os.AsyncTask$2.call(AsyncTask.java:304)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:762)
are both being grouped together, despite them being two different errors originating from different classes/rows and with different error messages.
Is there an efficient way of changing either some configuration in Crashlytics or by reporting it through said callback in another fashion, making Fabric not considering them the same error?
Crashlytics is a part of Fabric.io and gives mobile app developers insight into their apps' performance, so you can pinpoint and fix issues quickly and easily.
A non-fatal error might be an exception that is caught within a try-catch block, or a performance issue such as an ANR, which indicates the main thread is blocked and the user might be about to kill your app.
A non-fatal error is a failure in your application that didn't result in a crash for the user. In other words: the loss is recoverable, and the application can continue.
Since issues are grouped by the root cause of the exception, if you used the throwable
passed to reportError
and set it as the cause
of the exception you create, you should get the desired result.
if (!BuildConfig.APP_BUILD_VERSION.equals("local")) {
UtilitiesConfig.setExternalLogger(new Logger.ExternalLogger() {
@Override
public void reportError(String tag, String message, Throwable throwable) {
String logMessage = TextUtils.isEmpty(tag) ? message : tag + ": " + message;
Crashlytics.logException(new RuntimeException(logMessage, throwable));
}
});
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With