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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enha: Don't supress error logs #1228

Merged
merged 6 commits into from Jan 23, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Fixes

- Don't suppress error logs ([#1228](https://github.com/getsentry/sentry-dart/pull/1228))

### Breaking Changes

- Remove deprecated fields ([#1227](https://github.com/getsentry/sentry-dart/pull/1227))
Expand Down
15 changes: 13 additions & 2 deletions dart/lib/src/run_zoned_guarded_integration.dart
Expand Up @@ -8,16 +8,23 @@ import 'protocol.dart';
import 'sentry_options.dart';
import 'throwable_mechanism.dart';

/// Called inside of `runZonedGuarded`
typedef RunZonedGuardedRunner = Future<void> Function();

/// Caught exception and stacktrace in `runZonedGuarded`
typedef RunZonedGuardedOnError = FutureOr<void> Function(Object, StackTrace);

/// Integration that runs runner function within `runZonedGuarded` and capture
/// errors on the `runZonedGuarded` error handler.
/// See https://api.dart.dev/stable/dart-async/runZonedGuarded.html
///
/// This integration also records calls to `print()` as Breadcrumbs.
/// This can be configured with [SentryOptions.enablePrintBreadcrumbs]
class RunZonedGuardedIntegration extends Integration {
RunZonedGuardedIntegration(this._runner);
RunZonedGuardedIntegration(this._runner, this._onError);

final Future<void> Function() _runner;
final RunZonedGuardedRunner _runner;
final RunZonedGuardedOnError? _onError;

/// Needed to check if we somehow caused a `print()` recursion
bool _isPrinting = false;
Expand Down Expand Up @@ -70,6 +77,10 @@ class RunZonedGuardedIntegration extends Integration {
},
(exception, stackTrace) async {
await captureError(hub, options, exception, stackTrace);
final onError = _onError;
if (onError != null) {
await onError(exception, stackTrace);
}
},
zoneSpecification: ZoneSpecification(
print: (self, parent, zone, line) {
Expand Down
9 changes: 6 additions & 3 deletions dart/lib/src/sentry.dart
Expand Up @@ -39,6 +39,7 @@ class Sentry {
OptionsConfiguration optionsConfiguration, {
AppRunner? appRunner,
@internal bool callAppRunnerInRunZonedGuarded = true,
@internal RunZonedGuardedOnError? runZonedGuardedOnError,
@internal SentryOptions? options,
}) async {
final sentryOptions = options ?? SentryOptions();
Expand All @@ -59,7 +60,8 @@ class Sentry {
throw ArgumentError('DSN is required.');
}

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

static Future<void> _initDefaultValues(SentryOptions options) async {
Expand Down Expand Up @@ -101,6 +103,7 @@ class Sentry {
SentryOptions options,
AppRunner? appRunner,
bool callAppRunnerInRunZonedGuarded,
RunZonedGuardedOnError? runZonedGuardedOnError,
) async {
if (isEnabled) {
options.logger(
Expand All @@ -126,8 +129,8 @@ class Sentry {
await appRunner();
};

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

// RunZonedGuardedIntegration will run other integrations and appRunner
Expand Down
25 changes: 22 additions & 3 deletions dart/test/run_zoned_guarded_integration_test.dart
Expand Up @@ -25,7 +25,7 @@ void main() {
final client = MockSentryClient();
hub.bindClient(client);

final sut = fixture.getSut();
final sut = fixture.getSut(runner: () async {});

hub.startTransaction('name', 'operation', bindToScope: true);

Expand All @@ -37,14 +37,33 @@ void main() {

await span?.finish();
});

test('calls onError', () async {
final error = StateError("StateError");
var onErrorCalled = false;
RunZonedGuardedRunner runner = () async {
throw error;
};
RunZonedGuardedOnError onError = (error, stackTrace) async {
onErrorCalled = true;
};
final sut = fixture.getSut(runner: runner, onError: onError);

sut.call(fixture.hub, fixture.options);
await Future.delayed(Duration(milliseconds: 10));

expect(onErrorCalled, true);
});
});
}

class Fixture {
final hub = MockHub();
final options = SentryOptions(dsn: fakeDsn)..tracesSampleRate = 1.0;

RunZonedGuardedIntegration getSut() {
return RunZonedGuardedIntegration(() async {});
RunZonedGuardedIntegration getSut(
{required RunZonedGuardedRunner runner,
RunZonedGuardedOnError? onError}) {
return RunZonedGuardedIntegration(runner, onError);
}
}
13 changes: 13 additions & 0 deletions flutter/lib/src/sentry_flutter.dart
Expand Up @@ -3,6 +3,7 @@ import 'dart:ui';

import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:meta/meta.dart';
import '../sentry_flutter.dart';
import 'event_processor/android_platform_exception_event_processor.dart';
Expand Down Expand Up @@ -61,6 +62,16 @@ mixin SentryFlutter {
? false
: wrapper.isOnErrorSupported(flutterOptions);

final runZonedGuardedOnError = flutterOptions.platformChecker.isWeb
? (Object error, StackTrace stackTrace) async {
final errorDetails = FlutterErrorDetails(
exception: error,
stack: stackTrace,
);
FlutterError.dumpErrorToConsole(errorDetails, forceReport: true);
}
: null;
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(
Expand All @@ -83,6 +94,8 @@ mixin SentryFlutter {
options: flutterOptions,
// ignore: invalid_use_of_internal_member
callAppRunnerInRunZonedGuarded: !isOnErrorSupported,
// ignore: invalid_use_of_internal_member
runZonedGuardedOnError: runZonedGuardedOnError,
);
}

Expand Down