From 3ea3dbc155b529ca4690f02b9b08c37491819957 Mon Sep 17 00:00:00 2001 From: Manoel Aranda Neto Date: Tue, 8 Nov 2022 20:16:00 +0100 Subject: [PATCH 1/3] Add mechanism to Dio Http Client error --- .../src/http_client/failed_request_client.dart | 15 ++++++++++++--- dart/lib/src/sentry_exception_factory.dart | 5 +++++ dart/lib/src/throwable_mechanism.dart | 9 ++++++++- .../http_client/failed_request_client_test.dart | 6 ++++-- dart/test/sentry_exception_factory_test.dart | 16 ++++++++++++++++ dio/lib/src/failed_request_interceptor.dart | 6 +++++- dio/test/failed_request_interceptor_test.dart | 9 ++++++++- 7 files changed, 58 insertions(+), 8 deletions(-) diff --git a/dart/lib/src/http_client/failed_request_client.dart b/dart/lib/src/http_client/failed_request_client.dart index 00e2fc0aff..079dce47cb 100644 --- a/dart/lib/src/http_client/failed_request_client.dart +++ b/dart/lib/src/http_client/failed_request_client.dart @@ -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) { @@ -178,7 +177,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, diff --git a/dart/lib/src/sentry_exception_factory.dart b/dart/lib/src/sentry_exception_factory.dart index b59ab6da18..e4a2f12561 100644 --- a/dart/lib/src/sentry_exception_factory.dart +++ b/dart/lib/src/sentry_exception_factory.dart @@ -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) { @@ -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; } @@ -39,6 +43,7 @@ class SentryExceptionFactory { if (frames.isNotEmpty) { sentryStackTrace = SentryStackTrace( frames: frames, + snapshot: snapshot, ); } } diff --git a/dart/lib/src/throwable_mechanism.dart b/dart/lib/src/throwable_mechanism.dart index 2c8fd525ff..8a3932a701 100644 --- a/dart/lib/src/throwable_mechanism.dart +++ b/dart/lib/src/throwable_mechanism.dart @@ -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; } diff --git a/dart/test/http_client/failed_request_client_test.dart b/dart/test/http_client/failed_request_client_test.dart index 7645d47c44..6c21fc5021 100644 --- a/dart/test/http_client/failed_request_client_test.dart +++ b/dart/test/http_client/failed_request_client_test.dart @@ -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; @@ -100,14 +101,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); diff --git a/dart/test/sentry_exception_factory_test.dart b/dart/test/sentry_exception_factory_test.dart index 9af95538c0..2b47263a48 100644 --- a/dart/test/sentry_exception_factory_test.dart +++ b/dart/test/sentry_exception_factory_test.dart @@ -83,6 +83,22 @@ 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 = fixture.getSut().getSentryException( + throwableMechanism, + ); + + expect(sentryException.stackTrace!.snapshot, true); + }); } class CustomError extends Error {} diff --git a/dio/lib/src/failed_request_interceptor.dart b/dio/lib/src/failed_request_interceptor.dart index d9b6af30c8..e23dc6501d 100644 --- a/dio/lib/src/failed_request_interceptor.dart +++ b/dio/lib/src/failed_request_interceptor.dart @@ -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); } diff --git a/dio/test/failed_request_interceptor_test.dart b/dio/test/failed_request_interceptor_test.dart index 26ff1e2598..0d58dfd516 100644 --- a/dio/test/failed_request_interceptor_test.dart +++ b/dio/test/failed_request_interceptor_test.dart @@ -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'; @@ -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); }); } From 055e20f2db478b3e1c1e6a50391e54c2bc5dcc94 Mon Sep 17 00:00:00 2001 From: Manoel Aranda Neto Date: Tue, 8 Nov 2022 20:33:32 +0100 Subject: [PATCH 2/3] fix js --- dart/test/sentry_exception_factory_test.dart | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/dart/test/sentry_exception_factory_test.dart b/dart/test/sentry_exception_factory_test.dart index 2b47263a48..d6ace485cf 100644 --- a/dart/test/sentry_exception_factory_test.dart +++ b/dart/test/sentry_exception_factory_test.dart @@ -93,9 +93,15 @@ void main() { snapshot: true, ); - SentryException sentryException = fixture.getSut().getSentryException( - throwableMechanism, - ); + SentryException sentryException; + try { + throw throwableMechanism; + } catch (err, stackTrace) { + sentryException = fixture.getSut().getSentryException( + throwableMechanism, + stackTrace: stackTrace, + ); + } expect(sentryException.stackTrace!.snapshot, true); }); From d7a5b03ed463dbae3997f7a163fccbd8fb102a60 Mon Sep 17 00:00:00 2001 From: Manoel Aranda Neto Date: Wed, 9 Nov 2022 08:45:26 +0100 Subject: [PATCH 3/3] fix pr id --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c944dec29d..8a9bc32dbd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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