DataDog / dd-sdk-flutter

Flutter bindings and tools for utilizing Datadog Mobile SDKs
Apache License 2.0
45 stars 41 forks source link

App Crashes On StartUp #651

Closed LarssK-TS closed 1 month ago

LarssK-TS commented 1 month ago

Stack trace

FATAL EXCEPTION: main Process: com.xxxxx.mobile_app, PID: 11249 java.lang.UnsatisfiedLinkError: No implementation found for void i2.o.b(int, java.lang.String, long) (tried Java_i2_o_b and Java_i2_o_b__ILjava_lang_String_2J) at i2.o.b(Native Method) at i2.o.e(NdkCrashReportsFeature.kt:151) at y1.z.i(SdkFeature.kt:312) at y1.r.f(DatadogCore.kt:25) at E2.v.onMethodCall(DatadogSdkPlugin.kt:1226) at C9.j$a.a(MethodChannel.java:18) at s9.c.i(DartMessenger.java:46) at s9.b.run(R8$$SyntheticClass:13) at android.os.Handler.handleCallback(Handler.java:873) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:193) at android.app.ActivityThread.main(ActivityThread.java:6692) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

Reproduction steps

    DatadogSdk? datadogSdk;

    final currentRegion = defaultRegion ?? Region.UK;
    final currentConfiguration = configurations[currentRegion];
    // Only use datadog for configurations that have datadogServiceConfig
    if (currentConfiguration != null && currentConfiguration.datadogServiceConfig != null) {
      final datadogAppConfig = currentConfiguration.datadogServiceConfig!;

      try {
        final datadogConfig = DatadogConfiguration(
          clientToken: datadogAppConfig.datadogClientToken,
          env: '${currentRegion.name}-${appEnv.name}',
          site: DatadogSite.eu1,
          nativeCrashReportEnabled: true,
          rumConfiguration: DatadogRumConfiguration(
            applicationId: datadogAppConfig.datadogApplicationId,
          ),
        )..enableHttpTracking();

        datadogSdk = DatadogSdk.instance;
        final datadogLoggerConfiguration = DatadogLoggerConfiguration(
          networkInfoEnabled: true,
        );
        datadogSdk.logs?.createLogger(datadogLoggerConfiguration);
        await datadogSdk.initialize(datadogConfig, TrackingConsent.granted);
      } catch (_) {
        //Not a production service so no need to handle error
      }
    }
    // END Setup Datadog logging service
    final datadogService = DatadogService(datadogSdk);
    LoggingService(datadogService);

    FlutterError.onError = (FlutterErrorDetails flutterErrorDetails) async {
      final FlutterErrorDetails error = flutterErrorDetails.exception is HttpServiceException
          ? flutterErrorDetails.copyWith(
              exception:
                  (flutterErrorDetails.exception as HttpServiceException).exceptionForCrashlytics,
            )
          : flutterErrorDetails;

      await FirebaseCrashlytics.instance.recordFlutterError(error);
      if (datadogSdk != null) datadogSdk.rum?.handleFlutterError(error);
    };
// runApp

Volume

100%

Affected SDK versions

2.7.0

Latest working SDK version

No response

Does the crash manifest in the latest SDK version?

Yes

Flutter Version

3.24.2

Setup Type

Flutter application [✓] Flutter (Channel stable, 3.24.2, on macOS 15.0 24A335 darwin-arm64, locale en-GB) • Flutter version 3.24.2 on channel stable at /Users/xxxxx/.asdf/installs/flutter/3.24.2-stable • Upstream repository https://github.com/flutter/flutter.git • Framework revision 4cf269e36d (3 weeks ago), 2024-09-03 14:30:00 -0700 • Engine revision a6bd3f1de1 • Dart version 3.5.2 • DevTools version 2.37.2

[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0) • Android SDK at /Users/xxxxx/Library/Android/sdk • Platform android-34, build-tools 34.0.0 • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 17.0.11+0-17.0.11b1207.24-11852314) • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 16.0) • Xcode at /Applications/Xcode.app/Contents/Developer • Build 16A242d • CocoaPods version 1.15.2

Kotlin 1.8.22 Gradle 8.2.2

Device Information

Android only

Other relevant information

If we comment out the initialization of DataDog then the app will work fine.

fuzzybinary commented 1 month ago

Hi @LarssK-TS ,

Thanks for reporting, I'll start looking into it.

Any chance you can get that stack trace deobfuscated by sending your Proguard mapping file to Datadog?

fuzzybinary commented 1 month ago

Sorry, I meant the mapping file that's generated as part of your build, so Datadog could deobfuscate, but since you're likely not getting the error in Datadog to begin with that won't help.

Alternately, can you try running without obfuscation, just so we can see the names of the methods that are being called?

LarssK-TS commented 1 month ago

Sorry, I meant the mapping file that's generated as part of your build, so Datadog could deobfuscate, but since you're likely not getting the error in Datadog to begin with that won't help.

Alternately, can you try running without obfuscation, just so we can see the names of the methods that are being called?

 Fatal Exception: java.lang.UnsatisfiedLinkError: No implementation found for void i2.o.b(int, java.lang.String, long) (tried Java_i2_o_b and Java_i2_o_b__ILjava_lang_String_2J)
 at com.datadog.android.ndk.internal.NdkCrashReportsFeature.registerSignalHandler(NdkCrashReportsFeature.kt)
 at com.datadog.android.ndk.internal.NdkCrashReportsFeature.onInitialize(NdkCrashReportsFeature.kt:68)
 at com.datadog.android.core.internal.SdkFeature.initialize(SdkFeature.kt:108)
 at com.datadog.android.core.internal.DatadogCore.registerFeature(DatadogCore.kt:135)
 at com.datadog.android.ndk.NdkCrashReports.enable(NdkCrashReports.java:30)
 at com.datadog.android.ndk.NdkCrashReports.enable$default(NdkCrashReports.java:27)
 at com.datadoghq.flutter.DatadogSdkPlugin.initialize(DatadogSdkPlugin.kt:213)
 at com.datadoghq.flutter.DatadogSdkPlugin.onMethodCall(DatadogSdkPlugin.kt:91)
 at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:267)
 at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:292)
 at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0(DartMessenger.java:319)
 at android.os.Handler.handleCallback(Handler.java:873)
 at android.os.Handler.dispatchMessage(Handler.java:99)
 at android.os.Looper.loop(Looper.java:193)
 at android.app.ActivityThread.main(ActivityThread.java:6692)
 at java.lang.reflect.Method.invoke(Method.java)
 at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

Not sure but this might help, looks like it's point an issue here https://github.com/DataDog/dd-sdk-flutter/blob/develop/packages/datadog_flutter_plugin/android/src/main/kotlin/com/datadoghq/flutter/DatadogSdkPlugin.kt#L205-L216

fuzzybinary commented 1 month ago

Okay, this is very strange.

The Android Datadog SDK calls a JNI method registerSignalHandler, which it can't find. But, registerSignalHandler's signature is (String, int, long) not (int, String, long) as the error suggests (hence why it can't find it. Also, the only change recently was to add the long to the end, the order of the other parameters didn't change

A few diagnostic steps:

The way I tend to look at the Android SDK code is:

LarssK-TS commented 1 month ago

When did this start happening? Did you make any changes recently that might be responsible?

Yes we made changes, we have updated our application to Flutter 3.24.2 and it's dependencies, upgraded Flutter DataDog Plugin from 2.1.0 to 2.7.0, DataDog tracking_http_client 2.0.0 to 2.2.0. We also updated the Android Gradle plugin to 8.2.2 following this guide https://docs.flutter.dev/release/breaking-changes/flutter-gradle-plugin-apply

Are you using anything that might be rewriting parameter order for some reason?

No we don't believe so but there have been a few similar issues reported on the flutter side, see here https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+UnsatisfiedLinkError

Can you double check the Datadog Android SDK version you've downloaded and the code it has?

Please see attached screenshot

Gradle: com.datadoghq:dd-sdk-android-ndk:2.12.1@aar

private external fun registerSignalHandler(
        storagePath: String,
        consent: Int,
        appStartTimeMs: Long
    )

Screenshot 2024-09-24 at 7 12 01 PM

LarssK-TS commented 1 month ago

@fuzzybinary I forgot to mention one important point, when building the app locally the app works on physical devices and emulators. But when built remotely on Fastlane the build will crash for both emulator and physical devices. However, when the Datadog initialisation is removed from the Fastlane builds the app runs without issue.

fuzzybinary commented 1 month ago

@LarssK-TS Are there any build commands that are different on Fastlane? Can you get a build locally that will crash and, if so, can you send me the commands / setup that will cause the crash?

This doesn't sound like a Flutter or Datadog issue to me. Something in your build process is rewriting that JNI call for some unknown reason.

LarssK-TS commented 1 month ago

Hi, I will investigate and get back to you tomorrow morning with our findings.

LarssK-TS commented 1 month ago

Fastlane builds worked without issue before we started the upgrade. We'll investigate further and come back to you with an update.

LarssK-TS commented 1 month ago

We've managed to resolve the issue. The problem was on our side

fuzzybinary commented 1 month ago

@LarssK-TS Glad to hear it! Was the fix something that might affect other teams or was it very specific to your workflow?

LarssK-TS commented 1 month ago

@LarssK-TS Glad to hear it! Was the fix something that might affect other teams or was it very specific to your workflow?

Hi sorry for the late reply, yes maybe. Inside android/build.gradle we had

rootProject.buildDir = '../build'
subprojects {
    project.buildDir = "${rootProject.buildDir}/${project.name}"
    project.evaluationDependsOn(':app')
}

instead of

rootProject.buildDir = '../build'
subprojects {
    project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
    project.evaluationDependsOn(':app')
}
fuzzybinary commented 1 month ago

Thanks for letting me know! I have no idea why that would cause a crash, but if anyone else has this issue, hopefully this will help!