Skip to content

Commit

Permalink
Enha: Don't supress error logs (#1228)
Browse files Browse the repository at this point in the history
  • Loading branch information
denrase authored Jan 23, 2023
1 parent 68ea1ef commit 16ab023
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 8 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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);
}
}
17 changes: 17 additions & 0 deletions flutter/lib/src/sentry_flutter.dart
Original file line number Diff line number Diff line change
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,10 @@ mixin SentryFlutter {
? false
: wrapper.isOnErrorSupported(flutterOptions);

final runZonedGuardedOnError = flutterOptions.platformChecker.isWeb
? _createRunZonedGuardedOnError()
: null;

// 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 +88,8 @@ mixin SentryFlutter {
options: flutterOptions,
// ignore: invalid_use_of_internal_member
callAppRunnerInRunZonedGuarded: !isOnErrorSupported,
// ignore: invalid_use_of_internal_member
runZonedGuardedOnError: runZonedGuardedOnError,
);
}

Expand Down Expand Up @@ -184,6 +191,16 @@ mixin SentryFlutter {
return integrations;
}

static RunZonedGuardedOnError _createRunZonedGuardedOnError() {
return (Object error, StackTrace stackTrace) async {
final errorDetails = FlutterErrorDetails(
exception: error,
stack: stackTrace,
);
FlutterError.dumpErrorToConsole(errorDetails, forceReport: true);
};
}

/// Manually set when your app finished startup. Make sure to set
/// [SentryFlutterOptions.autoAppStart] to false on init.
static void setAppStartEnd(DateTime appStartEnd) {
Expand Down

0 comments on commit 16ab023

Please sign in to comment.