Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
4 changes: 2 additions & 2 deletions .github/workflows/dart.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
# TODO: cedx/setup-dart@v2 doesn't work on Windows (doesn't add pub to the PATH?)
# os: [ubuntu-latest, windows-latest, macos-latest]
os: [ubuntu-latest, macos-latest]
sdk: [beta, dev, stable]
sdk: [beta, dev]
exclude:
# Bad state: Could not run tests with Observatory enabled. Try setting a different port with --port option.
- os: ubuntu-latest
Expand Down Expand Up @@ -61,7 +61,7 @@ jobs:
steps:
- uses: cedx/setup-dart@v2
with:
release-channel: stable
release-channel: beta
- uses: actions/checkout@v2
- run: |
dart pub get
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/flutter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
target: ['ios', 'android', 'web']
channel: ['stable', 'beta']
channel: ['beta']
exclude:
- os: ubuntu-latest
target: ios
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@

# 4.0.6

* Fix: Do not append stack trace to the exception if there are no frames
* Fix: Empty DSN disables the SDK and runs the App

# 4.0.6

* Refactoring: Migrate Sentry Dart to null safety
* Fix: captureMessage defaults SentryLevel to info
* Fix: SentryEvent.throwable returns the unwrapped throwable instead of the throwableMechanism
* Feat: Support enableNativeCrashHandling on iOS
Expand Down
11 changes: 5 additions & 6 deletions dart/lib/src/http_client/sentry_http_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,12 @@ import '../../sentry.dart';
// For example with Darts Stopwatch:
// https://api.dart.dev/stable/2.10.4/dart-core/Stopwatch-class.html
class SentryHttpClient extends BaseClient {
SentryHttpClient({Client client, Hub hub}) {
_hub = hub ?? HubAdapter();
_client = client ?? Client();
}
SentryHttpClient({Client? client, Hub? hub})
: _hub = hub ?? HubAdapter(),
_client = client ?? Client();

Client _client;
Hub _hub;
final Client _client;
final Hub _hub;

@override
Future<StreamedResponse> send(BaseRequest request) async {
Expand Down
192 changes: 65 additions & 127 deletions dart/lib/src/hub.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import 'dart:async';
import 'dart:collection';

import 'noop_sentry_client.dart';
import 'protocol.dart';
import 'scope.dart';
import 'sentry_client.dart';
Expand All @@ -18,8 +17,9 @@ class Hub {

final ListQueue<_StackItem> _stack = ListQueue();

/// if stack is empty, it throws IterableElementError.noElement()
_StackItem _peek() => _stack.isNotEmpty ? _stack.first : null;
// peek can never return null since Stack can be created only with an item and
// pop does not drop the last item.
_StackItem _peek() => _stack.first;

final SentryOptions _options;

Expand All @@ -35,11 +35,7 @@ class Hub {
}

static void _validateOptions(SentryOptions options) {
if (options == null) {
throw ArgumentError('SentryOptions is required.');
}

if (options.dsn?.isNotEmpty != true) {
if (options.dsn == null) {
throw ArgumentError('DSN is required.');
}
}
Expand Down Expand Up @@ -67,34 +63,23 @@ class Hub {
SentryLevel.warning,
"Instance is disabled and this 'captureEvent' call is a no-op.",
);
} else if (event == null) {
_options.logger(
SentryLevel.warning,
'captureEvent called with null parameter.',
);
} else {
final item = _peek();
if (item != null) {
try {
sentryId = await item.client.captureEvent(
event,
stackTrace: stackTrace,
scope: item.scope,
hint: hint,
);
} catch (err) {
_options.logger(
SentryLevel.error,
'Error while capturing event with id: ${event.eventId}, error: $err',
);
} finally {
_lastEventId = sentryId;
}
} else {

try {
sentryId = await item.client.captureEvent(
event,
stackTrace: stackTrace,
scope: item.scope,
hint: hint,
);
} catch (err) {
_options.logger(
SentryLevel.fatal,
'Stack peek was null when captureEvent',
SentryLevel.error,
'Error while capturing event with id: ${event.eventId}, error: $err',
);
} finally {
_lastEventId = sentryId;
}
}
return sentryId;
Expand All @@ -120,27 +105,21 @@ class Hub {
);
} else {
final item = _peek();
if (item != null) {
try {
sentryId = await item.client.captureException(
throwable,
stackTrace: stackTrace,
scope: item.scope,
hint: hint,
);
} catch (err) {
_options.logger(
SentryLevel.error,
'Error while capturing exception : $throwable',
);
} finally {
_lastEventId = sentryId;
}
} else {

try {
sentryId = await item.client.captureException(
throwable,
stackTrace: stackTrace,
scope: item.scope,
hint: hint,
);
} catch (err) {
_options.logger(
SentryLevel.fatal,
'Stack peek was null when captureException',
SentryLevel.error,
'Error while capturing exception : $throwable',
);
} finally {
_lastEventId = sentryId;
}
}

Expand All @@ -149,10 +128,10 @@ class Hub {

/// Captures the message.
Future<SentryId> captureMessage(
String message, {
SentryLevel level,
String template,
List<dynamic> params,
String? message, {
SentryLevel? level,
String? template,
List<dynamic>? params,
dynamic hint,
}) async {
var sentryId = SentryId.empty();
Expand All @@ -169,29 +148,23 @@ class Hub {
);
} else {
final item = _peek();
if (item != null) {
try {
sentryId = await item.client.captureMessage(
message,
level: level,
template: template,
params: params,
scope: item.scope,
hint: hint,
);
} catch (err) {
_options.logger(
SentryLevel.error,
'Error while capturing message with id: $message, error: $err',
);
} finally {
_lastEventId = sentryId;
}
} else {

try {
sentryId = await item.client.captureMessage(
message,
level: level,
template: template,
params: params,
scope: item.scope,
hint: hint,
);
} catch (err) {
_options.logger(
SentryLevel.fatal,
'Stack peek was null when captureMessage',
SentryLevel.error,
'Error while capturing message with id: $message, error: $err',
);
} finally {
_lastEventId = sentryId;
}
}
return sentryId;
Expand All @@ -204,21 +177,9 @@ class Hub {
SentryLevel.warning,
"Instance is disabled and this 'addBreadcrumb' call is a no-op.",
);
} else if (crumb == null) {
_options.logger(
SentryLevel.warning,
'addBreadcrumb called with null parameter.',
);
} else {
final item = _peek();
if (item != null) {
item.scope.addBreadcrumb(crumb, hint: hint);
} else {
_options.logger(
SentryLevel.fatal,
'Stack peek was null when addBreadcrumb',
);
}
item.scope.addBreadcrumb(crumb, hint: hint);
}
}

Expand All @@ -229,20 +190,8 @@ class Hub {
"Instance is disabled and this 'bindClient' call is a no-op.");
} else {
final item = _peek();
if (item != null) {
if (client != null) {
_options.logger(SentryLevel.debug, 'New client bound to scope.');
item.client = client;
} else {
_options.logger(SentryLevel.debug, 'NoOp client bound to scope.');
item.client = NoOpSentryClient();
}
} else {
_options.logger(
SentryLevel.fatal,
'Stack peek was null when bindClient',
);
}
_options.logger(SentryLevel.debug, 'New client bound to scope.');
item.client = client;
}
}

Expand Down Expand Up @@ -272,21 +221,16 @@ class Hub {
}

final item = _peek();
if (item != null) {
try {
item.client.close();
} catch (err) {
_options.logger(
SentryLevel.error,
'Error while closing the Hub, error: $err',
);
}
} else {

try {
item.client.close();
} catch (err) {
_options.logger(
SentryLevel.fatal,
'Stack peek was NULL when closing Hub',
SentryLevel.error,
'Error while closing the Hub, error: $err',
);
}

_isEnabled = false;
}
}
Expand All @@ -300,19 +244,13 @@ class Hub {
);
} else {
final item = _peek();
if (item != null) {
try {
callback(item.scope);
} catch (err) {
_options.logger(
SentryLevel.error,
"Error in the 'configureScope' callback, error: $err",
);
}
} else {

try {
callback(item.scope);
} catch (err) {
_options.logger(
SentryLevel.fatal,
'Stack peek was NULL when configureScope',
SentryLevel.error,
"Error in the 'configureScope' callback, error: $err",
);
}
}
Expand Down
8 changes: 4 additions & 4 deletions dart/lib/src/hub_adapter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ class HubAdapter implements Hub {

@override
Future<SentryId> captureMessage(
String message, {
SentryLevel level,
String template,
List params,
String? message, {
SentryLevel? level,
String? template,
List? params,
dynamic hint,
}) =>
Sentry.captureMessage(
Expand Down
2 changes: 1 addition & 1 deletion dart/lib/src/isolate_error_integration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import 'sentry_options.dart';
import 'throwable_mechanism.dart';

class IsolateErrorIntegration extends Integration {
RawReceivePort _receivePort;
late RawReceivePort _receivePort;

@override
FutureOr<void> call(Hub hub, SentryOptions options) async {
Expand Down
Loading