Skip to content

Commit

Permalink
Add mechanism to Dio Http Client error (#1114)
Browse files Browse the repository at this point in the history
  • Loading branch information
marandaneto authored Nov 9, 2022
1 parent 0db91cc commit 3a69405
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- Merging of integrations and packages ([#1111](https://github.com/getsentry/sentry-dart/pull/1111))
- Add missing `fragment` for HTTP Client Errors ([#1102](https://github.com/getsentry/sentry-dart/pull/1102))
- Sync user name and geo for Android ([#1102](https://github.com/getsentry/sentry-dart/pull/1102))
- Add mechanism to Dio Http Client error ([#1114](https://github.com/getsentry/sentry-dart/pull/1114))

### Dependencies

Expand Down
15 changes: 12 additions & 3 deletions dart/lib/src/http_client/failed_request_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,7 @@ class FailedRequestClient extends BaseClient {
} else if (failedRequestStatusCodes.containsStatusCode(statusCode)) {
// Capture an exception if the status code is considered bad
capture = true;
reason =
'Event was captured because the request status code was $statusCode';
reason = 'HTTP Client Error with status code: $statusCode';
exception ??= SentryHttpClientError(reason);
}
if (capture) {
Expand Down Expand Up @@ -184,7 +183,17 @@ class FailedRequestClient extends BaseClient {
type: 'SentryHttpClient',
description: reason,
);
final throwableMechanism = ThrowableMechanism(mechanism, exception);

bool? snapshot;
if (exception is SentryHttpClientError) {
snapshot = true;
}

final throwableMechanism = ThrowableMechanism(
mechanism,
exception,
snapshot: snapshot,
);

final event = SentryEvent(
throwable: throwableMechanism,
Expand Down
5 changes: 5 additions & 0 deletions dart/lib/src/sentry_exception_factory.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ class SentryExceptionFactory {
}) {
var throwable = exception;
Mechanism? mechanism;
bool? snapshot;
if (exception is ThrowableMechanism) {
throwable = exception.throwable;
mechanism = exception.mechanism;
snapshot = exception.snapshot;
}

if (throwable is Error) {
Expand All @@ -29,6 +31,8 @@ class SentryExceptionFactory {
// hence we check again if stackTrace is null and if not, read the current stack trace
// but only if attachStacktrace is enabled
if (_options.attachStacktrace) {
// TODO: snapshot=true if stackTrace is null
// Requires a major breaking change because of grouping
stackTrace ??= StackTrace.current;
}

Expand All @@ -39,6 +43,7 @@ class SentryExceptionFactory {
if (frames.isNotEmpty) {
sentryStackTrace = SentryStackTrace(
frames: frames,
snapshot: snapshot,
);
}
}
Expand Down
9 changes: 8 additions & 1 deletion dart/lib/src/throwable_mechanism.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,17 @@ import 'protocol/mechanism.dart';
class ThrowableMechanism implements Exception {
final Mechanism _mechanism;
final dynamic _throwable;
final bool? _snapshot;

ThrowableMechanism(this._mechanism, this._throwable);
ThrowableMechanism(
this._mechanism,
this._throwable, {
bool? snapshot,
}) : _snapshot = snapshot;

Mechanism get mechanism => _mechanism;

dynamic get throwable => _throwable;

bool? get snapshot => _snapshot;
}
6 changes: 4 additions & 2 deletions dart/test/http_client/failed_request_client_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ void main() {
final mechanism = exception?.mechanism;

expect(exception?.stackTrace, isNotNull);
expect(exception?.stackTrace!.snapshot, isNull);
expect(mechanism?.type, 'SentryHttpClient');

final request = eventCall.request;
Expand Down Expand Up @@ -101,14 +102,15 @@ void main() {
expect(mechanism?.type, 'SentryHttpClient');
expect(
mechanism?.description,
'Event was captured because the request status code was 404',
'HTTP Client Error with status code: 404',
);

expect(exception?.type, 'SentryHttpClientError');
expect(
exception?.value,
'Exception: Event was captured because the request status code was 404',
'Exception: HTTP Client Error with status code: 404',
);
expect(exception?.stackTrace?.snapshot, true);

final request = eventCall.request;
expect(request, isNotNull);
Expand Down
22 changes: 22 additions & 0 deletions dart/test/sentry_exception_factory_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,28 @@ void main() {

// skip on browser because [StackTrace.current] still returns null
}, onPlatform: {'browser': Skip()});

test('reads the snapshot from the mechanism', () {
final error = StateError('test-error');
final mechanism = Mechanism(type: 'Mechanism');
final throwableMechanism = ThrowableMechanism(
mechanism,
error,
snapshot: true,
);

SentryException sentryException;
try {
throw throwableMechanism;
} catch (err, stackTrace) {
sentryException = fixture.getSut().getSentryException(
throwableMechanism,
stackTrace: stackTrace,
);
}

expect(sentryException.stackTrace!.snapshot, true);
});
}

class CustomError extends Error {}
Expand Down
6 changes: 5 additions & 1 deletion dio/lib/src/failed_request_interceptor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@ class FailedRequestInterceptor extends Interceptor {
DioError err,
ErrorInterceptorHandler handler,
) async {
final mechanism = Mechanism(type: 'SentryDioClientAdapter');
final throwableMechanism = ThrowableMechanism(mechanism, err);

_hub.getSpan()?.throwable = err;
await _hub.captureException(err);

await _hub.captureException(throwableMechanism);

handler.next(err);
}
Expand Down
9 changes: 8 additions & 1 deletion dio/test/failed_request_interceptor_test.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:dio/dio.dart';
import 'package:sentry/sentry.dart';
import 'package:sentry_dio/src/failed_request_interceptor.dart';
import 'package:test/test.dart';

Expand All @@ -14,13 +15,19 @@ void main() {

test('interceptor send error', () async {
final interceptor = fixture.getSut();
final error = DioError(requestOptions: RequestOptions(path: ''));
await interceptor.onError(
DioError(requestOptions: RequestOptions(path: '')),
error,
fixture.errorInterceptorHandler,
);

expect(fixture.errorInterceptorHandler.nextWasCalled, true);
expect(fixture.hub.captureExceptionCalls.length, 1);

final throwable =
fixture.hub.captureExceptionCalls.first.throwable as ThrowableMechanism;
expect(throwable.mechanism.type, 'SentryDioClientAdapter');
expect(throwable.throwable, error);
});
}

Expand Down

0 comments on commit 3a69405

Please sign in to comment.