xamarin / AndroidX

AndroidX bindings for .NET for Android
MIT License
185 stars 45 forks source link

Crashlytics RecordException uses Throwable instead of Exception, which leads to unusable log #1011

Open DavidMarquezF opened 3 days ago

DavidMarquezF commented 3 days ago

Android framework version

net8.0-android

Affected platform version

2022 17.11.4, NET 8

Description

Since the https://github.com/xamarin/GooglePlayServicesComponents/ repository is now considered deprecated I'm reopening https://github.com/xamarin/GooglePlayServicesComponents/issues/423 here.

The main issue is that Crashlytics uses Java.Lang.Throwable. To convert our exceptions to this type we can use Java.Lang.Throwable.FromException. However, the resulting crash logs are pretty hard to read and use compared to when we were using AppCenter (to be deprecated in 2025). On top of that inner exceptions are not even displayed, so for some issues it's impossible to know what actually happened.

Given the deprecation of AppCenter and Firebase being the logical alternative (other than sentry), it feels like a big downgrade to not be able to get proper readable logs.

Steps to Reproduce

  1. Create a new project and set up Firebase Crashlytics
  2. Throw a simple error -> This shows that the crashlytics error is usable but hard to understand, also firebase crashlytics groupping will not work very well in this case
  3. Create an inner exception like starting a task and throwing and error from inside (the inner exception is not logged and thus you loose crucial information)

Did you find any workaround?

You can try to prepare the logs a little bit better yourself by using regex (as seen in this gist). However this is only for managed exceptions. We don't have any way currently to act on unmanaged exceptions.

Relevant log output

Example of AppCenter crash:

Xamarin Exception Stack:
System.Exception: Exception NavigateToFirstViewModel
  at x.AppStart.NavigateToFirstViewModel(Object hint)
  at MvvmCross.ViewModels.MvxAppStart.StartAsync(Object hint)
  at x.Droid.Activities.RootActivity.RunAppStartAsync(Bundle bundle)
  at x.Droid.Activities.RootActivity.OnResume()
  at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_0(Object state)
  at Android.App.SyncContext.<>c__DisplayClass2_0.<Post>b__0()
  at Java.Lang.Thread.RunnableImplementor.Run()
  at Java.Lang.IRunnableInvoker.n_Run(IntPtr jnienv, IntPtr native__this)
  at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PP_V(_JniMarshal_PP_V callback, IntPtr jnienv, IntPtr klazz)
--- End of inner exception stack trace ---
  System.NullReferenceException: Object reference not set to an instance of an object
    at x.Droid.UIManager.KeyboardHelper.EnableKeyboard(Activity activity)
    at x.Droid.MvxServices.UserInterfaceService.SetDisableKeyboard(Boolean disabled)
    at x.AppStart.NavigateToFirstViewModel(IAppStartStatusService appStartStatus, IMvxNavigationService navigationService, BusinessLogic dataService, IApplyUserSettingsService settingsService, IUserInterfaceService userSettingsService, IEventTracker eventTracker, String startName)
    at x.AppStart.NavigateToFirstViewModel(Object hint)

Same issue in Crashlytics:

Fatal Exception: android.runtime.JavaProxyThrowable: [System.Exception]: Exception NavigateToFirstViewModel
       at x.AppStart+<NavigateToFirstViewModel>d__6.MoveNext()
       at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess()
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification()
       at MvvmCross.ViewModels.MvxAppStart+<StartAsync>d__5.MoveNext()
       at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess()
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification()
       at x.Droid.Activities.RootActivity+<RunAppStartAsync>d__10.MoveNext()
       at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess()
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification()
       at x.Droid.Activities.RootActivity+<OnResume>d__8.MoveNext()
       at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
       at System.Threading.Tasks.Task+<>c.<ThrowAsync>b__128_0()
       at Android.App.SyncContext+<>c__DisplayClass2_0.<Post>b__0()
       at Java.Lang.Thread+RunnableImplementor.Run()
       at Java.Lang.IRunnableInvoker.n_Run()
       at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PP_V()
       at mono.java.lang.RunnableImplementor.n_run(SourceFile)
       at mono.java.lang.RunnableImplementor.run(SourceFile:1)
       at android.os.Handler.handleCallback(Handler.java:938)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loop(Looper.java:223)
       at android.app.ActivityThread.main(ActivityThread.java:7680)
       at java.lang.reflect.Method.invokeNative(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:423)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

Looking at the whole crashlytics log, there is no reference at `EnableKeyboard` function, which is the one that threw the error
jpobst commented 3 days ago

Obviously we don't have anything to do with how Google's Firebase Crashlytics operates, so there isn't much we can do there. But Java.Lang.Throwable.FromException is ours and maybe it can be improved to provide a better translation of the stack trace.

Will transfer to the dotnet/android repository for investigation.

jpobst commented 3 days ago

Oh, right, it moved to a different GitHub organization and we can no longer transfer issues to it. 😢

DavidMarquezF commented 2 days ago

@jpobst should i close here and open it there?

AmrAlSayed0 commented 2 days ago

This should already be fixed here since I faced this issue before and "complained" at @jonpryor on discord about it 😄 https://github.com/dotnet/android/pull/8185