I have a small game which has a few levels. In the google play console, I am getting crashes in the Game-Fragment but it's hard for me to find which level is causing the crash. The first few levels look okay and tested. I am just wondering what is best/standard approach to get the crash along with the level ID/some more information.
There are different good libraries that allow you to improve logging of the exceptions, one of them is Crashlytics from Google.
With Crashlytics, you can catch exceptions that are happening with following code and log it(and include custom parameters in the message variable):
try {
methodThatThrows();
} catch (Exception e) {
Crashlytics.log(priority, tag, message);
// additional handling of your exception
}
You can improve your logging this way to include all kind of helpful information. See documentation page for details:
https://firebase.google.com/docs/crashlytics/customize-crash-reports
Related
Our app uses Firebase Crashlytics and Sentry to keep track of all the crashes. We have covered all of our dart code with crash handling but have noticed that in some cases the crashes come from native code, which means that they are not caught by our catchers.
For example, we recently had an issue with one of our images accidentally getting published in very high res causing memory issues and the app to crashed without any reports.
We were to able to know about it and fix it because of feedback from the users and the fact that it was easily reproducible, but we'd rather have some sort of reporting in place for such crashes.
Firebase Crashlytics can pick up those errors too.
Follow all steps on the package setup guide.
https://pub.dev/packages/firebase_crashlytics
quoting the guide
Overriding FlutterError.onError with Crashlytics.instance.recordFlutterError will automatically catch all errors that are thrown from within the Flutter framework.
If you want to catch errors that occur in runZoned, you can supply Crashlytics.instance.recordError to the onError parameter:
runZoned<Future<void>>(() async {
// ...
}, onError: Crashlytics.instance.recordError);
Have you tried catching NDK crashes? Crashlytics supports it
I've seen the option of automatic crash reports to firebase. But what about regular try/catch exceptions? Is there any way to set automatic logs to Firebase on each caught exception in my android app?
Once you use the Firebase Crash Reporting SDK in your app, uncaught exception are automatically reported to the server.
To report an exception that you catch, cal FirebaseCrash.report:
...
}
catch (IOException ex) {
FirebaseCrash.report(ex);
}
I highly recommend reading the Firebase Crash Reporting documentation. It's pretty much a single page and covers the entire API and many common use-cases.
I'm trying to get logs with some service data with Crashlytics in my android application. But I don't see my logs in dashboard.
I used this:
String myLog = getServiceData(); //myLog is not null and non-empty
CrashLytics.log(myLog);
and this:
String myLog = getServiceData(); //myLog is not null and non-empty
CrashLytics.log(Log.Error, getString(R.string.app_name), myLog);
I tried to generate exception in my application and handle it, but have no results:
try {
int a = 0;
a = 1/a;
}
catch (Exception e) {
CrashLytics.log(myLog);
}
Also I read on Crashlytics log not sent I need to initialize crashlytics before log data. I put Crashlytics.start(this) in onStart() event of my Activity but didn't see my logs in dashboard again. At last I tried to put Crashlitycs.start(this) directly before logging my data, but still have no logs in dashboard.
Plase, tell me what I do wrong and how to get my custom logs in Crashlytics dashboard?
I had a similar situation. With some experimenting, I was able to deduce the rules to Crashlytics' behavior.
I'm sharing my learnings here so (hopefully) others don't have to go through the arduous and time-consuming process that I did to figure it out.
Crashlytics will only upload a crash report "to the dashboard" immediately if a fatal exception occurs. In other words, when your app crashes. And nothing shows in the dashboard unless and until a crash report is uploaded.
If you log a non-fatal exception, using CrashLytics.logException(e), a crash report will not be uploaded till the next time your app is restarted. So you will not see the exception in the Crashlytics dashboard till an app restart.
You can tell when an upload occurs because you'll see this sort of message in LogCat:
07-17 19:30:41.477 18815-18906/com.foo.bar I/Crashlytics﹕ Crashlytics report upload complete: 55A9BA0C01D7-0001-462D-B8B4C49333333.cls
A Crashlytics log message must be associated with a fatal or non-fatal exception to show up in the dashboard.
Furthermore, log messages that aren't associated with an exception do not survive app restart.
So, if you do something like log a few messages, then restart the app, then the app throws an exception, or it logs a non-fatal exception using Crashlytics.logException(), the log messages will be lost. They will not show up in the dashboard.
If you want to log some messages without a fatal exception, use one or more Crashlytics.log() statements followed by Crashlytics.logException().
To verify that it works, have the code run, then restart the app. In the dashboard, you should see the logs associated with the issue created for the non-fatal exception. In the wild, you'll just have to trust your users restart the app with some regularity.
On the Fabric/Crashlytics dashboard, you'll need to select All Events or (if you want to see just your logging calls) Non-Fatals.
according to Crashlytics knowledgebase:
Logged messages are associated with your crash data and are visible in
the Crashlytics dashboard if you look at the specific crash itself.
And from my experience this seems true. However I am unsure as to what determines which logging is associated with a crash report. Perhaps a time window (time around crash) or a limited number of logs (before the crash) is associated with the crash report?
However Crashlytics knowledgebase does say that exceptions can be logged:
All logged exceptions will appear as "non-fatal" issues in the
Crashlytics dashboard.
So if you changed your try/catch to:
try {
int a = 0;
a = 1/a;
}
catch (Exception e) {
CrashLytics.logException(e);
}
then it should show up in the Crashlytics dashboard.
This is an old question but since I was having the same problem today, I figured I should post my solution (it's in Kotlin though).
With Crashlytics now a part of Google's Firebase offering, it initializes behind the scenes, so a solution I wrote a few years ago had to be updated to this:
Implement some kind of log caching, First In First Out. I put one together based on cache-lite.
Put this function in YourApplicationClass that extends Application:
fun setExceptionHandler() {
val defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler()
Thread.setDefaultUncaughtExceptionHandler { thread, ex ->
Crashlytics.log(cacheLoggingTree.getAll().joinToString("++"))
Crashlytics.logException(ex)
defaultExceptionHandler.uncaughtException(thread, ex)
}
}
Then you call the function from the end of your onCreate function in your MainActivity:
(application as YourApplicationClass).setExceptionHandler()
With that, any exceptions that get thrown will first post the most recent log entries, then log the exception. You probably want to be cautious with how many lines you cache though, lest you overload the system.
Also, I used ++ as a flag to manually replace with carriage returns when you download the log, since the \n I had gets stripped in the upload process.
Instead of catching the exception and logging it, you can instead use RuntimeExceptions:
throw new RuntimeException("Test crash");
Android Studio will not require you to catch these, thus having the app terminate and upload the report immediately.
I recall seeing a check box on android apps that, when crashing, will ask to send the device data with the crash report.
My app has produced a handful of java.lang.OutOfMemoryError on my customers devices, and I was wanting to see the model phone they are using to see if I can create an alternative for their below average hardware. Or if nothing else, disallow their model from being able to download the app.
Unless it says on the report (because the device sent that data), the only other place is in the message the user sent with the error report.
If neither of those two places then you cannot determine it for now. However if you then know which bit of your code is causing the error you could wrap the code in a try catch and rethrow it with the device type. This would only benefit you you in the future and not for the current reports. Like this:
try{
myVar.methodThatCausesCrash():
} catch (OutOfMemoryException e){
throw new Exception("OutOfMemoryException model: " + Build.MODEL, e); // or rethrow another OoME
}
Is there anyone using Flurry to generate reports for uncaught exceptions that could post some sample code on how to do this?
I don't see any example via Flurry themselves, and though I've seen code samples of custom exception reporters, I haven't seen a simple example of how to implement the basic error reporting just using Flurry.
Thanks.
This is all good feedback. We're looking into adding full stack traces for error reporting which we'll hopefully see in our next major SDK release. We'll also look at filtering by device model.
In the meantime we've added a new REST API for exporting your error reports if you want to do your own analysis. If you need help using it you can just contact our support or message me.
Sean / CTO / Flurry, Inc.
Flurry does it automatically (if you have it running). However, the error reporting is lame. They only catch the message w/o giving you the stack trace, so you may end up seeing (for example) that people are getting lots of NullPointerExceptions, but you won't have any idea where, or how, they're happening. If you try to do it yourself with the FlurryAgent.onEvent() method you'll quickly discover that they limit you to 255 characters.
If you need detailed error reporting it really is better to roll your own right now.
I wasn't going to post this initially, but since it sounds like Flurry's error reporting sucks, you should check android-remote-stacktrace. It sends the stack trace to a url, which you can use to redirect it to an e-mail or just gather it on the server.
I'm not using it for uncaught exceptions , but you can catch it and then send it to flurry.
I am using bugsense for error reports. It catches full stack trace when an uncaught exception happens and also gives some useful information about the device - OS version, you app's version, is WiFi available on the device, etc. You can add custom messages and tags for specific events.
I've already fixed a couple crashes in my app thanks to it.
Since people are posting alternatives for getting stack traces, I'll recommend ACRA. ACRA can send the stack trace to a spreadsheet on google drive/docs. Or you can also have it send to your server if you wish too. By default it also includes phone model, android version, memory of device, and other data too.