Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide a way to cause an example native crash from Flutter #2239

Merged
merged 10 commits into from
Aug 21, 2024
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Features

- Add `SentryFlutter.nativeCrash()` using MethodChannels for Android and iOS ([#2239](https://github.com/getsentry/sentry-dart/pull/2239))
martinhaintz marked this conversation as resolved.
Show resolved Hide resolved
- Add `ignoreRoutes` parameter to `SentryNavigatorObserver`. ([#2218](https://github.com/getsentry/sentry-dart/pull/2218))
- This will ignore the Routes and prevent the Route from being pushed to the Sentry server.
- Ignored routes will also create no TTID and TTFD spans.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package io.sentry.flutter
import android.app.Activity
import android.content.Context
import android.os.Build
import android.os.Looper
import android.util.Log
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
Expand Down Expand Up @@ -74,6 +75,7 @@ class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
"removeTag" -> removeTag(call.argument("key"), result)
"loadContexts" -> loadContexts(result)
"displayRefreshRate" -> displayRefreshRate(result)
"nativeCrash" -> crash(result)
else -> result.notImplemented()
}
}
Expand Down Expand Up @@ -466,4 +468,11 @@ class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
)
result.success(serializedScope)
}

private fun crash(result: Result) {
val exception = RuntimeException("FlutterSentry Native Integration: Sample RuntimeException")
val mainThread = Looper.getMainLooper().thread
mainThread.uncaughtExceptionHandler.uncaughtException(mainThread, exception)
mainThread.join(500)
}
}
12 changes: 12 additions & 0 deletions flutter/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,12 @@ class AndroidExample extends StatelessWidget {
},
child: const Text('Platform exception'),
),
ElevatedButton(
onPressed: () async {
SentryFlutter.nativeCrash();
},
child: const Text('Sentry.nativeCrash'),
),
]);
}
}
Expand Down Expand Up @@ -870,6 +876,12 @@ class CocoaExample extends StatelessWidget {
},
child: const Text('Objective-C SEGFAULT'),
),
ElevatedButton(
onPressed: () async {
SentryFlutter.nativeCrash();
},
child: const Text('Sentry.nativeCrash'),
),
],
);
}
Expand Down
7 changes: 7 additions & 0 deletions flutter/ios/Classes/SentryFlutterPluginApple.swift
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,9 @@ public class SentryFlutterPluginApple: NSObject, FlutterPlugin {
case "resumeAppHangTracking":
resumeAppHangTracking(result)

case "nativeCrash":
crash()

default:
result(FlutterMethodNotImplemented)
}
Expand Down Expand Up @@ -729,6 +732,10 @@ public class SentryFlutterPluginApple: NSObject, FlutterPlugin {
SentrySDK.resumeAppHangTracking()
result("")
}

private func crash() {
SentrySDK.crash()
}
}

// swiftlint:enable function_body_length
Expand Down
2 changes: 2 additions & 0 deletions flutter/lib/src/native/sentry_native_binding.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,6 @@ abstract class SentryNativeBinding {
Future<void> pauseAppHangTracking();

Future<void> resumeAppHangTracking();

Future<void> nativeCrash();
}
3 changes: 3 additions & 0 deletions flutter/lib/src/native/sentry_native_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -194,4 +194,7 @@
@override
Future<void> resumeAppHangTracking() =>
_channel.invokeMethod('resumeAppHangTracking');

@override
Future<void> nativeCrash() => _channel.invokeMethod('nativeCrash');

Check warning on line 199 in flutter/lib/src/native/sentry_native_channel.dart

View check run for this annotation

Codecov / codecov/patch

flutter/lib/src/native/sentry_native_channel.dart#L198-L199

Added lines #L198 - L199 were not covered by tests
}
28 changes: 18 additions & 10 deletions flutter/lib/src/sentry_flutter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -249,11 +249,7 @@
/// Only for iOS and macOS.
static Future<void> pauseAppHangTracking() {
if (_native == null) {
// ignore: invalid_use_of_internal_member
Sentry.currentHub.options.logger(
SentryLevel.debug,
'Native integration is not available. Make sure SentryFlutter is initialized before accessing the pauseAppHangTracking API.',
);
_logNativeIntegrationNotAvailable("pauseAppHangTracking");
martinhaintz marked this conversation as resolved.
Show resolved Hide resolved
return Future<void>.value();
}
return _native!.pauseAppHangTracking();
Expand All @@ -263,11 +259,7 @@
/// Only for iOS and macOS
static Future<void> resumeAppHangTracking() {
if (_native == null) {
// ignore: invalid_use_of_internal_member
Sentry.currentHub.options.logger(
SentryLevel.debug,
'Native integration is not available. Make sure SentryFlutter is initialized before accessing the resumeAppHangTracking API.',
);
_logNativeIntegrationNotAvailable("resumeAppHangTracking");
return Future<void>.value();
}
return _native!.resumeAppHangTracking();
Expand All @@ -280,4 +272,20 @@
static set native(SentryNativeBinding? value) => _native = value;

static SentryNativeBinding? _native;

static Future<void> nativeCrash() {

Check warning on line 276 in flutter/lib/src/sentry_flutter.dart

View check run for this annotation

Codecov / codecov/patch

flutter/lib/src/sentry_flutter.dart#L276

Added line #L276 was not covered by tests
martinhaintz marked this conversation as resolved.
Show resolved Hide resolved
if (_native == null) {
_logNativeIntegrationNotAvailable("nativeCrash");
return Future<void>.value();

Check warning on line 279 in flutter/lib/src/sentry_flutter.dart

View check run for this annotation

Codecov / codecov/patch

flutter/lib/src/sentry_flutter.dart#L278-L279

Added lines #L278 - L279 were not covered by tests
}
return _native!.nativeCrash();

Check warning on line 281 in flutter/lib/src/sentry_flutter.dart

View check run for this annotation

Codecov / codecov/patch

flutter/lib/src/sentry_flutter.dart#L281

Added line #L281 was not covered by tests
}

static void _logNativeIntegrationNotAvailable(String methodName) {
// ignore: invalid_use_of_internal_member
Sentry.currentHub.options.logger(
SentryLevel.debug,
'Native integration is not available. Make sure SentryFlutter is initialized before accessing the $methodName API.',
);
}
}
Loading