Skip to content

Commit 3a69405

Browse files
authored
Add mechanism to Dio Http Client error (#1114)
1 parent 0db91cc commit 3a69405

8 files changed

+65
-8
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
- Merging of integrations and packages ([#1111](https://github.com/getsentry/sentry-dart/pull/1111))
88
- Add missing `fragment` for HTTP Client Errors ([#1102](https://github.com/getsentry/sentry-dart/pull/1102))
99
- Sync user name and geo for Android ([#1102](https://github.com/getsentry/sentry-dart/pull/1102))
10+
- Add mechanism to Dio Http Client error ([#1114](https://github.com/getsentry/sentry-dart/pull/1114))
1011

1112
### Dependencies
1213

dart/lib/src/http_client/failed_request_client.dart

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,7 @@ class FailedRequestClient extends BaseClient {
126126
} else if (failedRequestStatusCodes.containsStatusCode(statusCode)) {
127127
// Capture an exception if the status code is considered bad
128128
capture = true;
129-
reason =
130-
'Event was captured because the request status code was $statusCode';
129+
reason = 'HTTP Client Error with status code: $statusCode';
131130
exception ??= SentryHttpClientError(reason);
132131
}
133132
if (capture) {
@@ -184,7 +183,17 @@ class FailedRequestClient extends BaseClient {
184183
type: 'SentryHttpClient',
185184
description: reason,
186185
);
187-
final throwableMechanism = ThrowableMechanism(mechanism, exception);
186+
187+
bool? snapshot;
188+
if (exception is SentryHttpClientError) {
189+
snapshot = true;
190+
}
191+
192+
final throwableMechanism = ThrowableMechanism(
193+
mechanism,
194+
exception,
195+
snapshot: snapshot,
196+
);
188197

189198
final event = SentryEvent(
190199
throwable: throwableMechanism,

dart/lib/src/sentry_exception_factory.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@ class SentryExceptionFactory {
1717
}) {
1818
var throwable = exception;
1919
Mechanism? mechanism;
20+
bool? snapshot;
2021
if (exception is ThrowableMechanism) {
2122
throwable = exception.throwable;
2223
mechanism = exception.mechanism;
24+
snapshot = exception.snapshot;
2325
}
2426

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

@@ -39,6 +43,7 @@ class SentryExceptionFactory {
3943
if (frames.isNotEmpty) {
4044
sentryStackTrace = SentryStackTrace(
4145
frames: frames,
46+
snapshot: snapshot,
4247
);
4348
}
4449
}

dart/lib/src/throwable_mechanism.dart

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,17 @@ import 'protocol/mechanism.dart';
44
class ThrowableMechanism implements Exception {
55
final Mechanism _mechanism;
66
final dynamic _throwable;
7+
final bool? _snapshot;
78

8-
ThrowableMechanism(this._mechanism, this._throwable);
9+
ThrowableMechanism(
10+
this._mechanism,
11+
this._throwable, {
12+
bool? snapshot,
13+
}) : _snapshot = snapshot;
914

1015
Mechanism get mechanism => _mechanism;
1116

1217
dynamic get throwable => _throwable;
18+
19+
bool? get snapshot => _snapshot;
1320
}

dart/test/http_client/failed_request_client_test.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ void main() {
4848
final mechanism = exception?.mechanism;
4949

5050
expect(exception?.stackTrace, isNotNull);
51+
expect(exception?.stackTrace!.snapshot, isNull);
5152
expect(mechanism?.type, 'SentryHttpClient');
5253

5354
final request = eventCall.request;
@@ -101,14 +102,15 @@ void main() {
101102
expect(mechanism?.type, 'SentryHttpClient');
102103
expect(
103104
mechanism?.description,
104-
'Event was captured because the request status code was 404',
105+
'HTTP Client Error with status code: 404',
105106
);
106107

107108
expect(exception?.type, 'SentryHttpClientError');
108109
expect(
109110
exception?.value,
110-
'Exception: Event was captured because the request status code was 404',
111+
'Exception: HTTP Client Error with status code: 404',
111112
);
113+
expect(exception?.stackTrace?.snapshot, true);
112114

113115
final request = eventCall.request;
114116
expect(request, isNotNull);

dart/test/sentry_exception_factory_test.dart

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,28 @@ void main() {
8383

8484
// skip on browser because [StackTrace.current] still returns null
8585
}, onPlatform: {'browser': Skip()});
86+
87+
test('reads the snapshot from the mechanism', () {
88+
final error = StateError('test-error');
89+
final mechanism = Mechanism(type: 'Mechanism');
90+
final throwableMechanism = ThrowableMechanism(
91+
mechanism,
92+
error,
93+
snapshot: true,
94+
);
95+
96+
SentryException sentryException;
97+
try {
98+
throw throwableMechanism;
99+
} catch (err, stackTrace) {
100+
sentryException = fixture.getSut().getSentryException(
101+
throwableMechanism,
102+
stackTrace: stackTrace,
103+
);
104+
}
105+
106+
expect(sentryException.stackTrace!.snapshot, true);
107+
});
86108
}
87109

88110
class CustomError extends Error {}

dio/lib/src/failed_request_interceptor.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,12 @@ class FailedRequestInterceptor extends Interceptor {
1313
DioError err,
1414
ErrorInterceptorHandler handler,
1515
) async {
16+
final mechanism = Mechanism(type: 'SentryDioClientAdapter');
17+
final throwableMechanism = ThrowableMechanism(mechanism, err);
18+
1619
_hub.getSpan()?.throwable = err;
17-
await _hub.captureException(err);
20+
21+
await _hub.captureException(throwableMechanism);
1822

1923
handler.next(err);
2024
}

dio/test/failed_request_interceptor_test.dart

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'package:dio/dio.dart';
2+
import 'package:sentry/sentry.dart';
23
import 'package:sentry_dio/src/failed_request_interceptor.dart';
34
import 'package:test/test.dart';
45

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

1516
test('interceptor send error', () async {
1617
final interceptor = fixture.getSut();
18+
final error = DioError(requestOptions: RequestOptions(path: ''));
1719
await interceptor.onError(
18-
DioError(requestOptions: RequestOptions(path: '')),
20+
error,
1921
fixture.errorInterceptorHandler,
2022
);
2123

2224
expect(fixture.errorInterceptorHandler.nextWasCalled, true);
2325
expect(fixture.hub.captureExceptionCalls.length, 1);
26+
27+
final throwable =
28+
fixture.hub.captureExceptionCalls.first.throwable as ThrowableMechanism;
29+
expect(throwable.mechanism.type, 'SentryDioClientAdapter');
30+
expect(throwable.throwable, error);
2431
});
2532
}
2633

0 commit comments

Comments
 (0)