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

Fix: Use PlatformDispatcher.onError in Flutter 3.3 #1039

Merged
merged 26 commits into from
Oct 13, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
60fba54
dont call apprunner in runzonedguarded if onError is supported
denrase Oct 3, 2022
df7b25d
Merge branch 'main' into fix/platform-dispatcher-onerror
denrase Oct 3, 2022
a18c5ac
format
denrase Oct 3, 2022
9360251
update changelog
denrase Oct 3, 2022
1a43cf1
fix analyze issues
denrase Oct 3, 2022
34a2d4f
use BindingUtils.getWidgetsBindingInstance() to access platform dispa…
denrase Oct 3, 2022
412aa83
dont check if error is supported again
denrase Oct 3, 2022
7d6f830
mark callAppRunnerInRunZonedGuarded as internal
denrase Oct 3, 2022
9b69409
Merge branch 'main' into fix/platform-dispatcher-onerror
denrase Oct 10, 2022
f3e8676
use PlatformDispatcher.instance
denrase Oct 10, 2022
628880b
move changelog entry to features
denrase Oct 10, 2022
3e52249
use type inference
denrase Oct 11, 2022
1c792b6
ignore warning
denrase Oct 11, 2022
315be14
remove unused import
denrase Oct 11, 2022
8189aaf
recreate mock.mocks.dart
denrase Oct 11, 2022
7b9e707
Merge branch 'main' into fix/platform-dispatcher-onerror
denrase Oct 11, 2022
281547a
Merge branch 'main' into fix/platform-dispatcher-onerror
marandaneto Oct 11, 2022
609026b
fix incorrect changelog
denrase Oct 11, 2022
f27e3c2
Merge branch 'main' into fix/platform-dispatcher-onerror
marandaneto Oct 11, 2022
a4d6e42
add WidgetsFlutterBindingIntegration before OnErrorIntegration
denrase Oct 11, 2022
6fdd196
Merge branch 'main' into fix/platform-dispatcher-onerror
denrase Oct 11, 2022
4ea91c6
add newline
denrase Oct 11, 2022
001e443
test that WidgetsFlutterBindingIntegration is before OnErrorIntegration
denrase Oct 11, 2022
33ad3ec
Merge branch 'main' into fix/platform-dispatcher-onerror
marandaneto Oct 13, 2022
485b071
fix
marandaneto Oct 13, 2022
1c94f1e
Merge branch 'main' into fix/platform-dispatcher-onerror
marandaneto Oct 13, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## Unreleased

### Fixes
denrase marked this conversation as resolved.
Show resolved Hide resolved

- Use PlatformDispatcher.onError in Flutter 3.3 ([#1039](https://github.com/getsentry/sentry-dart/pull/1039))

## 6.11.2

### Fixes
Expand Down
39 changes: 23 additions & 16 deletions dart/lib/src/sentry.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class Sentry {
static Future<void> init(
OptionsConfiguration optionsConfiguration, {
AppRunner? appRunner,
bool callAppRunnerInRunZonedGuarded = true,
marandaneto marked this conversation as resolved.
Show resolved Hide resolved
@internal SentryOptions? options,
}) async {
final sentryOptions = options ?? SentryOptions();
Expand All @@ -56,7 +57,7 @@ class Sentry {
throw ArgumentError('DSN is required.');
}

await _init(sentryOptions, appRunner);
await _init(sentryOptions, appRunner, callAppRunnerInRunZonedGuarded);
}

static Future<void> _initDefaultValues(
Expand Down Expand Up @@ -96,7 +97,8 @@ class Sentry {
}

/// Initializes the SDK
static Future<void> _init(SentryOptions options, AppRunner? appRunner) async {
static Future<void> _init(SentryOptions options, AppRunner? appRunner,
bool callAppRunnerInRunZonedGuarded) async {
if (isEnabled) {
options.logger(
SentryLevel.warning,
Expand All @@ -113,21 +115,26 @@ class Sentry {

// execute integrations after hub being enabled
if (appRunner != null) {
var runIntegrationsAndAppRunner = () async {
final integrations =
options.integrations.where((i) => i is! RunZonedGuardedIntegration);
await _callIntegrations(integrations, options);
if (callAppRunnerInRunZonedGuarded) {
var runIntegrationsAndAppRunner = () async {
final integrations = options.integrations
.where((i) => i is! RunZonedGuardedIntegration);
await _callIntegrations(integrations, options);
await appRunner();
};

final runZonedGuardedIntegration =
RunZonedGuardedIntegration(runIntegrationsAndAppRunner);
options.addIntegrationByIndex(0, runZonedGuardedIntegration);

// RunZonedGuardedIntegration will run other integrations and appRunner
// runZonedGuarded so all exception caught in the error handler are
// handled
await runZonedGuardedIntegration(HubAdapter(), options);
} else {
await _callIntegrations(options.integrations, options);
await appRunner();
};

final runZonedGuardedIntegration =
RunZonedGuardedIntegration(runIntegrationsAndAppRunner);
options.addIntegrationByIndex(0, runZonedGuardedIntegration);

// RunZonedGuardedIntegration will run other integrations and appRunner
// runZonedGuarded so all exception caught in the error handler are
// handled
await runZonedGuardedIntegration(HubAdapter(), options);
}
} else {
await _callIntegrations(options.integrations, options);
}
Expand Down
25 changes: 25 additions & 0 deletions dart/test/sentry_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,31 @@ void main() {
});
});

test('should complete when appRunner is not called in runZonedGuarded',
() async {
final completer = Completer();
var completed = false;

final init = Sentry.init(
(options) {
options.dsn = fakeDsn;
},
appRunner: () => completer.future,
callAppRunnerInRunZonedGuarded: false,
).whenComplete(() => completed = true);

await Future(() {
// We make the expectation only after all microtasks have completed,
// that Sentry.init might have scheduled.
expect(completed, false);
});

completer.complete();
await init;

expect(completed, true);
});

test('options.environment debug', () async {
final sentryOptions = SentryOptions(dsn: fakeDsn)
..platformChecker = FakePlatformChecker.debugMode();
Expand Down
34 changes: 19 additions & 15 deletions flutter/lib/src/sentry_flutter.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import 'dart:async';
import 'dart:ui';

import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
import 'package:meta/meta.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:sentry/sentry.dart';
import '../sentry_flutter.dart';
import 'event_processor/android_platform_exception_event_processor.dart';
import 'native_scope_observer.dart';
import 'sentry_native.dart';
Expand All @@ -13,9 +14,7 @@ import 'sentry_native_channel.dart';
import 'flutter_enricher_event_processor.dart';
import 'integrations/debug_print_integration.dart';
import 'integrations/native_app_start_integration.dart';
import 'sentry_flutter_options.dart';

import 'default_integrations.dart';
import 'file_system_transport.dart';

import 'version.dart';
Expand Down Expand Up @@ -45,27 +44,26 @@ mixin SentryFlutter {
final native = SentryNative();
native.setNativeChannel(nativeChannel);

final wrapper = PlatformDispatcherWrapper(PlatformDispatcher.instance);
denrase marked this conversation as resolved.
Show resolved Hide resolved
final isOnErrorSupported = wrapper.isOnErrorSupported(flutterOptions);
denrase marked this conversation as resolved.
Show resolved Hide resolved

// first step is to install the native integration and set default values,
// so we are able to capture future errors.
final defaultIntegrations = _createDefaultIntegrations(
packageLoader,
channel,
flutterOptions,
);
packageLoader, channel, flutterOptions, isOnErrorSupported);
for (final defaultIntegration in defaultIntegrations) {
flutterOptions.addIntegration(defaultIntegration);
}

await _initDefaultValues(flutterOptions, channel);

await Sentry.init(
(options) async {
await optionsConfiguration(options as SentryFlutterOptions);
},
appRunner: appRunner,
// ignore: invalid_use_of_internal_member
options: flutterOptions,
);
await Sentry.init((options) async {
await optionsConfiguration(options as SentryFlutterOptions);
},
appRunner: appRunner,
// ignore: invalid_use_of_internal_member
options: flutterOptions,
callAppRunnerInRunZonedGuarded: !isOnErrorSupported);
marandaneto marked this conversation as resolved.
Show resolved Hide resolved
}

static Future<void> _initDefaultValues(
Expand Down Expand Up @@ -96,11 +94,17 @@ mixin SentryFlutter {
PackageLoader packageLoader,
MethodChannel channel,
SentryFlutterOptions options,
bool isOnErrorSupported,
) {
final integrations = <Integration>[];
final platformChecker = options.platformChecker;
final platform = platformChecker.platform;

// Use PlatformDispatcher.onError instead of zones.
if (isOnErrorSupported) {
integrations.add(OnErrorIntegration());
}

// Will call WidgetsFlutterBinding.ensureInitialized() before all other integrations.
integrations.add(WidgetsFlutterBindingIntegration());

Expand Down
Loading