firebase / flutterfire

🔥 A collection of Firebase plugins for Flutter apps.
https://firebase.google.com/docs/flutter/setup
BSD 3-Clause "New" or "Revised" License
8.67k stars 3.97k forks source link

🐛 [FirebaseCrashlytics] Dashboard Stack Trace and Events #3907

Closed kungfuslippers closed 3 years ago

kungfuslippers commented 3 years ago

Bug report

This may not be a bug but having using Crashlytics previously for native mobile development - exceptions would be caught by Crashlytics and you would see a full stack trace in the Crashlytics console.

Since using FlutterFire Crashlytics I've found that the stack trace information is less useful.

I've found that:

  1. The stack track doesn't give an indication of where the crash occurred in terms of a line number or source file for Crashes / Non-fatal errors.

  2. Crashes forced by calling: FirebaseCrashlytics.instance.crash() are shown as an event

  3. Non-fatal errors don't show up for me as an event when filters are cleared.

Steps to reproduce

Steps to reproduce the behavior:

  1. Follow steps to set up FirebaseCrashlytics as per the documentation: https://firebase.flutter.dev/docs/crashlytics/overview

Expected behavior

Expect Crashes to show up with line numbers/source files as per native SDK behaviour

Additional context

My main() function looks like this:

void main() async {

  WidgetsFlutterBinding.ensureInitialized();

  await Firebase.initializeApp();

  FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterError;

  await FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true);

  runZonedGuarded(() {
    runApp(MyApp());
  }, (error, stackTrace) {
    FirebaseCrashlytics.instance.recordError(error, stackTrace);
  });

}

Flutter doctor

Run flutter doctor and paste the output below:

Click To Expand ``` [✓] Flutter (Channel stable, 1.20.4, on Mac OS X 10.15.6 19G2021, locale en-GB) [✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2) [✓] Xcode - develop for iOS and macOS (Xcode 12.0) [✓] Android Studio (version 4.0) [✓] VS Code (version 1.49.3) [✓] Connected device (2 available) ```

Flutter dependencies

Run flutter pub deps -- --style=compact and paste the output below:

Click To Expand ``` Dart SDK 2.9.2 Flutter SDK 1.20.4 basketballengland_flutter 1.0.0+10 dependencies: - cupertino_icons 0.1.3 - flutter 0.0.0 [characters collection meta typed_data vector_math sky_engine] dev dependencies: - add_2_calendar 1.4.0 [flutter] - after_layout 1.0.7+2 [flutter] - awesome_page_transitions 1.0.0 [flutter] - cached_network_image 2.3.2+1 [flutter flutter_cache_manager octo_image] - connectivity 0.4.9+3 [flutter meta connectivity_platform_interface connectivity_macos connectivity_for_web] - device_calendar 3.1.0 [flutter meta collection] - equatable 1.2.5 [collection meta] - firebase_core 0.5.0+1 [firebase_core_platform_interface flutter quiver meta firebase_core_web] - firebase_crashlytics 0.2.1+1 [flutter stack_trace firebase_core firebase_core_platform_interface firebase_crashlytics_platform_interface] - flutter_bloc 4.0.1 [flutter bloc provider] - flutter_image_compress 0.6.8 [flutter] - flutter_localizations 0.0.0 [flutter intl characters collection meta path typed_data vector_math] - flutter_picker 1.1.5 [flutter] - flutter_statusbarcolor 0.2.3 [flutter] - flutter_svg 0.17.1 [path_drawing xml vector_math meta flutter] - flutter_test 0.0.0 [flutter test_api path fake_async clock stack_trace vector_math async boolean_selector characters charcode collection matcher meta source_span stream_channel string_scanner term_glyph typed_data] - http 0.12.2 [http_parser path pedantic] - image 2.1.13 [archive xml] - image_picker 0.6.3 [flutter flutter_plugin_android_lifecycle] - native_pdf_view 3.2.1 [flutter extended_image synchronized device_info native_pdf_renderer] - onesignal_flutter 2.6.1 [flutter] - package_info 0.4.3 [flutter] - path 1.7.0 - path_provider 1.6.0 [flutter platform meta] - progress_dialog 1.2.4 [flutter] - rflutter_alert 1.1.0 [flutter] - scrollable_positioned_list 0.1.7 [flutter meta] - shared_preferences 0.5.6+1 [meta flutter shared_preferences_platform_interface shared_preferences_macos shared_preferences_web] - sprintf 4.1.0 - sqflite 1.1.7+2 [flutter synchronized path] - step_progress_indicator 0.2.4+7 [flutter] - test 1.15.0 [analyzer async boolean_selector coverage http http_multi_server io js node_preamble package_config path pedantic pool shelf shelf_packages_handler shelf_static shelf_web_socket source_span stack_trace stream_channel typed_data web_socket_channel webkit_inspection_protocol yaml test_api test_core] - toast 0.1.5 [flutter] - uuid 2.0.2 [crypto convert] transitive dependencies: - _fe_analyzer_shared 7.0.0 [meta] - analyzer 0.39.17 [_fe_analyzer_shared args charcode cli_util collection convert crypto glob html meta package_config path pub_semver source_span watcher yaml] - archive 2.0.13 [crypto args path] - args 1.6.0 - async 2.4.2 [collection] - bloc 4.0.0 [meta] - boolean_selector 2.0.0 [source_span string_scanner] - characters 1.0.0 - charcode 1.1.3 - cli_util 0.2.0 [path] - clock 1.0.1 [meta] - collection 1.14.13 - connectivity_for_web 0.3.1+2 [connectivity_platform_interface flutter_web_plugins flutter] - connectivity_macos 0.1.0+5 [flutter] - connectivity_platform_interface 1.0.6 [flutter meta plugin_platform_interface] - convert 2.1.1 [charcode typed_data] - coverage 0.14.1 [args logging package_config path source_maps stack_trace vm_service] - crypto 2.1.5 [collection convert typed_data] - csslib 0.16.2 [source_span] - device_info 0.4.2+8 [flutter device_info_platform_interface] - device_info_platform_interface 1.0.1 [flutter meta plugin_platform_interface] - extended_image 0.7.4 [flutter extended_image_library] - extended_image_library 0.2.3 [flutter path_provider http_client_helper crypto] - extension 0.1.1 - fake_async 1.1.0 [clock collection] - file 5.2.1 [intl meta path] - firebase 7.3.0 [http http_parser js] - firebase_core_platform_interface 2.0.0 [flutter meta plugin_platform_interface quiver] - firebase_core_web 0.2.0 [firebase firebase_core_platform_interface flutter flutter_web_plugins meta js] - firebase_crashlytics_platform_interface 1.1.1 [flutter meta collection firebase_core plugin_platform_interface] - flutter_blurhash 0.5.0 [flutter meta] - flutter_cache_manager 1.4.2 [flutter path_provider uuid http path sqflite pedantic clock file rxdart] - flutter_plugin_android_lifecycle 1.0.11 [flutter] - flutter_web_plugins 0.0.0 [flutter characters collection meta typed_data vector_math] - glob 1.2.0 [async collection node_io path pedantic string_scanner] - html 0.14.0+3 [csslib source_span] - http_client_helper 0.2.1 [http] - http_multi_server 2.2.0 [async] - http_parser 3.1.4 [charcode collection source_span string_scanner typed_data] - intl 0.16.1 [path] - io 0.3.4 [charcode meta path string_scanner] - js 0.6.2 - logging 0.11.4 - matcher 0.12.8 [stack_trace] - meta 1.1.8 - mime 0.9.7 - native_pdf_renderer 2.1.1 [flutter meta extension synchronized] - nested 0.0.4 [flutter] - node_interop 1.1.1 [js] - node_io 1.1.1 [node_interop path] - node_preamble 1.4.12 - octo_image 0.3.0 [flutter flutter_blurhash] - package_config 1.9.3 [path charcode] - path_drawing 0.4.1+1 [vector_math meta path_parsing flutter] - path_parsing 0.1.4 [vector_math meta] - pedantic 1.9.0 - petitparser 3.0.4 [meta] - platform 2.2.1 - plugin_platform_interface 1.0.2 [meta] - pool 1.4.0 [async stack_trace] - provider 4.3.2+2 [flutter nested collection] - pub_semver 1.4.4 [collection] - quiver 2.1.3 [matcher meta] - rxdart 0.24.1 - shared_preferences_macos 0.0.1+10 [shared_preferences_platform_interface flutter] - shared_preferences_platform_interface 1.0.4 [meta flutter] - shared_preferences_web 0.1.2+7 [shared_preferences_platform_interface flutter flutter_web_plugins meta] - shelf 0.7.9 [async collection http_parser path stack_trace stream_channel] - shelf_packages_handler 2.0.0 [path shelf shelf_static] - shelf_static 0.2.8 [convert http_parser mime path shelf] - shelf_web_socket 0.2.3 [shelf web_socket_channel stream_channel] - sky_engine 0.0.99 - source_map_stack_trace 2.0.0 [path stack_trace source_maps] - source_maps 0.10.9 [source_span] - source_span 1.7.0 [charcode collection meta path term_glyph] - stack_trace 1.9.5 [path] - stream_channel 2.0.0 [async] - string_scanner 1.0.5 [charcode meta source_span] - synchronized 2.2.0+2 - term_glyph 1.1.0 - test_api 0.2.17 [async boolean_selector collection meta path source_span stack_trace stream_channel string_scanner term_glyph matcher] - test_core 0.3.8 [analyzer async args boolean_selector collection coverage glob io meta package_config path pedantic pool source_map_stack_trace source_maps source_span stack_trace stream_channel vm_service yaml matcher test_api] - typed_data 1.2.0 [collection] - vector_math 2.0.8 - vm_service 4.2.0 [meta] - watcher 0.9.7+15 [async path pedantic] - web_socket_channel 1.1.0 [async crypto stream_channel] - webkit_inspection_protocol 0.7.3 [logging] - xml 3.7.0 [collection convert meta petitparser] - yaml 2.2.1 [charcode collection string_scanner source_span] ```

markusaksli-nc commented 3 years ago

Hi @kungfuslippers Could you provide a screenhot of the native behavior of your Crashlytics versus what is logged with flutterfire?

FF Crashlytics does log the source code file and line numbers and even full thread dumps if you FirebaseCrashlytics.instance.crash().

When throwing an exception in the example:

_MyAppState.<fn> (main.dart:184)
_InkResponseState._handleTap (ink_well.dart:993)
_InkResponseState.<fn> (ink_well.dart:1111)
GestureRecognizer.invokeCallback (recognizer.dart:183)
TapGestureRecognizer.handleTapUp (tap.dart:598)
BaseTapGestureRecognizer._checkUp (tap.dart:287)
BaseTapGestureRecognizer.handlePrimaryPointer (tap.dart:222)
PrimaryPointerGestureRecognizer.handleEvent (recognizer.dart:476)
PointerRouter._dispatch (pointer_router.dart:77)
PointerRouter.<fn> (pointer_router.dart:122)
_LinkedHashMapMixin.forEach (dart:collection)
PointerRouter._dispatchEventToRoutes (pointer_router.dart:120)
PointerRouter.route (pointer_router.dart:106)
GestureBinding.handleEvent (binding.dart:370)
GestureBinding.dispatchEvent (binding.dart:350)
RendererBinding.dispatchEvent (binding.dart:266)
GestureBinding.handlePointerEvent (binding.dart:305)
GestureBinding._flushPointerEventQueue (binding.dart:240)
GestureBinding._handlePointerDataPacket (binding.dart:213)

is logged for example.

We need more specific expected vs actual behavior here. Also, could you clarify what you mean by FirebaseCrashlytics.instance.crash() being shown as an event?

Thank you

kungfuslippers commented 3 years ago

Hi @markusaksli-nc

I decided to start a test project from scratch and now I'm getting crash logs reported but the stack trace in the Crashlytics console is different for Android and iOS for the same non-fatal exception which I initiated using the following code:

List<String> list = List();
print("List Object with index 4 = " + list[4]);

For Android:

Non-fatal Exception: io.flutter.plugins.firebase.crashlytics.FlutterError: RangeError (length): Invalid value: Valid value range is empty: 4. Error thrown Instance of 'ErrorDescription'. at _MyHomePageState.(main.dart) at State.setState(framework.dart:1240) at _MyHomePageState._incrementCounter(main.dart:86) at _InkResponseState._handleTap(ink_well.dart:992) at _InkResponseState.(ink_well.dart:1098) at GestureRecognizer.invokeCallback(recognizer.dart:184) at TapGestureRecognizer.handleTapUp(tap.dart:524) at BaseTapGestureRecognizer._checkUp(tap.dart:301) at BaseTapGestureRecognizer.acceptGesture(tap.dart:256) at GestureArenaManager.sweep(arena.dart:158) at GestureBinding.handleEvent(binding.dart:224) at GestureBinding.dispatchEvent(binding.dart:200) at GestureBinding._handlePointerEvent(binding.dart:158) at GestureBinding._flushPointerEventQueue(binding.dart:104) at GestureBinding._handlePointerDataPacket(binding.dart:88)

For iOS:

Non-fatal Exception: FlutterError 0 ??? 0x0 (main.dart) 1 ??? 0x0 setState + 1240 (framework.dart:1240) 2 ??? 0x0 _incrementCounter + 86 (main.dart:86) 3 ??? 0x0 _handleTap + 992 (ink_well.dart:992) 4 ??? 0x0 + 1098 (ink_well.dart:1098) 5 ??? 0x0 invokeCallback + 184 (recognizer.dart:184) 6 ??? 0x0 handleTapUp + 524 (tap.dart:524) 7 ??? 0x0 _checkUp + 301 (tap.dart:301) 8 ??? 0x0 acceptGesture + 256 (tap.dart:256) 9 ??? 0x0 sweep + 158 (arena.dart:158) 10 ??? 0x0 handleEvent + 224 (binding.dart:224) 11 ??? 0x0 dispatchEvent + 200 (binding.dart:200) 12 ??? 0x0 _handlePointerEvent + 158 (binding.dart:158) 13 ??? 0x0 _flushPointerEventQueue + 104 (binding.dart:104) 14 ??? 0x0 _handlePointerDataPacket + 88 (binding.dart:88)

crashlytics_android_non_fatal_stacktrace crashlytics_ios_non_fatal_stacktrace

The flutter Android stack trace now looks like what I get for errors on native iOS/Android but as you can see line numbers/files are not resolved for flutter iOS.

Any ideas?

markusaksli-nc commented 3 years ago

What do you mean?

The iOS stack trace you screenshotted does have file names and line numbers.

kungfuslippers commented 3 years ago

So for a crash caused by - calling - FirebaseCrashlytics.instance.crash();

For Android I get :

Fatal Exception: io.flutter.plugins.firebase.crashlytics.FirebaseCrashlyticsTestCrash: This is a test crash caused by calling .crash() in Dart. at io.flutter.plugins.firebase.crashlytics.FlutterFirebaseCrashlyticsPlugin.lambda$crash$1(FlutterFirebaseCrashlyticsPlugin.java:81) at io.flutter.plugins.firebase.crashlytics.-$$Lambda$FlutterFirebaseCrashlyticsPlugin$H0t0BleSpjDMVvqpx8Hy-ZKGwP8.run() at android.os.Handler.handleCallback(Handler.java:900) at android.os.Handler.dispatchMessage(Handler.java:103) at android.os.Looper.loop(Looper.java:219) at android.app.ActivityThread.main(ActivityThread.java:8347) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1055)

and iOS :

Fatal Exception: FirebaseCrashlyticsTestCrash 0 CoreFoundation 0x19e6d9114 exceptionPreprocess 1 libobjc.A.dylib 0x1b1effcb4 objc_exception_throw 2 Runner 0x1009f2e74 56-[FLTFirebaseCrashlyticsPlugin handleMethodCall:result:]_block_invoke + 61 (FLTFirebaseCrashlyticsPlugin.m:61) 3 Flutter 0x1013a9958 (Missing) 4 Flutter 0x100e8c618 (Missing) 5 Flutter 0x101152f6c (Missing) 6 Flutter 0x100e956c4 (Missing) 7 Flutter 0x100e9733c (Missing) 8 CoreFoundation 0x19e659a30 CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION 9 CoreFoundation 0x19e659634 CFRunLoopDoTimer 10 CoreFoundation 0x19e658b14 CFRunLoopDoTimers 11 CoreFoundation 0x19e652eb0 __CFRunLoopRun 12 CoreFoundation 0x19e652200 CFRunLoopRunSpecific 13 GraphicsServices 0x1b474d598 GSEventRunModal 14 UIKitCore 0x1a0f18004 -[UIApplication _run] 15 UIKitCore 0x1a0f1d5d8 UIApplicationMain 16 Runner 0x100827d3c main + 5 (AppDelegate.swift:5) 17 libdyld.dylib 0x19e331598 start

crashlytics_android_fatal_stacktrace crashlytics_ios_fatal_stacktrace

Should non-fatal and fatal errors both produce the same level of crash info with respect to line numbers etc?

markusaksli-nc commented 3 years ago

It depends on the error but typically fatal errors only occur only on the native side anyway. Unhandled exceptions in Flutter are technically not crashes - on Android the Android activity is still running as the exception did not occur on the native UI thread.

This is why fatal crashes usually only have a native stack. This is also the case for FirebaseCrashlytics.instance.crash() and is mentioned in the documentation:

Causes the app to crash (natively). Note: crash reports will not include a stack trace.

Does this answer your question?

kungfuslippers commented 3 years ago

@markusaksli-nc

Yes, I think it clarifies some of the limitations. I was unsure of what to expect as you'd said:

-"FF Crashlytics does log the source code file and line numbers and even full thread dumps if you FirebaseCrashlytics.instance.crash()."-

..earlier in the thread.

But thanks for all your help in clarifying matters. :-)

markusaksli-nc commented 3 years ago

Yeah, that was my bad for saying two things at the same time.

I'll close this issue as solved then.