From 23081222cfe90d03a2ba29d16006d3dc03fa566a Mon Sep 17 00:00:00 2001 From: Martin Haintz Date: Mon, 16 Sep 2024 16:59:51 +0200 Subject: [PATCH 01/25] capture response body for failed requests and if tracing is enabled. --- .../http_client/failed_request_client.dart | 15 ++++-- dart/lib/src/http_client/tracing_client.dart | 19 +++++-- .../http_deep_copy_streamed_response.dart | 28 ++++++++++ .../failed_request_client_test.dart | 19 +++++++ .../test/http_client/tracing_client_test.dart | 51 +++++++++++++++++-- 5 files changed, 120 insertions(+), 12 deletions(-) create mode 100644 dart/lib/src/utils/http_deep_copy_streamed_response.dart diff --git a/dart/lib/src/http_client/failed_request_client.dart b/dart/lib/src/http_client/failed_request_client.dart index 446b88826c..d17b68cbe0 100644 --- a/dart/lib/src/http_client/failed_request_client.dart +++ b/dart/lib/src/http_client/failed_request_client.dart @@ -1,6 +1,7 @@ import 'package:http/http.dart'; import '../hint.dart'; import '../type_check_hint.dart'; +import '../utils/http_deep_copy_streamed_response.dart'; import '../utils/tracing_utils.dart'; import 'sentry_http_client_error.dart'; import '../protocol.dart'; @@ -100,14 +101,16 @@ class FailedRequestClient extends BaseClient { Object? exception; StackTrace? stackTrace; StreamedResponse? response; + List copiedResponses = []; final stopwatch = Stopwatch(); stopwatch.start(); try { response = await _client.send(request); - statusCode = response.statusCode; - return response; + copiedResponses = await deepCopyStreamedResponse(response, 2); + statusCode = copiedResponses[0].statusCode; + return copiedResponses[0]; } catch (e, st) { exception = e; stackTrace = st; @@ -119,7 +122,7 @@ class FailedRequestClient extends BaseClient { statusCode, exception, stackTrace, - response, + copiedResponses.isNotEmpty ? copiedResponses[1] : null, stopwatch.elapsed, ); } @@ -209,10 +212,16 @@ class FailedRequestClient extends BaseClient { final hint = Hint.withMap({TypeCheckHint.httpRequest: request}); if (response != null) { + final responseBody = await response.stream.bytesToString(); event.contexts.response = SentryResponse( headers: _hub.options.sendDefaultPii ? response.headers : null, bodySize: response.contentLength, statusCode: response.statusCode, + data: _hub.options.sendDefaultPii && + _hub.options.maxResponseBodySize + .shouldAddBody(response.contentLength!) + ? responseBody + : null, ); hint.set(TypeCheckHint.httpResponse, response); } diff --git a/dart/lib/src/http_client/tracing_client.dart b/dart/lib/src/http_client/tracing_client.dart index 95627724c3..68fbe409d9 100644 --- a/dart/lib/src/http_client/tracing_client.dart +++ b/dart/lib/src/http_client/tracing_client.dart @@ -4,6 +4,7 @@ import '../hub_adapter.dart'; import '../protocol.dart'; import '../sentry_trace_origins.dart'; import '../tracing.dart'; +import '../utils/http_deep_copy_streamed_response.dart'; import '../utils/tracing_utils.dart'; import '../utils/http_sanitizer.dart'; @@ -45,6 +46,7 @@ class TracingClient extends BaseClient { urlDetails?.applyToSpan(span); StreamedResponse? response; + List copiedResponses = []; try { if (containsTargetOrMatchesRegExp( _hub.options.tracePropagationTargets, request.url.toString())) { @@ -72,9 +74,18 @@ class TracingClient extends BaseClient { } response = await _client.send(request); - span?.setData('http.response.status_code', response.statusCode); - span?.setData('http.response_content_length', response.contentLength); - span?.status = SpanStatus.fromHttpStatusCode(response.statusCode); + copiedResponses = await deepCopyStreamedResponse(response, 2); + span?.setData('http.response.status_code', copiedResponses[1].statusCode); + span?.setData( + 'http.response_content_length', copiedResponses[1].contentLength); + if (_hub.options.sendDefaultPii && + _hub.options.maxResponseBodySize + .shouldAddBody(response.contentLength!)) { + final responseBody = await copiedResponses[1].stream.bytesToString(); + span?.setData('http.response_content', responseBody); + } + span?.status = + SpanStatus.fromHttpStatusCode(copiedResponses[1].statusCode); } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); @@ -83,7 +94,7 @@ class TracingClient extends BaseClient { } finally { await span?.finish(); } - return response; + return copiedResponses[0]; } @override diff --git a/dart/lib/src/utils/http_deep_copy_streamed_response.dart b/dart/lib/src/utils/http_deep_copy_streamed_response.dart new file mode 100644 index 0000000000..95c7e6058c --- /dev/null +++ b/dart/lib/src/utils/http_deep_copy_streamed_response.dart @@ -0,0 +1,28 @@ +import 'package:http/http.dart'; +import 'package:meta/meta.dart'; + +/// Helper to deep copy the StreamedResponse of a web request +@internal +Future> deepCopyStreamedResponse( + StreamedResponse originalResponse, int copies) async { + final List bufferedData = []; + + await for (final List chunk in originalResponse.stream) { + bufferedData.addAll(chunk); + } + + List copiedElements = []; + for (int i = 1; i <= copies; i++) { + copiedElements.add(StreamedResponse( + Stream.fromIterable([bufferedData]), + originalResponse.statusCode, + contentLength: originalResponse.contentLength, + request: originalResponse.request, + headers: originalResponse.headers, + reasonPhrase: originalResponse.reasonPhrase, + isRedirect: originalResponse.isRedirect, + persistentConnection: originalResponse.persistentConnection, + )); + } + return copiedElements; +} diff --git a/dart/test/http_client/failed_request_client_test.dart b/dart/test/http_client/failed_request_client_test.dart index 2ac9a74c8e..47e90e7827 100644 --- a/dart/test/http_client/failed_request_client_test.dart +++ b/dart/test/http_client/failed_request_client_test.dart @@ -30,6 +30,25 @@ void main() { expect(fixture.transport.calls, 0); }); + test('capture event with response body on error', () async { + fixture._hub.options.sendDefaultPii = true; + fixture._hub.options.maxResponseBodySize = MaxResponseBodySize.always; + String responseBody = "this is the response body"; + int statusCode = 505; + + final sut = fixture.getSut( + client: fixture.getClient(statusCode: statusCode, body: responseBody), + ); + final response = await sut.get(requestUri); + + expect(response.statusCode, statusCode); + expect(response.body, responseBody); + expect(fixture.transport.calls, 1); + expect(fixture.transport.events.length, 1); + expect(fixture.transport.events.first.contexts["response"].data, + responseBody); + }); + test('exception gets reported if client throws', () async { fixture._hub.options.captureFailedRequests = true; fixture._hub.options.sendDefaultPii = true; diff --git a/dart/test/http_client/tracing_client_test.dart b/dart/test/http_client/tracing_client_test.dart index 6cefe626b3..b8235454d5 100644 --- a/dart/test/http_client/tracing_client_test.dart +++ b/dart/test/http_client/tracing_client_test.dart @@ -18,9 +18,44 @@ void main() { fixture = Fixture(); }); - test('captured span if successful request', () async { + test('captured span if successful request without Pii', () async { + final responseBody = "test response body"; final sut = fixture.getSut( - client: fixture.getClient(statusCode: 200, reason: 'OK'), + client: fixture.getClient( + statusCode: 200, reason: 'OK', body: responseBody), + ); + final tr = fixture._hub.startTransaction( + 'name', + 'op', + bindToScope: true, + ); + + await sut.get(requestUri); + + await tr.finish(); + + final tracer = (tr as SentryTracer); + final span = tracer.children.first; + + expect(span.status, SpanStatus.ok()); + expect(span.context.operation, 'http.client'); + expect(span.context.description, 'GET https://example.com'); + expect(span.data['http.request.method'], 'GET'); + expect(span.data['url'], 'https://example.com'); + expect(span.data['http.query'], 'foo=bar'); + expect(span.data['http.fragment'], 'baz'); + expect(span.data['http.response.status_code'], 200); + expect(span.data['http.response_content_length'], responseBody.length); + expect(span.data['http.response_content'], null); + expect(span.origin, SentryTraceOrigins.autoHttpHttp); + }); + + test('captured span if successful request with Pii', () async { + fixture._hub.options.sendDefaultPii = true; + final responseBody = "test response body"; + final sut = fixture.getSut( + client: fixture.getClient( + statusCode: 200, reason: 'OK', body: responseBody), ); final tr = fixture._hub.startTransaction( 'name', @@ -43,7 +78,8 @@ void main() { expect(span.data['http.query'], 'foo=bar'); expect(span.data['http.fragment'], 'baz'); expect(span.data['http.response.status_code'], 200); - expect(span.data['http.response_content_length'], 2); + expect(span.data['http.response_content_length'], responseBody.length); + expect(span.data['http.response_content'], responseBody); expect(span.origin, SentryTraceOrigins.autoHttpHttp); }); @@ -244,10 +280,15 @@ class Fixture { ); } - MockClient getClient({int statusCode = 200, String? reason}) { + MockClient getClient({ + int statusCode = 200, + // String body = '{}', + String body = '', + String? reason, + }) { return MockClient((request) async { expect(request.url, requestUri); - return Response('{}', statusCode, reasonPhrase: reason, request: request); + return Response(body, statusCode, reasonPhrase: reason, request: request); }); } } From da865b2d30bad53417091362335b01476f11ca96 Mon Sep 17 00:00:00 2001 From: Martin Haintz Date: Tue, 17 Sep 2024 14:09:26 +0200 Subject: [PATCH 02/25] unified event capturing for request and response --- .../http_client/failed_request_client.dart | 141 ++---------------- .../src/http_client/sentry_http_client.dart | 94 ++++++++++++ dart/lib/src/http_client/tracing_client.dart | 13 ++ dart/lib/src/sentry_options.dart | 2 + 4 files changed, 118 insertions(+), 132 deletions(-) diff --git a/dart/lib/src/http_client/failed_request_client.dart b/dart/lib/src/http_client/failed_request_client.dart index d17b68cbe0..832bd9b11e 100644 --- a/dart/lib/src/http_client/failed_request_client.dart +++ b/dart/lib/src/http_client/failed_request_client.dart @@ -117,144 +117,21 @@ class FailedRequestClient extends BaseClient { rethrow; } finally { stopwatch.stop(); - await _captureEventIfNeeded( - request, - statusCode, - exception, - stackTrace, - copiedResponses.isNotEmpty ? copiedResponses[1] : null, - stopwatch.elapsed, - ); - } - } - Future _captureEventIfNeeded( - BaseRequest request, - int? statusCode, - Object? exception, - StackTrace? stackTrace, - StreamedResponse? response, - Duration duration) async { - if (!(_captureFailedRequests ?? _hub.options.captureFailedRequests)) { - return; - } - - // Only check `failedRequestStatusCodes` & `failedRequestTargets` if no exception was thrown. - if (exception == null) { - if (!failedRequestStatusCodes._containsStatusCode(statusCode)) { - return; - } - if (!containsTargetOrMatchesRegExp( - failedRequestTargets, request.url.toString())) { - return; - } + await captureEvent( + _hub, + exception: exception, + stackTrace: stackTrace, + request: request, + requestDuration: stopwatch.elapsed, + response: copiedResponses.isNotEmpty ? copiedResponses[1] : null, + reason: 'HTTP Client Event with status code: $statusCode', + ); } - - final reason = 'HTTP Client Error with status code: $statusCode'; - exception ??= SentryHttpClientError(reason); - - await _captureEvent( - exception: exception, - stackTrace: stackTrace, - request: request, - requestDuration: duration, - response: response, - reason: reason, - ); } @override void close() => _client.close(); - - // See https://develop.sentry.dev/sdk/event-payloads/request/ - Future _captureEvent({ - required Object? exception, - StackTrace? stackTrace, - String? reason, - required Duration requestDuration, - required BaseRequest request, - required StreamedResponse? response, - }) async { - final sentryRequest = SentryRequest.fromUri( - method: request.method, - headers: _hub.options.sendDefaultPii ? request.headers : null, - uri: request.url, - data: _hub.options.sendDefaultPii ? _getDataFromRequest(request) : null, - // ignore: deprecated_member_use_from_same_package - other: { - 'content_length': request.contentLength.toString(), - 'duration': requestDuration.toString(), - }, - ); - - final mechanism = Mechanism( - type: 'SentryHttpClient', - description: reason, - ); - - bool? snapshot; - if (exception is SentryHttpClientError) { - snapshot = true; - } - - final throwableMechanism = ThrowableMechanism( - mechanism, - exception, - snapshot: snapshot, - ); - - final event = SentryEvent( - throwable: throwableMechanism, - request: sentryRequest, - timestamp: _hub.options.clock(), - ); - - final hint = Hint.withMap({TypeCheckHint.httpRequest: request}); - - if (response != null) { - final responseBody = await response.stream.bytesToString(); - event.contexts.response = SentryResponse( - headers: _hub.options.sendDefaultPii ? response.headers : null, - bodySize: response.contentLength, - statusCode: response.statusCode, - data: _hub.options.sendDefaultPii && - _hub.options.maxResponseBodySize - .shouldAddBody(response.contentLength!) - ? responseBody - : null, - ); - hint.set(TypeCheckHint.httpResponse, response); - } - - await _hub.captureEvent( - event, - stackTrace: stackTrace, - hint: hint, - ); - } - - // Types of Request can be found here: - // https://pub.dev/documentation/http/latest/http/http-library.html - Object? _getDataFromRequest(BaseRequest request) { - final contentLength = request.contentLength; - if (contentLength == null) { - return null; - } - if (!_hub.options.maxRequestBodySize.shouldAddBody(contentLength)) { - return null; - } - if (request is MultipartRequest) { - final data = {...request.fields}; - return data; - } - - if (request is Request) { - return request.body; - } - - // There's nothing we can do for a StreamedRequest - return null; - } } extension _ListX on List { diff --git a/dart/lib/src/http_client/sentry_http_client.dart b/dart/lib/src/http_client/sentry_http_client.dart index 35fcae4b4f..ff3c36c8a7 100644 --- a/dart/lib/src/http_client/sentry_http_client.dart +++ b/dart/lib/src/http_client/sentry_http_client.dart @@ -1,4 +1,6 @@ import 'package:http/http.dart'; +import 'package:meta/meta.dart'; +import '../../sentry.dart'; import 'tracing_client.dart'; import '../hub.dart'; import '../hub_adapter.dart'; @@ -160,3 +162,95 @@ class SentryStatusCode { return '$_min..$_max'; } } + +@internal +// See https://develop.sentry.dev/sdk/event-payloads/request/ +Future captureEvent( + Hub hub, { + Object? exception, + StackTrace? stackTrace, + String? reason, + required Duration requestDuration, + required BaseRequest request, + required StreamedResponse? response, +}) async { + final sentryRequest = SentryRequest.fromUri( + method: request.method, + headers: hub.options.sendDefaultPii ? request.headers : null, + uri: request.url, + data: hub.options.sendDefaultPii ? _getDataFromRequest(hub, request) : null, + // ignore: deprecated_member_use_from_same_package + other: { + 'content_length': request.contentLength.toString(), + 'duration': requestDuration.toString(), + }, + ); + + final mechanism = Mechanism( + type: 'SentryHttpClient', + description: reason, + ); + + bool? snapshot; + ThrowableMechanism? throwableMechanism; + if (exception is SentryHttpClientError) { + snapshot = true; + throwableMechanism = ThrowableMechanism( + mechanism, + exception, + snapshot: snapshot, + ); + } + + final event = SentryEvent( + throwable: throwableMechanism, + request: sentryRequest, + timestamp: hub.options.clock(), + ); + + final hint = Hint.withMap({TypeCheckHint.httpRequest: request}); + + if (response != null) { + final responseBody = await response.stream.bytesToString(); + event.contexts.response = SentryResponse( + headers: hub.options.sendDefaultPii ? response.headers : null, + bodySize: response.contentLength, + statusCode: response.statusCode, + data: hub.options.sendDefaultPii && + hub.options.maxResponseBodySize + .shouldAddBody(response.contentLength!) + ? responseBody + : null, + ); + hint.set(TypeCheckHint.httpResponse, response); + } + + await hub.captureEvent( + event, + stackTrace: stackTrace, + hint: hint, + ); +} + +// Types of Request can be found here: +// https://pub.dev/documentation/http/latest/http/http-library.html +Object? _getDataFromRequest(Hub hub, BaseRequest request) { + final contentLength = request.contentLength; + if (contentLength == null) { + return null; + } + if (!hub.options.maxRequestBodySize.shouldAddBody(contentLength)) { + return null; + } + if (request is MultipartRequest) { + final data = {...request.fields}; + return data; + } + + if (request is Request) { + return request.body; + } + + // There's nothing we can do for a StreamedRequest + return null; +} diff --git a/dart/lib/src/http_client/tracing_client.dart b/dart/lib/src/http_client/tracing_client.dart index 68fbe409d9..74161233cb 100644 --- a/dart/lib/src/http_client/tracing_client.dart +++ b/dart/lib/src/http_client/tracing_client.dart @@ -1,4 +1,5 @@ import 'package:http/http.dart'; +import '../../sentry.dart'; import '../hub.dart'; import '../hub_adapter.dart'; import '../protocol.dart'; @@ -22,6 +23,9 @@ class TracingClient extends BaseClient { @override Future send(BaseRequest request) async { // see https://develop.sentry.dev/sdk/performance/#header-sentry-trace + int? statusCode; + final stopwatch = Stopwatch(); + stopwatch.start(); final urlDetails = HttpSanitizer.sanitizeUrl(request.url.toString()); @@ -75,6 +79,7 @@ class TracingClient extends BaseClient { response = await _client.send(request); copiedResponses = await deepCopyStreamedResponse(response, 2); + statusCode = copiedResponses[0].statusCode; span?.setData('http.response.status_code', copiedResponses[1].statusCode); span?.setData( 'http.response_content_length', copiedResponses[1].contentLength); @@ -93,6 +98,14 @@ class TracingClient extends BaseClient { rethrow; } finally { await span?.finish(); + stopwatch.stop(); + await captureEvent( + _hub, + request: request, + requestDuration: stopwatch.elapsed, + response: copiedResponses.isNotEmpty ? copiedResponses[1] : null, + reason: 'HTTP Client Event with status code: $statusCode', + ); } return copiedResponses[0]; } diff --git a/dart/lib/src/sentry_options.dart b/dart/lib/src/sentry_options.dart index c9a9511c29..d73cdae120 100644 --- a/dart/lib/src/sentry_options.dart +++ b/dart/lib/src/sentry_options.dart @@ -278,6 +278,8 @@ class SentryOptions { /// because the connection was interrupted. /// Use with [SentryHttpClient] or `sentry_dio` integration for this to work, /// or iOS native where it sets the value to `enableCaptureFailedRequests`. + @Deprecated( + "All Request and Responses are now logged, if `sendDefaultPii` is `true` and `maxRequestBodySize` and `maxResponseBodySize` conditions are met.") bool captureFailedRequests = true; /// Whether to records requests as breadcrumbs. This is on by default. From 710ab1a49d87a66368142b660cc99dff288fb110 Mon Sep 17 00:00:00 2001 From: Martin Haintz Date: Tue, 5 Nov 2024 16:40:09 +0100 Subject: [PATCH 03/25] make response body accessible via hint --- .../http_client/failed_request_client.dart | 54 +- .../src/http_client/sentry_http_client.dart | 27 +- dart/lib/src/http_client/tracing_client.dart | 13 - dart/lib/src/sentry_options.dart | 2 - .../failed_request_client_test.dart | 61 ++- .../http_client/sentry_http_client_test.dart | 126 ++++- .../test/http_client/tracing_client_test.dart | 1 - dart/test/mocks.dart | 2 + dart/test/mocks.mocks.dart | 488 +++++++++++++++++- 9 files changed, 673 insertions(+), 101 deletions(-) diff --git a/dart/lib/src/http_client/failed_request_client.dart b/dart/lib/src/http_client/failed_request_client.dart index 832bd9b11e..c153112869 100644 --- a/dart/lib/src/http_client/failed_request_client.dart +++ b/dart/lib/src/http_client/failed_request_client.dart @@ -1,13 +1,9 @@ import 'package:http/http.dart'; -import '../hint.dart'; -import '../type_check_hint.dart'; import '../utils/http_deep_copy_streamed_response.dart'; import '../utils/tracing_utils.dart'; import 'sentry_http_client_error.dart'; -import '../protocol.dart'; import '../hub.dart'; import '../hub_adapter.dart'; -import '../throwable_mechanism.dart'; import 'sentry_http_client.dart'; /// A [http](https://pub.dev/packages/http)-package compatible HTTP client @@ -118,18 +114,52 @@ class FailedRequestClient extends BaseClient { } finally { stopwatch.stop(); - await captureEvent( - _hub, - exception: exception, - stackTrace: stackTrace, - request: request, - requestDuration: stopwatch.elapsed, - response: copiedResponses.isNotEmpty ? copiedResponses[1] : null, - reason: 'HTTP Client Event with status code: $statusCode', + await _captureEventIfNeeded( + request, + statusCode, + exception, + stackTrace, + copiedResponses.isNotEmpty ? copiedResponses[1] : null, + stopwatch.elapsed, ); } } + Future _captureEventIfNeeded( + BaseRequest request, + int? statusCode, + Object? exception, + StackTrace? stackTrace, + StreamedResponse? response, + Duration duration) async { + if (!(_captureFailedRequests ?? _hub.options.captureFailedRequests)) { + return; + } + + // Only check `failedRequestStatusCodes` & `failedRequestTargets` if no exception was thrown. + if (exception == null) { + if (!failedRequestStatusCodes._containsStatusCode(statusCode)) { + return; + } + if (!containsTargetOrMatchesRegExp( + failedRequestTargets, request.url.toString())) { + return; + } + } + + final reason = 'HTTP Client Error with status code: $statusCode'; + + await captureEvent( + _hub, + exception: exception ?? SentryHttpClientError(reason), + stackTrace: stackTrace, + request: request, + requestDuration: duration, + response: response, + reason: reason, + ); + } + @override void close() => _client.close(); } diff --git a/dart/lib/src/http_client/sentry_http_client.dart b/dart/lib/src/http_client/sentry_http_client.dart index ff3c36c8a7..c42777ed22 100644 --- a/dart/lib/src/http_client/sentry_http_client.dart +++ b/dart/lib/src/http_client/sentry_http_client.dart @@ -2,8 +2,6 @@ import 'package:http/http.dart'; import 'package:meta/meta.dart'; import '../../sentry.dart'; import 'tracing_client.dart'; -import '../hub.dart'; -import '../hub_adapter.dart'; import 'breadcrumb_client.dart'; import 'failed_request_client.dart'; @@ -192,16 +190,16 @@ Future captureEvent( ); bool? snapshot; - ThrowableMechanism? throwableMechanism; if (exception is SentryHttpClientError) { snapshot = true; - throwableMechanism = ThrowableMechanism( - mechanism, - exception, - snapshot: snapshot, - ); } + final throwableMechanism = ThrowableMechanism( + mechanism, + exception, + snapshot: snapshot, + ); + final event = SentryEvent( throwable: throwableMechanism, request: sentryRequest, @@ -211,17 +209,10 @@ Future captureEvent( final hint = Hint.withMap({TypeCheckHint.httpRequest: request}); if (response != null) { - final responseBody = await response.stream.bytesToString(); event.contexts.response = SentryResponse( - headers: hub.options.sendDefaultPii ? response.headers : null, - bodySize: response.contentLength, - statusCode: response.statusCode, - data: hub.options.sendDefaultPii && - hub.options.maxResponseBodySize - .shouldAddBody(response.contentLength!) - ? responseBody - : null, - ); + headers: hub.options.sendDefaultPii ? response.headers : null, + bodySize: response.contentLength, + statusCode: response.statusCode); hint.set(TypeCheckHint.httpResponse, response); } diff --git a/dart/lib/src/http_client/tracing_client.dart b/dart/lib/src/http_client/tracing_client.dart index 74161233cb..4ca1fb9c7e 100644 --- a/dart/lib/src/http_client/tracing_client.dart +++ b/dart/lib/src/http_client/tracing_client.dart @@ -1,13 +1,6 @@ import 'package:http/http.dart'; import '../../sentry.dart'; -import '../hub.dart'; -import '../hub_adapter.dart'; -import '../protocol.dart'; -import '../sentry_trace_origins.dart'; -import '../tracing.dart'; import '../utils/http_deep_copy_streamed_response.dart'; -import '../utils/tracing_utils.dart'; -import '../utils/http_sanitizer.dart'; /// A [http](https://pub.dev/packages/http)-package compatible HTTP client /// which adds support to Sentry Performance feature. @@ -83,12 +76,6 @@ class TracingClient extends BaseClient { span?.setData('http.response.status_code', copiedResponses[1].statusCode); span?.setData( 'http.response_content_length', copiedResponses[1].contentLength); - if (_hub.options.sendDefaultPii && - _hub.options.maxResponseBodySize - .shouldAddBody(response.contentLength!)) { - final responseBody = await copiedResponses[1].stream.bytesToString(); - span?.setData('http.response_content', responseBody); - } span?.status = SpanStatus.fromHttpStatusCode(copiedResponses[1].statusCode); } catch (exception) { diff --git a/dart/lib/src/sentry_options.dart b/dart/lib/src/sentry_options.dart index 349f7c4e91..1e4d84e868 100644 --- a/dart/lib/src/sentry_options.dart +++ b/dart/lib/src/sentry_options.dart @@ -307,8 +307,6 @@ class SentryOptions { /// because the connection was interrupted. /// Use with [SentryHttpClient] or `sentry_dio` integration for this to work, /// or iOS native where it sets the value to `enableCaptureFailedRequests`. - @Deprecated( - "All Request and Responses are now logged, if `sendDefaultPii` is `true` and `maxRequestBodySize` and `maxResponseBodySize` conditions are met.") bool captureFailedRequests = true; /// Whether to records requests as breadcrumbs. This is on by default. diff --git a/dart/test/http_client/failed_request_client_test.dart b/dart/test/http_client/failed_request_client_test.dart index b90005a4a8..daf797aef2 100644 --- a/dart/test/http_client/failed_request_client_test.dart +++ b/dart/test/http_client/failed_request_client_test.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:http/http.dart'; import 'package:http/testing.dart'; import 'package:mockito/mockito.dart'; @@ -6,18 +8,22 @@ import 'package:sentry/src/http_client/failed_request_client.dart'; import 'package:test/test.dart'; import '../mocks.dart'; -import '../mocks/mock_hub.dart'; import '../mocks/mock_transport.dart'; import '../test_utils.dart'; +import '../mocks.mocks.dart'; +import '../mocks/mock_hub.dart' as fake; + final requestUri = Uri.parse('https://example.com?foo=bar#myFragment'); void main() { group(FailedRequestClient, () { late Fixture fixture; + late MockHub mockHub; setUp(() { - fixture = Fixture(); + mockHub = MockHub(); + fixture = Fixture(null); }); test('no captured events when everything goes well', () async { @@ -31,23 +37,41 @@ void main() { expect(fixture.transport.calls, 0); }); - test('capture event with response body on error', () async { - fixture._hub.options.sendDefaultPii = true; - fixture._hub.options.maxResponseBodySize = MaxResponseBodySize.always; + test('capture response body as hint on error', () async { + fake.MockHub fakeHub = fake.MockHub(); + fixture = Fixture(mockHub); + SentryOptions options = SentryOptions(dsn: "fake.dsn") + ..maxResponseBodySize = MaxResponseBodySize.medium; String responseBody = "this is the response body"; int statusCode = 505; + when(mockHub.options).thenReturn(options); + when(mockHub.getSpan()).thenReturn(null); + when(mockHub.scope).thenReturn(fakeHub.scope); + when( + mockHub.captureEvent( + any, + stackTrace: anyNamed('stackTrace'), + hint: anyNamed('hint'), + ), + ).thenAnswer((invocation) async { + final hint = invocation.namedArguments[const Symbol('hint')] as Hint?; + final response = + hint?.get(TypeCheckHint.httpResponse) as StreamedResponse; + final responseBody = await response.stream.bytesToString(); + + expect(responseBody, responseBody); + + return SentryId.newId(); + }); + final sut = fixture.getSut( client: fixture.getClient(statusCode: statusCode, body: responseBody), ); final response = await sut.get(requestUri); + final actualResponseBody = utf8.decode(response.bodyBytes); - expect(response.statusCode, statusCode); - expect(response.body, responseBody); - expect(fixture.transport.calls, 1); - expect(fixture.transport.events.length, 1); - expect(fixture.transport.events.first.contexts["response"].data, - responseBody); + expect(actualResponseBody, responseBody); }); test('exception gets reported if client throws', () async { @@ -220,15 +244,14 @@ void main() { }); test('close does get called for user defined client', () async { - final mockHub = MockHub(); - + final fakeHub = fake.MockHub(); final mockClient = CloseableMockClient(); - final client = FailedRequestClient(client: mockClient, hub: mockHub); + final client = FailedRequestClient(client: mockClient, hub: fakeHub); client.close(); - expect(mockHub.addBreadcrumbCalls.length, 0); - expect(mockHub.captureExceptionCalls.length, 0); + expect(fakeHub.addBreadcrumbCalls.length, 0); + expect(fakeHub.captureExceptionCalls.length, 0); verify(mockClient.close()); }); @@ -380,11 +403,11 @@ class CloseableMockClient extends Mock implements BaseClient {} class Fixture { final options = defaultTestOptions(); - late Hub _hub; final transport = MockTransport(); - Fixture() { + late Hub _hub; + Fixture(Hub? hub) { options.transport = transport; - _hub = Hub(options); + _hub = hub ?? Hub(options); } FailedRequestClient getSut({ diff --git a/dart/test/http_client/sentry_http_client_test.dart b/dart/test/http_client/sentry_http_client_test.dart index be9d8d7bd1..5a5cb698fd 100644 --- a/dart/test/http_client/sentry_http_client_test.dart +++ b/dart/test/http_client/sentry_http_client_test.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:http/http.dart'; import 'package:http/testing.dart'; import 'package:mockito/mockito.dart'; @@ -5,15 +7,20 @@ import 'package:sentry/sentry.dart'; import 'package:sentry/src/http_client/failed_request_client.dart'; import 'package:test/test.dart'; -import '../mocks/mock_hub.dart'; +import '../mocks.mocks.dart'; +import '../mocks/mock_hub.dart' as fake; final requestUri = Uri.parse('https://example.com'); void main() { group(SentryHttpClient, () { late Fixture fixture; + late fake.MockHub fakeHub; + late MockHub mockHub; setUp(() { + fakeHub = fake.MockHub(); + mockHub = MockHub(); fixture = Fixture(); }); @@ -22,109 +29,174 @@ void main() { () async { final sut = fixture.getSut( client: fixture.getClient(statusCode: 200, reason: 'OK'), + hub: fakeHub, ); final response = await sut.get(requestUri); expect(response.statusCode, 200); - expect(fixture.hub.captureEventCalls.length, 0); - expect(fixture.hub.addBreadcrumbCalls.length, 1); + expect(fakeHub.captureEventCalls.length, 0); + expect(fakeHub.addBreadcrumbCalls.length, 1); }); test('no captured event with default config', () async { - fixture.hub.options.captureFailedRequests = false; + fakeHub.options.captureFailedRequests = false; final sut = fixture.getSut( client: createThrowingClient(), + hub: fakeHub, ); await expectLater(() async => await sut.get(requestUri), throwsException); - expect(fixture.hub.captureEventCalls.length, 0); - expect(fixture.hub.addBreadcrumbCalls.length, 1); + expect(fakeHub.captureEventCalls.length, 0); + expect(fakeHub.addBreadcrumbCalls.length, 1); }); test('captured event with override', () async { - fixture.hub.options.captureFailedRequests = false; + fakeHub.options.captureFailedRequests = false; final sut = fixture.getSut( client: createThrowingClient(), captureFailedRequests: true, + hub: fakeHub, ); await expectLater(() async => await sut.get(requestUri), throwsException); - expect(fixture.hub.captureEventCalls.length, 1); + expect(fakeHub.captureEventCalls.length, 1); }); test('one captured event with when enabling $FailedRequestClient', () async { - fixture.hub.options.captureFailedRequests = true; - fixture.hub.options.recordHttpBreadcrumbs = true; + fakeHub.options.captureFailedRequests = true; + fakeHub.options.recordHttpBreadcrumbs = true; final sut = fixture.getSut( client: createThrowingClient(), + hub: fakeHub, ); await expectLater(() async => await sut.get(requestUri), throwsException); - expect(fixture.hub.captureEventCalls.length, 1); + expect(fakeHub.captureEventCalls.length, 1); // The event should not have breadcrumbs from the BreadcrumbClient - expect(fixture.hub.captureEventCalls.first.event.breadcrumbs, null); + expect(fakeHub.captureEventCalls.first.event.breadcrumbs, null); // The breadcrumb for the request should still be added for every // following event. - expect(fixture.hub.addBreadcrumbCalls.length, 1); + expect(fakeHub.addBreadcrumbCalls.length, 1); }); test( 'no captured event with when enabling $FailedRequestClient with override', () async { - fixture.hub.options.captureFailedRequests = true; + fakeHub.options.captureFailedRequests = true; final sut = fixture.getSut( client: createThrowingClient(), captureFailedRequests: false, + hub: fakeHub, ); await expectLater(() async => await sut.get(requestUri), throwsException); - expect(fixture.hub.captureEventCalls.length, 0); + expect(fakeHub.captureEventCalls.length, 0); }); test('close does get called for user defined client', () async { - final mockHub = MockHub(); + final mockHub = fake.MockHub(); final mockClient = CloseableMockClient(); final client = SentryHttpClient(client: mockClient, hub: mockHub); client.close(); - expect(mockHub.addBreadcrumbCalls.length, 0); - expect(mockHub.captureExceptionCalls.length, 0); + expect(fakeHub.addBreadcrumbCalls.length, 0); + expect(fakeHub.captureExceptionCalls.length, 0); verify(mockClient.close()); }); test('no captured span if tracing disabled', () async { - fixture.hub.options.recordHttpBreadcrumbs = false; + fakeHub.options.recordHttpBreadcrumbs = false; final sut = fixture.getSut( client: fixture.getClient(statusCode: 200, reason: 'OK'), + hub: fakeHub, ); final response = await sut.get(requestUri); expect(response.statusCode, 200); - expect(fixture.hub.getSpanCalls, 0); + expect(fakeHub.getSpanCalls, 0); }); test('captured span if tracing enabled', () async { - fixture.hub.options.tracesSampleRate = 1.0; - fixture.hub.options.recordHttpBreadcrumbs = false; + fakeHub.options.tracesSampleRate = 1.0; + fakeHub.options.recordHttpBreadcrumbs = false; + final sut = fixture.getSut( + client: fixture.getClient(statusCode: 200, reason: 'OK'), + hub: fakeHub); + + final response = await sut.get(requestUri); + expect(response.statusCode, 200); + + expect(fakeHub.getSpanCalls, 1); + }); + + test('do not capture response body as hint if tracing disabled', () async { + SentryOptions options = SentryOptions(dsn: "fake.dsn") + ..recordHttpBreadcrumbs = false; + when(mockHub.options).thenReturn(options); + when(mockHub.getSpan()).thenReturn(null); + when(mockHub.scope).thenReturn(fakeHub.scope); + final sut = fixture.getSut( client: fixture.getClient(statusCode: 200, reason: 'OK'), + hub: mockHub, ); final response = await sut.get(requestUri); - expect(response.statusCode, 200); + final responseBody = utf8.decode(response.bodyBytes); + + expect(responseBody, fixture.responseBody); + + verifyNever(mockHub.captureEvent( + any, + stackTrace: anyNamed('stackTrace'), + hint: anyNamed('hint'), + )); + }); + + test('capture response body as hint if tracing enabled', () async { + SentryOptions options = SentryOptions(dsn: "fake.dsn") + ..tracesSampleRate = 1.0 + ..recordHttpBreadcrumbs = false; + when(mockHub.options).thenReturn(options); + when(mockHub.getSpan()).thenReturn(null); + when(mockHub.scope).thenReturn(fakeHub.scope); + when( + mockHub.captureEvent( + any, + stackTrace: anyNamed('stackTrace'), + hint: anyNamed('hint'), + ), + ).thenAnswer((invocation) async { + final hint = invocation.namedArguments[const Symbol('hint')] as Hint?; + final response = + hint?.get(TypeCheckHint.httpResponse) as StreamedResponse; + final responseBody = await response.stream.bytesToString(); + + expect(responseBody, fixture.responseBody); + + return SentryId.newId(); + }); + + final sut = fixture.getSut( + client: fixture.getClient(statusCode: 200, reason: 'OK'), + hub: mockHub, + ); + + final response = await sut.get(requestUri); + final responseBody = utf8.decode(response.bodyBytes); - expect(fixture.hub.getSpanCalls, 1); + expect(responseBody, fixture.responseBody); }); }); } @@ -145,6 +217,7 @@ class Fixture { MockClient? client, List badStatusCodes = const [], bool? captureFailedRequests, + required Hub hub, }) { final mc = client ?? getClient(); return SentryHttpClient( @@ -155,12 +228,13 @@ class Fixture { ); } - final MockHub hub = MockHub(); + // final MockHub hub = MockHub(); + final String responseBody = "this is the content of the response_body"; MockClient getClient({int statusCode = 200, String? reason}) { return MockClient((request) async { expect(request.url, requestUri); - return Response('', statusCode, reasonPhrase: reason); + return Response(responseBody, statusCode, reasonPhrase: reason); }); } } diff --git a/dart/test/http_client/tracing_client_test.dart b/dart/test/http_client/tracing_client_test.dart index 35bed6b101..195ebf91fa 100644 --- a/dart/test/http_client/tracing_client_test.dart +++ b/dart/test/http_client/tracing_client_test.dart @@ -79,7 +79,6 @@ void main() { expect(span.data['http.fragment'], 'baz'); expect(span.data['http.response.status_code'], 200); expect(span.data['http.response_content_length'], responseBody.length); - expect(span.data['http.response_content'], responseBody); expect(span.origin, SentryTraceOrigins.autoHttpHttp); }); diff --git a/dart/test/mocks.dart b/dart/test/mocks.dart index 679b9f73cd..5cbcb31721 100644 --- a/dart/test/mocks.dart +++ b/dart/test/mocks.dart @@ -1,5 +1,6 @@ import 'package:mockito/annotations.dart'; import 'package:sentry/sentry.dart'; +import 'package:sentry/sentry_io.dart'; import 'package:sentry/src/metrics/metric.dart'; import 'package:sentry/src/profiling.dart'; import 'package:sentry/src/transport/rate_limiter.dart'; @@ -214,5 +215,6 @@ final Map testUnknown = { SentryProfiler, SentryProfileInfo, ExceptionTypeIdentifier, + Hub, ]) void main() {} diff --git a/dart/test/mocks.mocks.dart b/dart/test/mocks.mocks.dart index 58133b794b..888d076890 100644 --- a/dart/test/mocks.mocks.dart +++ b/dart/test/mocks.mocks.dart @@ -3,11 +3,13 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i4; +import 'dart:async' as _i5; import 'package:mockito/mockito.dart' as _i1; import 'package:sentry/sentry.dart' as _i2; -import 'package:sentry/src/profiling.dart' as _i3; +import 'package:sentry/src/metrics/metric.dart' as _i6; +import 'package:sentry/src/metrics/metrics_api.dart' as _i3; +import 'package:sentry/src/profiling.dart' as _i4; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -33,41 +35,101 @@ class _FakeSentryEnvelopeItem_0 extends _i1.SmartFake ); } +class _FakeSentryOptions_1 extends _i1.SmartFake implements _i2.SentryOptions { + _FakeSentryOptions_1( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeMetricsApi_2 extends _i1.SmartFake implements _i3.MetricsApi { + _FakeMetricsApi_2( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeSentryId_3 extends _i1.SmartFake implements _i2.SentryId { + _FakeSentryId_3( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeScope_4 extends _i1.SmartFake implements _i2.Scope { + _FakeScope_4( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeHub_5 extends _i1.SmartFake implements _i2.Hub { + _FakeHub_5( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeISentrySpan_6 extends _i1.SmartFake implements _i2.ISentrySpan { + _FakeISentrySpan_6( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + /// A class which mocks [SentryProfilerFactory]. /// /// See the documentation for Mockito's code generation for more information. class MockSentryProfilerFactory extends _i1.Mock - implements _i3.SentryProfilerFactory { + implements _i4.SentryProfilerFactory { MockSentryProfilerFactory() { _i1.throwOnMissingStub(this); } @override - _i3.SentryProfiler? startProfiler(_i2.SentryTransactionContext? context) => + _i4.SentryProfiler? startProfiler(_i2.SentryTransactionContext? context) => (super.noSuchMethod(Invocation.method( #startProfiler, [context], - )) as _i3.SentryProfiler?); + )) as _i4.SentryProfiler?); } /// A class which mocks [SentryProfiler]. /// /// See the documentation for Mockito's code generation for more information. -class MockSentryProfiler extends _i1.Mock implements _i3.SentryProfiler { +class MockSentryProfiler extends _i1.Mock implements _i4.SentryProfiler { MockSentryProfiler() { _i1.throwOnMissingStub(this); } @override - _i4.Future<_i3.SentryProfileInfo?> finishFor( + _i5.Future<_i4.SentryProfileInfo?> finishFor( _i2.SentryTransaction? transaction) => (super.noSuchMethod( Invocation.method( #finishFor, [transaction], ), - returnValue: _i4.Future<_i3.SentryProfileInfo?>.value(), - ) as _i4.Future<_i3.SentryProfileInfo?>); + returnValue: _i5.Future<_i4.SentryProfileInfo?>.value(), + ) as _i5.Future<_i4.SentryProfileInfo?>); @override void dispose() => super.noSuchMethod( @@ -82,7 +144,7 @@ class MockSentryProfiler extends _i1.Mock implements _i3.SentryProfiler { /// A class which mocks [SentryProfileInfo]. /// /// See the documentation for Mockito's code generation for more information. -class MockSentryProfileInfo extends _i1.Mock implements _i3.SentryProfileInfo { +class MockSentryProfileInfo extends _i1.Mock implements _i4.SentryProfileInfo { MockSentryProfileInfo() { _i1.throwOnMissingStub(this); } @@ -112,3 +174,409 @@ class MockExceptionTypeIdentifier extends _i1.Mock _i1.throwOnMissingStub(this); } } + +/// A class which mocks [Hub]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockHub extends _i1.Mock implements _i2.Hub { + MockHub() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.SentryOptions get options => (super.noSuchMethod( + Invocation.getter(#options), + returnValue: _FakeSentryOptions_1( + this, + Invocation.getter(#options), + ), + ) as _i2.SentryOptions); + + @override + _i3.MetricsApi get metricsApi => (super.noSuchMethod( + Invocation.getter(#metricsApi), + returnValue: _FakeMetricsApi_2( + this, + Invocation.getter(#metricsApi), + ), + ) as _i3.MetricsApi); + + @override + bool get isEnabled => (super.noSuchMethod( + Invocation.getter(#isEnabled), + returnValue: false, + ) as bool); + + @override + _i2.SentryId get lastEventId => (super.noSuchMethod( + Invocation.getter(#lastEventId), + returnValue: _FakeSentryId_3( + this, + Invocation.getter(#lastEventId), + ), + ) as _i2.SentryId); + + @override + _i2.Scope get scope => (super.noSuchMethod( + Invocation.getter(#scope), + returnValue: _FakeScope_4( + this, + Invocation.getter(#scope), + ), + ) as _i2.Scope); + + @override + set profilerFactory(_i4.SentryProfilerFactory? value) => super.noSuchMethod( + Invocation.setter( + #profilerFactory, + value, + ), + returnValueForMissingStub: null, + ); + + @override + _i5.Future<_i2.SentryId> captureEvent( + _i2.SentryEvent? event, { + dynamic stackTrace, + _i2.Hint? hint, + _i2.ScopeCallback? withScope, + }) => + (super.noSuchMethod( + Invocation.method( + #captureEvent, + [event], + { + #stackTrace: stackTrace, + #hint: hint, + #withScope: withScope, + }, + ), + returnValue: _i5.Future<_i2.SentryId>.value(_FakeSentryId_3( + this, + Invocation.method( + #captureEvent, + [event], + { + #stackTrace: stackTrace, + #hint: hint, + #withScope: withScope, + }, + ), + )), + ) as _i5.Future<_i2.SentryId>); + + @override + _i5.Future<_i2.SentryId> captureException( + dynamic throwable, { + dynamic stackTrace, + _i2.Hint? hint, + _i2.ScopeCallback? withScope, + }) => + (super.noSuchMethod( + Invocation.method( + #captureException, + [throwable], + { + #stackTrace: stackTrace, + #hint: hint, + #withScope: withScope, + }, + ), + returnValue: _i5.Future<_i2.SentryId>.value(_FakeSentryId_3( + this, + Invocation.method( + #captureException, + [throwable], + { + #stackTrace: stackTrace, + #hint: hint, + #withScope: withScope, + }, + ), + )), + ) as _i5.Future<_i2.SentryId>); + + @override + _i5.Future<_i2.SentryId> captureMessage( + String? message, { + _i2.SentryLevel? level, + String? template, + List? params, + _i2.Hint? hint, + _i2.ScopeCallback? withScope, + }) => + (super.noSuchMethod( + Invocation.method( + #captureMessage, + [message], + { + #level: level, + #template: template, + #params: params, + #hint: hint, + #withScope: withScope, + }, + ), + returnValue: _i5.Future<_i2.SentryId>.value(_FakeSentryId_3( + this, + Invocation.method( + #captureMessage, + [message], + { + #level: level, + #template: template, + #params: params, + #hint: hint, + #withScope: withScope, + }, + ), + )), + ) as _i5.Future<_i2.SentryId>); + + @override + _i5.Future captureUserFeedback(_i2.SentryUserFeedback? userFeedback) => + (super.noSuchMethod( + Invocation.method( + #captureUserFeedback, + [userFeedback], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future<_i2.SentryId> captureFeedback( + _i2.SentryFeedback? feedback, { + _i2.Hint? hint, + _i2.ScopeCallback? withScope, + }) => + (super.noSuchMethod( + Invocation.method( + #captureFeedback, + [feedback], + { + #hint: hint, + #withScope: withScope, + }, + ), + returnValue: _i5.Future<_i2.SentryId>.value(_FakeSentryId_3( + this, + Invocation.method( + #captureFeedback, + [feedback], + { + #hint: hint, + #withScope: withScope, + }, + ), + )), + ) as _i5.Future<_i2.SentryId>); + + @override + _i5.Future addBreadcrumb( + _i2.Breadcrumb? crumb, { + _i2.Hint? hint, + }) => + (super.noSuchMethod( + Invocation.method( + #addBreadcrumb, + [crumb], + {#hint: hint}, + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + void bindClient(_i2.SentryClient? client) => super.noSuchMethod( + Invocation.method( + #bindClient, + [client], + ), + returnValueForMissingStub: null, + ); + + @override + _i2.Hub clone() => (super.noSuchMethod( + Invocation.method( + #clone, + [], + ), + returnValue: _FakeHub_5( + this, + Invocation.method( + #clone, + [], + ), + ), + ) as _i2.Hub); + + @override + _i5.Future close() => (super.noSuchMethod( + Invocation.method( + #close, + [], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.FutureOr configureScope(_i2.ScopeCallback? callback) => + (super.noSuchMethod(Invocation.method( + #configureScope, + [callback], + )) as _i5.FutureOr); + + @override + _i2.ISentrySpan startTransaction( + String? name, + String? operation, { + String? description, + DateTime? startTimestamp, + bool? bindToScope, + bool? waitForChildren, + Duration? autoFinishAfter, + bool? trimEnd, + _i2.OnTransactionFinish? onFinish, + Map? customSamplingContext, + }) => + (super.noSuchMethod( + Invocation.method( + #startTransaction, + [ + name, + operation, + ], + { + #description: description, + #startTimestamp: startTimestamp, + #bindToScope: bindToScope, + #waitForChildren: waitForChildren, + #autoFinishAfter: autoFinishAfter, + #trimEnd: trimEnd, + #onFinish: onFinish, + #customSamplingContext: customSamplingContext, + }, + ), + returnValue: _FakeISentrySpan_6( + this, + Invocation.method( + #startTransaction, + [ + name, + operation, + ], + { + #description: description, + #startTimestamp: startTimestamp, + #bindToScope: bindToScope, + #waitForChildren: waitForChildren, + #autoFinishAfter: autoFinishAfter, + #trimEnd: trimEnd, + #onFinish: onFinish, + #customSamplingContext: customSamplingContext, + }, + ), + ), + ) as _i2.ISentrySpan); + + @override + _i2.ISentrySpan startTransactionWithContext( + _i2.SentryTransactionContext? transactionContext, { + Map? customSamplingContext, + DateTime? startTimestamp, + bool? bindToScope, + bool? waitForChildren, + Duration? autoFinishAfter, + bool? trimEnd, + _i2.OnTransactionFinish? onFinish, + }) => + (super.noSuchMethod( + Invocation.method( + #startTransactionWithContext, + [transactionContext], + { + #customSamplingContext: customSamplingContext, + #startTimestamp: startTimestamp, + #bindToScope: bindToScope, + #waitForChildren: waitForChildren, + #autoFinishAfter: autoFinishAfter, + #trimEnd: trimEnd, + #onFinish: onFinish, + }, + ), + returnValue: _FakeISentrySpan_6( + this, + Invocation.method( + #startTransactionWithContext, + [transactionContext], + { + #customSamplingContext: customSamplingContext, + #startTimestamp: startTimestamp, + #bindToScope: bindToScope, + #waitForChildren: waitForChildren, + #autoFinishAfter: autoFinishAfter, + #trimEnd: trimEnd, + #onFinish: onFinish, + }, + ), + ), + ) as _i2.ISentrySpan); + + @override + _i5.Future<_i2.SentryId> captureTransaction( + _i2.SentryTransaction? transaction, { + _i2.SentryTraceContextHeader? traceContext, + }) => + (super.noSuchMethod( + Invocation.method( + #captureTransaction, + [transaction], + {#traceContext: traceContext}, + ), + returnValue: _i5.Future<_i2.SentryId>.value(_FakeSentryId_3( + this, + Invocation.method( + #captureTransaction, + [transaction], + {#traceContext: traceContext}, + ), + )), + ) as _i5.Future<_i2.SentryId>); + + @override + _i5.Future<_i2.SentryId> captureMetrics( + Map>? metricsBuckets) => + (super.noSuchMethod( + Invocation.method( + #captureMetrics, + [metricsBuckets], + ), + returnValue: _i5.Future<_i2.SentryId>.value(_FakeSentryId_3( + this, + Invocation.method( + #captureMetrics, + [metricsBuckets], + ), + )), + ) as _i5.Future<_i2.SentryId>); + + @override + void setSpanContext( + dynamic throwable, + _i2.ISentrySpan? span, + String? transaction, + ) => + super.noSuchMethod( + Invocation.method( + #setSpanContext, + [ + throwable, + span, + transaction, + ], + ), + returnValueForMissingStub: null, + ); +} From f9abe1663282f462134ad27da2449f9fdbb788de Mon Sep 17 00:00:00 2001 From: Martin Haintz Date: Tue, 5 Nov 2024 16:47:52 +0100 Subject: [PATCH 04/25] fix warning --- dart/lib/sentry.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/dart/lib/sentry.dart b/dart/lib/sentry.dart index ecb44288f1..0d0033cf0b 100644 --- a/dart/lib/sentry.dart +++ b/dart/lib/sentry.dart @@ -25,6 +25,7 @@ export 'src/throwable_mechanism.dart'; export 'src/transport/transport.dart'; export 'src/integration.dart'; export 'src/event_processor.dart'; +// ignore: invalid_export_of_internal_element export 'src/http_client/sentry_http_client.dart'; export 'src/http_client/sentry_http_client_error.dart'; export 'src/sentry_attachment/sentry_attachment.dart'; From a309f1612c09ea766403cec8a41f81d7924f24ac Mon Sep 17 00:00:00 2001 From: Martin Haintz Date: Tue, 5 Nov 2024 17:27:49 +0100 Subject: [PATCH 05/25] add changelog entry --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9260793a20..1de40f1fbe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,18 @@ ### Enhancements +- Make response body accessible via hint in `beforSend` callback for failed web requests or if tracing is enabled in `SentryHttpClient` ([#2293](https://github.com/getsentry/sentry-dart/pull/2293)) + ```dart + options.beforeSend = (event, hint) async { + final response = hint.get(TypeCheckHint.httpResponse); + if (response is StreamedResponse) { + final body = await response.stream.bytesToString(); + // user can now use it + } + return event; + }; + ``` + - Cache parsed DSN ([#2365](https://github.com/getsentry/sentry-dart/pull/2365)) - Handle backpressure earlier in pipeline ([#2371](https://github.com/getsentry/sentry-dart/pull/2371)) - Drops max un-awaited parallel tasks earlier, so event processors & callbacks are not executed for them. From 41904673f5a703f34bbc6a4d44489e27dfc2f42b Mon Sep 17 00:00:00 2001 From: Martin Haintz Date: Mon, 18 Nov 2024 19:15:47 +0100 Subject: [PATCH 06/25] add response body as hint for beforeTransactionSend --- .../http_client/failed_request_client.dart | 6 +- dart/lib/src/http_client/tracing_client.dart | 34 ++++----- dart/lib/src/hub.dart | 8 +- dart/lib/src/hub_adapter.dart | 2 + dart/lib/src/noop_hub.dart | 1 + dart/lib/src/noop_sentry_client.dart | 1 + dart/lib/src/noop_sentry_span.dart | 7 +- dart/lib/src/protocol/sentry_span.dart | 11 ++- dart/lib/src/sentry_client.dart | 11 ++- dart/lib/src/sentry_options.dart | 1 + dart/lib/src/sentry_span_interface.dart | 8 +- dart/lib/src/sentry_tracer.dart | 27 ++++--- .../src/utils/streamed_response_copier.dart | 58 +++++++++++++++ .../test/http_client/tracing_client_test.dart | 73 +++++++++++++++++++ dart/test/mocks.mocks.dart | 11 ++- dart/test/mocks/mock_hub.dart | 6 +- dart/test/mocks/mock_sentry_client.dart | 1 + dart/test/sentry_client_test.dart | 22 ++++-- dart/test/sentry_span_test.dart | 4 +- 19 files changed, 236 insertions(+), 56 deletions(-) create mode 100644 dart/lib/src/utils/streamed_response_copier.dart diff --git a/dart/lib/src/http_client/failed_request_client.dart b/dart/lib/src/http_client/failed_request_client.dart index c153112869..74fcb24569 100644 --- a/dart/lib/src/http_client/failed_request_client.dart +++ b/dart/lib/src/http_client/failed_request_client.dart @@ -96,15 +96,15 @@ class FailedRequestClient extends BaseClient { int? statusCode; Object? exception; StackTrace? stackTrace; - StreamedResponse? response; + StreamedResponse? streamedResponse; List copiedResponses = []; final stopwatch = Stopwatch(); stopwatch.start(); try { - response = await _client.send(request); - copiedResponses = await deepCopyStreamedResponse(response, 2); + streamedResponse = await _client.send(request); + copiedResponses = await deepCopyStreamedResponse(streamedResponse, 2); statusCode = copiedResponses[0].statusCode; return copiedResponses[0]; } catch (e, st) { diff --git a/dart/lib/src/http_client/tracing_client.dart b/dart/lib/src/http_client/tracing_client.dart index 4ca1fb9c7e..5dea250d74 100644 --- a/dart/lib/src/http_client/tracing_client.dart +++ b/dart/lib/src/http_client/tracing_client.dart @@ -1,6 +1,7 @@ import 'package:http/http.dart'; import '../../sentry.dart'; import '../utils/http_deep_copy_streamed_response.dart'; +import '../utils/streamed_response_copier.dart'; /// A [http](https://pub.dev/packages/http)-package compatible HTTP client /// which adds support to Sentry Performance feature. @@ -42,8 +43,9 @@ class TracingClient extends BaseClient { span?.setData('http.request.method', request.method); urlDetails?.applyToSpan(span); - StreamedResponse? response; - List copiedResponses = []; + StreamedResponse? originalResponse; + final hint = Hint(); + // List copiedResponses = []; try { if (containsTargetOrMatchesRegExp( _hub.options.tracePropagationTargets, request.url.toString())) { @@ -70,31 +72,27 @@ class TracingClient extends BaseClient { } } - response = await _client.send(request); - copiedResponses = await deepCopyStreamedResponse(response, 2); - statusCode = copiedResponses[0].statusCode; - span?.setData('http.response.status_code', copiedResponses[1].statusCode); + originalResponse = await _client.send(request); + final copier = StreamedResponseCopier(originalResponse); + originalResponse = copier.copy(); + final copiedResponse = copier.copy(); + + span?.setData('http.response.status_code', originalResponse.statusCode); span?.setData( - 'http.response_content_length', copiedResponses[1].contentLength); - span?.status = - SpanStatus.fromHttpStatusCode(copiedResponses[1].statusCode); + 'http.response_content_length', originalResponse.contentLength); + span?.status = SpanStatus.fromHttpStatusCode(originalResponse.statusCode); + + hint.set(TypeCheckHint.httpResponse, copiedResponse); } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); rethrow; } finally { - await span?.finish(); + await span?.finish(hint: hint); stopwatch.stop(); - await captureEvent( - _hub, - request: request, - requestDuration: stopwatch.elapsed, - response: copiedResponses.isNotEmpty ? copiedResponses[1] : null, - reason: 'HTTP Client Event with status code: $statusCode', - ); } - return copiedResponses[0]; + return originalResponse; } @override diff --git a/dart/lib/src/hub.dart b/dart/lib/src/hub.dart index 4e2ca289c3..073627f5df 100644 --- a/dart/lib/src/hub.dart +++ b/dart/lib/src/hub.dart @@ -576,6 +576,7 @@ class Hub { Future captureTransaction( SentryTransaction transaction, { SentryTraceContextHeader? traceContext, + Hint? hint, }) async { var sentryId = SentryId.empty(); @@ -613,11 +614,8 @@ class Hub { ); } else { try { - sentryId = await item.client.captureTransaction( - transaction, - scope: item.scope, - traceContext: traceContext, - ); + sentryId = await item.client.captureTransaction(transaction, + scope: item.scope, traceContext: traceContext, hint: hint); } catch (exception, stackTrace) { _options.logger( SentryLevel.error, diff --git a/dart/lib/src/hub_adapter.dart b/dart/lib/src/hub_adapter.dart index fa93aaf915..9297aaa28e 100644 --- a/dart/lib/src/hub_adapter.dart +++ b/dart/lib/src/hub_adapter.dart @@ -109,10 +109,12 @@ class HubAdapter implements Hub { Future captureTransaction( SentryTransaction transaction, { SentryTraceContextHeader? traceContext, + Hint? hint, }) => Sentry.currentHub.captureTransaction( transaction, traceContext: traceContext, + hint: hint, ); @override diff --git a/dart/lib/src/noop_hub.dart b/dart/lib/src/noop_hub.dart index 10f34a6d42..0446c7422e 100644 --- a/dart/lib/src/noop_hub.dart +++ b/dart/lib/src/noop_hub.dart @@ -93,6 +93,7 @@ class NoOpHub implements Hub { Future captureTransaction( SentryTransaction transaction, { SentryTraceContextHeader? traceContext, + Hint? hint, }) async => SentryId.empty(); diff --git a/dart/lib/src/noop_sentry_client.dart b/dart/lib/src/noop_sentry_client.dart index f2854f4f7e..233f63f19f 100644 --- a/dart/lib/src/noop_sentry_client.dart +++ b/dart/lib/src/noop_sentry_client.dart @@ -67,6 +67,7 @@ class NoOpSentryClient implements SentryClient { SentryTransaction transaction, { Scope? scope, SentryTraceContextHeader? traceContext, + Hint? hint, }) async => SentryId.empty(); diff --git a/dart/lib/src/noop_sentry_span.dart b/dart/lib/src/noop_sentry_span.dart index 45d72b94c9..eabe7f9954 100644 --- a/dart/lib/src/noop_sentry_span.dart +++ b/dart/lib/src/noop_sentry_span.dart @@ -1,3 +1,4 @@ +import '../sentry.dart'; import 'metrics/local_metrics_aggregator.dart'; import 'protocol.dart'; import 'tracing.dart'; @@ -27,7 +28,11 @@ class NoOpSentrySpan extends ISentrySpan { } @override - Future finish({SpanStatus? status, DateTime? endTimestamp}) async {} + Future finish({ + SpanStatus? status, + DateTime? endTimestamp, + Hint? hint, + }) async {} @override void removeData(String key) {} diff --git a/dart/lib/src/protocol/sentry_span.dart b/dart/lib/src/protocol/sentry_span.dart index 00f6ec8f5a..338f8816a6 100644 --- a/dart/lib/src/protocol/sentry_span.dart +++ b/dart/lib/src/protocol/sentry_span.dart @@ -7,7 +7,8 @@ import '../metrics/local_metrics_aggregator.dart'; import '../sentry_tracer.dart'; -typedef OnFinishedCallback = Future Function({DateTime? endTimestamp}); +typedef OnFinishedCallback = Future Function( + {DateTime? endTimestamp, Hint? hint}); class SentrySpan extends ISentrySpan { final SentrySpanContext _context; @@ -55,7 +56,13 @@ class SentrySpan extends ISentrySpan { } @override - Future finish({SpanStatus? status, DateTime? endTimestamp}) async { + Future finish({ + SpanStatus? status, + DateTime? endTimestamp, + Hint? hint, + }) async { + _tracer.hint ??= hint; + if (finished) { return; } diff --git a/dart/lib/src/sentry_client.dart b/dart/lib/src/sentry_client.dart index f5a893b45a..048d3e2b75 100644 --- a/dart/lib/src/sentry_client.dart +++ b/dart/lib/src/sentry_client.dart @@ -365,8 +365,9 @@ class SentryClient { SentryTransaction transaction, { Scope? scope, SentryTraceContextHeader? traceContext, + Hint? hint, }) async { - final hint = Hint(); + hint ??= Hint(); SentryTransaction? preparedTransaction = _prepareEvent(transaction, hint) as SentryTransaction; @@ -409,8 +410,10 @@ class SentryClient { preparedTransaction = _createUserOrSetDefaultIpAddress(preparedTransaction) as SentryTransaction; - preparedTransaction = - await _runBeforeSend(preparedTransaction, hint) as SentryTransaction?; + preparedTransaction = await _runBeforeSend( + preparedTransaction, + hint, + ) as SentryTransaction?; // dropped by beforeSendTransaction if (preparedTransaction == null) { @@ -515,7 +518,7 @@ class SentryClient { try { if (event is SentryTransaction && beforeSendTransaction != null) { beforeSendName = 'beforeSendTransaction'; - final callbackResult = beforeSendTransaction(event); + final callbackResult = beforeSendTransaction(event, hint); if (callbackResult is Future) { processedEvent = await callbackResult; } else { diff --git a/dart/lib/src/sentry_options.dart b/dart/lib/src/sentry_options.dart index 52f0834ae9..1e1b9a28fa 100644 --- a/dart/lib/src/sentry_options.dart +++ b/dart/lib/src/sentry_options.dart @@ -654,6 +654,7 @@ typedef BeforeSendCallback = FutureOr Function( /// object or nothing to skip reporting the transaction typedef BeforeSendTransactionCallback = FutureOr Function( SentryTransaction transaction, + Hint hint, ); /// This function is called with an SDK specific breadcrumb object before the breadcrumb is added diff --git a/dart/lib/src/sentry_span_interface.dart b/dart/lib/src/sentry_span_interface.dart index 979822c2ac..b7b65f39f5 100644 --- a/dart/lib/src/sentry_span_interface.dart +++ b/dart/lib/src/sentry_span_interface.dart @@ -1,5 +1,7 @@ +import 'package:http/http.dart'; import 'package:meta/meta.dart'; +import '../sentry.dart'; import 'metrics/local_metrics_aggregator.dart'; import 'protocol.dart'; import 'tracing.dart'; @@ -26,7 +28,11 @@ abstract class ISentrySpan { void removeData(String key); /// Sets span timestamp marking this span as finished. - Future finish({SpanStatus? status, DateTime? endTimestamp}) async {} + Future finish({ + SpanStatus? status, + DateTime? endTimestamp, + Hint? hint, + }) async {} /// Gets span status. SpanStatus? get status; diff --git a/dart/lib/src/sentry_tracer.dart b/dart/lib/src/sentry_tracer.dart index 0f53d26e38..021db25fc5 100644 --- a/dart/lib/src/sentry_tracer.dart +++ b/dart/lib/src/sentry_tracer.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:http/http.dart'; import 'package:meta/meta.dart'; import '../sentry.dart'; @@ -33,6 +34,12 @@ class SentryTracer extends ISentrySpan { late SentryTransactionNameSource transactionNameSource; + Hint? _hint; + @internal + Hint? get hint => _hint; + @internal + set hint(Hint? hint) => _hint = hint; + SentryTraceContextHeader? _sentryTraceContextHeader; // Profiler attached to this tracer. @@ -92,7 +99,12 @@ class SentryTracer extends ISentrySpan { } @override - Future finish({SpanStatus? status, DateTime? endTimestamp}) async { + Future finish({ + SpanStatus? status, + DateTime? endTimestamp, + Hint? hint, + }) async { + _hint ??= hint; final commonEndTimestamp = endTimestamp ?? _hub.options.clock(); _autoFinishAfterTimer?.cancel(); _finishStatus = SentryTracerFinishStatus.finishing(status); @@ -157,10 +169,8 @@ class SentryTracer extends ISentrySpan { ? await profiler?.finishFor(transaction) : null; - await _hub.captureTransaction( - transaction, - traceContext: traceContext(), - ); + await _hub.captureTransaction(transaction, + traceContext: traceContext(), hint: _hint); } finally { profiler?.dispose(); } @@ -274,12 +284,11 @@ class SentryTracer extends ISentrySpan { return child; } - Future _finishedCallback({ - DateTime? endTimestamp, - }) async { + Future _finishedCallback({DateTime? endTimestamp, Hint? hint}) async { final finishStatus = _finishStatus; if (finishStatus.finishing) { - await finish(status: finishStatus.status, endTimestamp: endTimestamp); + await finish( + status: finishStatus.status, endTimestamp: endTimestamp, hint: hint); } } diff --git a/dart/lib/src/utils/streamed_response_copier.dart b/dart/lib/src/utils/streamed_response_copier.dart new file mode 100644 index 0000000000..7087fa3dbf --- /dev/null +++ b/dart/lib/src/utils/streamed_response_copier.dart @@ -0,0 +1,58 @@ +import 'dart:async'; +import 'dart:io'; +import 'package:http/http.dart'; + +class StreamedResponseCopier { + final StreamController> _streamController; + final List> _cache = []; + bool _isDone = false; + final StreamedResponse originalResponse; + + StreamedResponseCopier(this.originalResponse) + : _streamController = StreamController>.broadcast() { + // Listen to the original stream and cache the data + originalResponse.stream.listen( + (data) { + _cache.add(data); // Cache the data + _streamController.add(data); // Forward the data + }, + onError: _streamController.addError, + onDone: () { + _isDone = true; + _streamController.close(); + }, + ); + } + + /// Get a copied StreamedResponse + StreamedResponse copy() { + final Stream> replayStream = _getReplayStream(); + return StreamedResponse( + replayStream, + originalResponse.statusCode, + contentLength: originalResponse.contentLength, + request: originalResponse.request, + headers: originalResponse.headers, + isRedirect: originalResponse.isRedirect, + reasonPhrase: originalResponse.reasonPhrase, + ); + } + + /// Create a stream that replays the cached data and listens to future updates + Stream> _getReplayStream() async* { + // Replay cached data + for (final chunk in _cache) { + yield chunk; + } + + // Stream new data if the original stream is not done + if (!_isDone) { + yield* _streamController.stream; + } + } + + /// Dispose resources when done + void dispose() { + _streamController.close(); + } +} diff --git a/dart/test/http_client/tracing_client_test.dart b/dart/test/http_client/tracing_client_test.dart index 195ebf91fa..32cff3af0b 100644 --- a/dart/test/http_client/tracing_client_test.dart +++ b/dart/test/http_client/tracing_client_test.dart @@ -1,5 +1,8 @@ +import 'dart:async'; + import 'package:http/http.dart'; import 'package:http/testing.dart'; +import 'package:mockito/mockito.dart'; import 'package:sentry/sentry.dart'; import 'package:sentry/src/http_client/tracing_client.dart'; import 'package:sentry/src/sentry_tracer.dart'; @@ -10,6 +13,13 @@ import '../test_utils.dart'; final requestUri = Uri.parse('https://example.com?foo=bar#baz'); +class MockBeforeSendTransactionCallback extends Mock { + FutureOr beforeSendTransaction( + SentryTransaction? transaction, + Hint? hint, + ); +} + void main() { group(TracingClient, () { late Fixture fixture; @@ -18,6 +28,69 @@ void main() { fixture = Fixture(); }); + test('beforeSendTransaction called for captured span', () async { + var beforeSendTransaction = + MockBeforeSendTransactionCallback().beforeSendTransaction; + + fixture._hub.options.beforeSendTransaction = beforeSendTransaction; + final responseBody = "test response body"; + final sut = fixture.getSut( + client: fixture.getClient( + statusCode: 200, reason: 'OK', body: responseBody), + ); + final tr = fixture._hub.startTransaction( + 'name', + 'op', + bindToScope: true, + ); + + await sut.get(requestUri); + + await tr.finish(); + + verify(beforeSendTransaction( + any, + any, + )).called(1); + }); + + test('beforeSendTransaction called with response as hint for captured span', + () async { + SentryTransaction? transaction; + Hint? hint; + + fixture._hub.options.beforeSendTransaction = (_transaction, _hint) { + transaction = _transaction; + hint = _hint; + return transaction; + }; + + final responseBody = "test response body"; + final sut = fixture.getSut( + client: fixture.getClient( + statusCode: 200, reason: 'OK', body: responseBody), + ); + final tr = fixture._hub.startTransaction( + 'name', + 'op', + bindToScope: true, + ); + + final originalResponse = await sut.get(requestUri); + final originalResponseBody = originalResponse.body; + + await tr.finish(); + + final httpResponse = + hint!.get(TypeCheckHint.httpResponse) as StreamedResponse; + final httpResponseBody = await httpResponse.stream.bytesToString(); + + expect(httpResponse.statusCode, 200); + expect(httpResponseBody, responseBody); + + expect(originalResponseBody, responseBody); + }); + test('captured span if successful request without Pii', () async { final responseBody = "test response body"; final sut = fixture.getSut( diff --git a/dart/test/mocks.mocks.dart b/dart/test/mocks.mocks.dart index 888d076890..ea7de1a607 100644 --- a/dart/test/mocks.mocks.dart +++ b/dart/test/mocks.mocks.dart @@ -528,19 +528,26 @@ class MockHub extends _i1.Mock implements _i2.Hub { _i5.Future<_i2.SentryId> captureTransaction( _i2.SentryTransaction? transaction, { _i2.SentryTraceContextHeader? traceContext, + _i2.Hint? hint, }) => (super.noSuchMethod( Invocation.method( #captureTransaction, [transaction], - {#traceContext: traceContext}, + { + #traceContext: traceContext, + #hint: hint, + }, ), returnValue: _i5.Future<_i2.SentryId>.value(_FakeSentryId_3( this, Invocation.method( #captureTransaction, [transaction], - {#traceContext: traceContext}, + { + #traceContext: traceContext, + #hint: hint, + }, ), )), ) as _i5.Future<_i2.SentryId>); diff --git a/dart/test/mocks/mock_hub.dart b/dart/test/mocks/mock_hub.dart index dcd305e821..92cb1837b3 100644 --- a/dart/test/mocks/mock_hub.dart +++ b/dart/test/mocks/mock_hub.dart @@ -118,10 +118,8 @@ class MockHub with NoSuchMethodProvider implements Hub { bool get isEnabled => _isEnabled; @override - Future captureTransaction( - SentryTransaction transaction, { - SentryTraceContextHeader? traceContext, - }) async { + Future captureTransaction(SentryTransaction transaction, + {SentryTraceContextHeader? traceContext, Hint? hint}) async { captureTransactionCalls .add(CaptureTransactionCall(transaction, traceContext)); return transaction.eventId; diff --git a/dart/test/mocks/mock_sentry_client.dart b/dart/test/mocks/mock_sentry_client.dart index c0e4ba9ffe..f0d6dd9ebf 100644 --- a/dart/test/mocks/mock_sentry_client.dart +++ b/dart/test/mocks/mock_sentry_client.dart @@ -110,6 +110,7 @@ class MockSentryClient with NoSuchMethodProvider implements SentryClient { SentryTransaction transaction, { Scope? scope, SentryTraceContextHeader? traceContext, + Hint? hint, }) async { captureTransactionCalls .add(CaptureTransactionCall(transaction, traceContext)); diff --git a/dart/test/sentry_client_test.dart b/dart/test/sentry_client_test.dart index 17b209ec83..69d5fea559 100644 --- a/dart/test/sentry_client_test.dart +++ b/dart/test/sentry_client_test.dart @@ -1368,7 +1368,8 @@ void main() { test('thrown error is handled', () async { fixture.options.automatedTestMode = false; final exception = Exception("before send exception"); - final beforeSendTransactionCallback = (SentryTransaction event) { + final beforeSendTransactionCallback = + (SentryTransaction event, Hint? hint) { throw exception; }; @@ -1767,7 +1768,10 @@ void main() { fixture.tracer.startChild('child2'); fixture.tracer.startChild('child3'); - fixture.options.beforeSendTransaction = (transaction) { + fixture.options.beforeSendTransaction = ( + transaction, + Hint? hint, + ) { if (transaction.tracer == fixture.tracer) { return null; } @@ -1794,7 +1798,10 @@ void main() { fixture.tracer.startChild('child2'); fixture.tracer.startChild('child3'); - fixture.options.beforeSendTransaction = (transaction) { + fixture.options.beforeSendTransaction = ( + transaction, + Hint? hint, + ) { if (transaction.tracer == fixture.tracer) { transaction.spans .removeWhere((element) => element.context.operation == 'child2'); @@ -2237,6 +2244,7 @@ Future asyncBeforeSendFeedbackCallbackDropEvent( SentryTransaction? beforeSendTransactionCallbackDropEvent( SentryTransaction event, + Hint? hint, ) => null; @@ -2249,7 +2257,9 @@ Future asyncBeforeSendCallbackDropEvent( } Future asyncBeforeSendTransactionCallbackDropEvent( - SentryEvent event) async { + SentryEvent event, + Hint? hint, +) async { await Future.delayed(Duration(milliseconds: 200)); return null; } @@ -2271,7 +2281,9 @@ SentryEvent? beforeSendCallback(SentryEvent event, Hint hint) { } SentryTransaction? beforeSendTransactionCallback( - SentryTransaction transaction) { + SentryTransaction transaction, + Hint? hint, +) { return transaction ..tags!.addAll({'theme': 'material'}) // ignore: deprecated_member_use_from_same_package diff --git a/dart/test/sentry_span_test.dart b/dart/test/sentry_span_test.dart index d063cf787e..0fba7110b2 100644 --- a/dart/test/sentry_span_test.dart +++ b/dart/test/sentry_span_test.dart @@ -259,8 +259,8 @@ void main() { test('callback called on finish', () async { var numberOfCallbackCalls = 0; - final sut = - fixture.getSut(finishedCallback: ({DateTime? endTimestamp}) async { + final sut = fixture.getSut( + finishedCallback: ({DateTime? endTimestamp, Hint? hint}) async { numberOfCallbackCalls += 1; }); From 24b8ca99a1d46679b9137a13390e6e959641a352 Mon Sep 17 00:00:00 2001 From: Martin Haintz Date: Tue, 19 Nov 2024 12:43:34 +0100 Subject: [PATCH 07/25] update hive mocks --- hive/test/mocks/mocks.mocks.dart | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/hive/test/mocks/mocks.mocks.dart b/hive/test/mocks/mocks.mocks.dart index 5cd8fc7e30..9cf52423ef 100644 --- a/hive/test/mocks/mocks.mocks.dart +++ b/hive/test/mocks/mocks.mocks.dart @@ -428,21 +428,28 @@ class MockHub extends _i1.Mock implements _i2.Hub { @override _i5.Future<_i2.SentryId> captureTransaction( - _i2.SentryTransaction? transaction, { - _i2.SentryTraceContextHeader? traceContext, - }) => + _i2.SentryTransaction? transaction, { + _i2.SentryTraceContextHeader? traceContext, + _i2.Hint? hint, + }) => (super.noSuchMethod( Invocation.method( #captureTransaction, [transaction], - {#traceContext: traceContext}, + { + #traceContext: traceContext, + #hint: hint, + }, ), returnValue: _i5.Future<_i2.SentryId>.value(_FakeSentryId_1( this, Invocation.method( #captureTransaction, [transaction], - {#traceContext: traceContext}, + { + #traceContext: traceContext, + #hint: hint, + }, ), )), ) as _i5.Future<_i2.SentryId>); From 7042c14e78feccc609a3c0845eeefc5247c5a1da Mon Sep 17 00:00:00 2001 From: Martin Haintz Date: Tue, 19 Nov 2024 12:43:56 +0100 Subject: [PATCH 08/25] update drift mocks --- drift/test/mocks/mocks.mocks.dart | 337 ++++++++++++++++++------------ 1 file changed, 206 insertions(+), 131 deletions(-) diff --git a/drift/test/mocks/mocks.mocks.dart b/drift/test/mocks/mocks.mocks.dart index f6a88c359a..d68c5ed2f5 100644 --- a/drift/test/mocks/mocks.mocks.dart +++ b/drift/test/mocks/mocks.mocks.dart @@ -1,20 +1,24 @@ -// Mocks generated by Mockito 5.4.2 from annotations +// Mocks generated by Mockito 5.4.4 from annotations // in sentry_drift/test/mocks/mocks.dart. // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i5; +import 'dart:async' as _i6; -import 'package:drift/backends.dart' as _i3; -import 'package:drift/drift.dart' as _i6; +import 'package:drift/backends.dart' as _i4; +import 'package:drift/drift.dart' as _i8; import 'package:mockito/mockito.dart' as _i1; import 'package:sentry/sentry.dart' as _i2; -import 'package:sentry/src/profiling.dart' as _i4; +import 'package:sentry/src/metrics/metric.dart' as _i7; +import 'package:sentry/src/metrics/metrics_api.dart' as _i3; +import 'package:sentry/src/profiling.dart' as _i5; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values // ignore_for_file: avoid_setters_without_getters // ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package // ignore_for_file: implementation_imports // ignore_for_file: invalid_use_of_visible_for_testing_member // ignore_for_file: prefer_const_constructors @@ -32,8 +36,8 @@ class _FakeSentryOptions_0 extends _i1.SmartFake implements _i2.SentryOptions { ); } -class _FakeSentryId_1 extends _i1.SmartFake implements _i2.SentryId { - _FakeSentryId_1( +class _FakeMetricsApi_1 extends _i1.SmartFake implements _i3.MetricsApi { + _FakeMetricsApi_1( Object parent, Invocation parentInvocation, ) : super( @@ -42,8 +46,8 @@ class _FakeSentryId_1 extends _i1.SmartFake implements _i2.SentryId { ); } -class _FakeScope_2 extends _i1.SmartFake implements _i2.Scope { - _FakeScope_2( +class _FakeSentryId_2 extends _i1.SmartFake implements _i2.SentryId { + _FakeSentryId_2( Object parent, Invocation parentInvocation, ) : super( @@ -52,8 +56,8 @@ class _FakeScope_2 extends _i1.SmartFake implements _i2.Scope { ); } -class _FakeHub_3 extends _i1.SmartFake implements _i2.Hub { - _FakeHub_3( +class _FakeScope_3 extends _i1.SmartFake implements _i2.Scope { + _FakeScope_3( Object parent, Invocation parentInvocation, ) : super( @@ -62,8 +66,8 @@ class _FakeHub_3 extends _i1.SmartFake implements _i2.Hub { ); } -class _FakeISentrySpan_4 extends _i1.SmartFake implements _i2.ISentrySpan { - _FakeISentrySpan_4( +class _FakeHub_4 extends _i1.SmartFake implements _i2.Hub { + _FakeHub_4( Object parent, Invocation parentInvocation, ) : super( @@ -72,8 +76,8 @@ class _FakeISentrySpan_4 extends _i1.SmartFake implements _i2.ISentrySpan { ); } -class _FakeQueryExecutor_5 extends _i1.SmartFake implements _i3.QueryExecutor { - _FakeQueryExecutor_5( +class _FakeISentrySpan_5 extends _i1.SmartFake implements _i2.ISentrySpan { + _FakeISentrySpan_5( Object parent, Invocation parentInvocation, ) : super( @@ -82,9 +86,19 @@ class _FakeQueryExecutor_5 extends _i1.SmartFake implements _i3.QueryExecutor { ); } -class _FakeTransactionExecutor_6 extends _i1.SmartFake - implements _i3.TransactionExecutor { - _FakeTransactionExecutor_6( +class _FakeQueryExecutor_6 extends _i1.SmartFake implements _i4.QueryExecutor { + _FakeQueryExecutor_6( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeTransactionExecutor_7 extends _i1.SmartFake + implements _i4.TransactionExecutor { + _FakeTransactionExecutor_7( Object parent, Invocation parentInvocation, ) : super( @@ -110,6 +124,15 @@ class MockHub extends _i1.Mock implements _i2.Hub { ), ) as _i2.SentryOptions); + @override + _i3.MetricsApi get metricsApi => (super.noSuchMethod( + Invocation.getter(#metricsApi), + returnValue: _FakeMetricsApi_1( + this, + Invocation.getter(#metricsApi), + ), + ) as _i3.MetricsApi); + @override bool get isEnabled => (super.noSuchMethod( Invocation.getter(#isEnabled), @@ -119,7 +142,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { @override _i2.SentryId get lastEventId => (super.noSuchMethod( Invocation.getter(#lastEventId), - returnValue: _FakeSentryId_1( + returnValue: _FakeSentryId_2( this, Invocation.getter(#lastEventId), ), @@ -128,14 +151,14 @@ class MockHub extends _i1.Mock implements _i2.Hub { @override _i2.Scope get scope => (super.noSuchMethod( Invocation.getter(#scope), - returnValue: _FakeScope_2( + returnValue: _FakeScope_3( this, Invocation.getter(#scope), ), ) as _i2.Scope); @override - set profilerFactory(_i4.SentryProfilerFactory? value) => super.noSuchMethod( + set profilerFactory(_i5.SentryProfilerFactory? value) => super.noSuchMethod( Invocation.setter( #profilerFactory, value, @@ -144,7 +167,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { ); @override - _i5.Future<_i2.SentryId> captureEvent( + _i6.Future<_i2.SentryId> captureEvent( _i2.SentryEvent? event, { dynamic stackTrace, _i2.Hint? hint, @@ -160,7 +183,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #withScope: withScope, }, ), - returnValue: _i5.Future<_i2.SentryId>.value(_FakeSentryId_1( + returnValue: _i6.Future<_i2.SentryId>.value(_FakeSentryId_2( this, Invocation.method( #captureEvent, @@ -172,10 +195,10 @@ class MockHub extends _i1.Mock implements _i2.Hub { }, ), )), - ) as _i5.Future<_i2.SentryId>); + ) as _i6.Future<_i2.SentryId>); @override - _i5.Future<_i2.SentryId> captureException( + _i6.Future<_i2.SentryId> captureException( dynamic throwable, { dynamic stackTrace, _i2.Hint? hint, @@ -191,7 +214,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #withScope: withScope, }, ), - returnValue: _i5.Future<_i2.SentryId>.value(_FakeSentryId_1( + returnValue: _i6.Future<_i2.SentryId>.value(_FakeSentryId_2( this, Invocation.method( #captureException, @@ -203,10 +226,10 @@ class MockHub extends _i1.Mock implements _i2.Hub { }, ), )), - ) as _i5.Future<_i2.SentryId>); + ) as _i6.Future<_i2.SentryId>); @override - _i5.Future<_i2.SentryId> captureMessage( + _i6.Future<_i2.SentryId> captureMessage( String? message, { _i2.SentryLevel? level, String? template, @@ -226,7 +249,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #withScope: withScope, }, ), - returnValue: _i5.Future<_i2.SentryId>.value(_FakeSentryId_1( + returnValue: _i6.Future<_i2.SentryId>.value(_FakeSentryId_2( this, Invocation.method( #captureMessage, @@ -240,21 +263,49 @@ class MockHub extends _i1.Mock implements _i2.Hub { }, ), )), - ) as _i5.Future<_i2.SentryId>); + ) as _i6.Future<_i2.SentryId>); @override - _i5.Future captureUserFeedback(_i2.SentryUserFeedback? userFeedback) => + _i6.Future captureUserFeedback(_i2.SentryUserFeedback? userFeedback) => (super.noSuchMethod( Invocation.method( #captureUserFeedback, [userFeedback], ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); + + @override + _i6.Future<_i2.SentryId> captureFeedback( + _i2.SentryFeedback? feedback, { + _i2.Hint? hint, + _i2.ScopeCallback? withScope, + }) => + (super.noSuchMethod( + Invocation.method( + #captureFeedback, + [feedback], + { + #hint: hint, + #withScope: withScope, + }, + ), + returnValue: _i6.Future<_i2.SentryId>.value(_FakeSentryId_2( + this, + Invocation.method( + #captureFeedback, + [feedback], + { + #hint: hint, + #withScope: withScope, + }, + ), + )), + ) as _i6.Future<_i2.SentryId>); @override - _i5.Future addBreadcrumb( + _i6.Future addBreadcrumb( _i2.Breadcrumb? crumb, { _i2.Hint? hint, }) => @@ -264,9 +315,9 @@ class MockHub extends _i1.Mock implements _i2.Hub { [crumb], {#hint: hint}, ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); @override void bindClient(_i2.SentryClient? client) => super.noSuchMethod( @@ -283,7 +334,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #clone, [], ), - returnValue: _FakeHub_3( + returnValue: _FakeHub_4( this, Invocation.method( #clone, @@ -293,21 +344,21 @@ class MockHub extends _i1.Mock implements _i2.Hub { ) as _i2.Hub); @override - _i5.Future close() => (super.noSuchMethod( + _i6.Future close() => (super.noSuchMethod( Invocation.method( #close, [], ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); @override - _i5.FutureOr configureScope(_i2.ScopeCallback? callback) => + _i6.FutureOr configureScope(_i2.ScopeCallback? callback) => (super.noSuchMethod(Invocation.method( #configureScope, [callback], - )) as _i5.FutureOr); + )) as _i6.FutureOr); @override _i2.ISentrySpan startTransaction( @@ -340,7 +391,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #customSamplingContext: customSamplingContext, }, ), - returnValue: _FakeISentrySpan_4( + returnValue: _FakeISentrySpan_5( this, Invocation.method( #startTransaction, @@ -387,7 +438,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #onFinish: onFinish, }, ), - returnValue: _FakeISentrySpan_4( + returnValue: _FakeISentrySpan_5( this, Invocation.method( #startTransactionWithContext, @@ -406,25 +457,49 @@ class MockHub extends _i1.Mock implements _i2.Hub { ) as _i2.ISentrySpan); @override - _i5.Future<_i2.SentryId> captureTransaction( + _i6.Future<_i2.SentryId> captureTransaction( _i2.SentryTransaction? transaction, { _i2.SentryTraceContextHeader? traceContext, + _i2.Hint? hint, }) => (super.noSuchMethod( Invocation.method( #captureTransaction, [transaction], - {#traceContext: traceContext}, + { + #traceContext: traceContext, + #hint: hint, + }, ), - returnValue: _i5.Future<_i2.SentryId>.value(_FakeSentryId_1( + returnValue: _i6.Future<_i2.SentryId>.value(_FakeSentryId_2( this, Invocation.method( #captureTransaction, [transaction], - {#traceContext: traceContext}, + { + #traceContext: traceContext, + #hint: hint, + }, + ), + )), + ) as _i6.Future<_i2.SentryId>); + + @override + _i6.Future<_i2.SentryId> captureMetrics( + Map>? metricsBuckets) => + (super.noSuchMethod( + Invocation.method( + #captureMetrics, + [metricsBuckets], + ), + returnValue: _i6.Future<_i2.SentryId>.value(_FakeSentryId_2( + this, + Invocation.method( + #captureMetrics, + [metricsBuckets], ), )), - ) as _i5.Future<_i2.SentryId>); + ) as _i6.Future<_i2.SentryId>); @override void setSpanContext( @@ -448,65 +523,65 @@ class MockHub extends _i1.Mock implements _i2.Hub { /// A class which mocks [LazyDatabase]. /// /// See the documentation for Mockito's code generation for more information. -class MockLazyDatabase extends _i1.Mock implements _i6.LazyDatabase { +class MockLazyDatabase extends _i1.Mock implements _i8.LazyDatabase { MockLazyDatabase() { _i1.throwOnMissingStub(this); } @override - _i6.DatabaseOpener get opener => (super.noSuchMethod( + _i8.DatabaseOpener get opener => (super.noSuchMethod( Invocation.getter(#opener), returnValue: () => - _i5.Future<_i3.QueryExecutor>.value(_FakeQueryExecutor_5( + _i6.Future<_i4.QueryExecutor>.value(_FakeQueryExecutor_6( this, Invocation.getter(#opener), )), - ) as _i6.DatabaseOpener); + ) as _i8.DatabaseOpener); @override - _i3.SqlDialect get dialect => (super.noSuchMethod( + _i4.SqlDialect get dialect => (super.noSuchMethod( Invocation.getter(#dialect), - returnValue: _i3.SqlDialect.sqlite, - ) as _i3.SqlDialect); + returnValue: _i4.SqlDialect.sqlite, + ) as _i4.SqlDialect); @override - _i3.TransactionExecutor beginTransaction() => (super.noSuchMethod( + _i4.TransactionExecutor beginTransaction() => (super.noSuchMethod( Invocation.method( #beginTransaction, [], ), - returnValue: _FakeTransactionExecutor_6( + returnValue: _FakeTransactionExecutor_7( this, Invocation.method( #beginTransaction, [], ), ), - ) as _i3.TransactionExecutor); + ) as _i4.TransactionExecutor); @override - _i5.Future ensureOpen(_i3.QueryExecutorUser? user) => + _i6.Future ensureOpen(_i4.QueryExecutorUser? user) => (super.noSuchMethod( Invocation.method( #ensureOpen, [user], ), - returnValue: _i5.Future.value(false), - ) as _i5.Future); + returnValue: _i6.Future.value(false), + ) as _i6.Future); @override - _i5.Future runBatched(_i3.BatchedStatements? statements) => + _i6.Future runBatched(_i4.BatchedStatements? statements) => (super.noSuchMethod( Invocation.method( #runBatched, [statements], ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); @override - _i5.Future runCustom( + _i6.Future runCustom( String? statement, [ List? args, ]) => @@ -518,12 +593,12 @@ class MockLazyDatabase extends _i1.Mock implements _i6.LazyDatabase { args, ], ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); @override - _i5.Future runDelete( + _i6.Future runDelete( String? statement, List? args, ) => @@ -535,11 +610,11 @@ class MockLazyDatabase extends _i1.Mock implements _i6.LazyDatabase { args, ], ), - returnValue: _i5.Future.value(0), - ) as _i5.Future); + returnValue: _i6.Future.value(0), + ) as _i6.Future); @override - _i5.Future runInsert( + _i6.Future runInsert( String? statement, List? args, ) => @@ -551,11 +626,11 @@ class MockLazyDatabase extends _i1.Mock implements _i6.LazyDatabase { args, ], ), - returnValue: _i5.Future.value(0), - ) as _i5.Future); + returnValue: _i6.Future.value(0), + ) as _i6.Future); @override - _i5.Future>> runSelect( + _i6.Future>> runSelect( String? statement, List? args, ) => @@ -567,12 +642,12 @@ class MockLazyDatabase extends _i1.Mock implements _i6.LazyDatabase { args, ], ), - returnValue: _i5.Future>>.value( + returnValue: _i6.Future>>.value( >[]), - ) as _i5.Future>>); + ) as _i6.Future>>); @override - _i5.Future runUpdate( + _i6.Future runUpdate( String? statement, List? args, ) => @@ -584,25 +659,25 @@ class MockLazyDatabase extends _i1.Mock implements _i6.LazyDatabase { args, ], ), - returnValue: _i5.Future.value(0), - ) as _i5.Future); + returnValue: _i6.Future.value(0), + ) as _i6.Future); @override - _i5.Future close() => (super.noSuchMethod( + _i6.Future close() => (super.noSuchMethod( Invocation.method( #close, [], ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); } /// A class which mocks [TransactionExecutor]. /// /// See the documentation for Mockito's code generation for more information. class MockTransactionExecutor extends _i1.Mock - implements _i3.TransactionExecutor { + implements _i4.TransactionExecutor { MockTransactionExecutor() { _i1.throwOnMissingStub(this); } @@ -614,43 +689,43 @@ class MockTransactionExecutor extends _i1.Mock ) as bool); @override - _i3.SqlDialect get dialect => (super.noSuchMethod( + _i4.SqlDialect get dialect => (super.noSuchMethod( Invocation.getter(#dialect), - returnValue: _i3.SqlDialect.sqlite, - ) as _i3.SqlDialect); + returnValue: _i4.SqlDialect.sqlite, + ) as _i4.SqlDialect); @override - _i5.Future send() => (super.noSuchMethod( + _i6.Future send() => (super.noSuchMethod( Invocation.method( #send, [], ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); @override - _i5.Future rollback() => (super.noSuchMethod( + _i6.Future rollback() => (super.noSuchMethod( Invocation.method( #rollback, [], ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); @override - _i5.Future ensureOpen(_i3.QueryExecutorUser? user) => + _i6.Future ensureOpen(_i4.QueryExecutorUser? user) => (super.noSuchMethod( Invocation.method( #ensureOpen, [user], ), - returnValue: _i5.Future.value(false), - ) as _i5.Future); + returnValue: _i6.Future.value(false), + ) as _i6.Future); @override - _i5.Future>> runSelect( + _i6.Future>> runSelect( String? statement, List? args, ) => @@ -662,12 +737,12 @@ class MockTransactionExecutor extends _i1.Mock args, ], ), - returnValue: _i5.Future>>.value( + returnValue: _i6.Future>>.value( >[]), - ) as _i5.Future>>); + ) as _i6.Future>>); @override - _i5.Future runInsert( + _i6.Future runInsert( String? statement, List? args, ) => @@ -679,11 +754,11 @@ class MockTransactionExecutor extends _i1.Mock args, ], ), - returnValue: _i5.Future.value(0), - ) as _i5.Future); + returnValue: _i6.Future.value(0), + ) as _i6.Future); @override - _i5.Future runUpdate( + _i6.Future runUpdate( String? statement, List? args, ) => @@ -695,11 +770,11 @@ class MockTransactionExecutor extends _i1.Mock args, ], ), - returnValue: _i5.Future.value(0), - ) as _i5.Future); + returnValue: _i6.Future.value(0), + ) as _i6.Future); @override - _i5.Future runDelete( + _i6.Future runDelete( String? statement, List? args, ) => @@ -711,11 +786,11 @@ class MockTransactionExecutor extends _i1.Mock args, ], ), - returnValue: _i5.Future.value(0), - ) as _i5.Future); + returnValue: _i6.Future.value(0), + ) as _i6.Future); @override - _i5.Future runCustom( + _i6.Future runCustom( String? statement, [ List? args, ]) => @@ -727,43 +802,43 @@ class MockTransactionExecutor extends _i1.Mock args, ], ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); @override - _i5.Future runBatched(_i3.BatchedStatements? statements) => + _i6.Future runBatched(_i4.BatchedStatements? statements) => (super.noSuchMethod( Invocation.method( #runBatched, [statements], ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); @override - _i3.TransactionExecutor beginTransaction() => (super.noSuchMethod( + _i4.TransactionExecutor beginTransaction() => (super.noSuchMethod( Invocation.method( #beginTransaction, [], ), - returnValue: _FakeTransactionExecutor_6( + returnValue: _FakeTransactionExecutor_7( this, Invocation.method( #beginTransaction, [], ), ), - ) as _i3.TransactionExecutor); + ) as _i4.TransactionExecutor); @override - _i5.Future close() => (super.noSuchMethod( + _i6.Future close() => (super.noSuchMethod( Invocation.method( #close, [], ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); } From b9fbb3abaabdbfbc84a12d5bf93c279202cbf5dc Mon Sep 17 00:00:00 2001 From: Martin Haintz Date: Tue, 19 Nov 2024 12:44:08 +0100 Subject: [PATCH 09/25] update dio mocks --- dio/test/mocks/mock_hub.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/dio/test/mocks/mock_hub.dart b/dio/test/mocks/mock_hub.dart index d798b551ac..b10bb07ac0 100644 --- a/dio/test/mocks/mock_hub.dart +++ b/dio/test/mocks/mock_hub.dart @@ -117,6 +117,7 @@ class MockHub with NoSuchMethodProvider implements Hub { Future captureTransaction( SentryTransaction transaction, { SentryTraceContextHeader? traceContext, + Hint? hint }) async { captureTransactionCalls.add(transaction); return transaction.eventId; From 557958f3bd796692f6a504e54c58a01995893124 Mon Sep 17 00:00:00 2001 From: Martin Haintz Date: Tue, 19 Nov 2024 12:44:25 +0100 Subject: [PATCH 10/25] update file mocks --- file/test/mock_sentry_client.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/file/test/mock_sentry_client.dart b/file/test/mock_sentry_client.dart index 8fb4091cd7..098f5b84fd 100644 --- a/file/test/mock_sentry_client.dart +++ b/file/test/mock_sentry_client.dart @@ -17,6 +17,7 @@ class MockSentryClient with NoSuchMethodProvider implements SentryClient { SentryTransaction transaction, { Scope? scope, SentryTraceContextHeader? traceContext, + Hint? hint, }) async { captureTransactionCalls .add(CaptureTransactionCall(transaction, traceContext, scope)); From 5959137fd5f8225ec66e1afffda444f24e06bf19 Mon Sep 17 00:00:00 2001 From: Martin Haintz Date: Tue, 19 Nov 2024 12:53:45 +0100 Subject: [PATCH 11/25] update mocks for isar --- isar/test/mocks/mocks.mocks.dart | 482 ++++++++++++++++++------------- 1 file changed, 281 insertions(+), 201 deletions(-) diff --git a/isar/test/mocks/mocks.mocks.dart b/isar/test/mocks/mocks.mocks.dart index dc4cbd87a4..cceba1025b 100644 --- a/isar/test/mocks/mocks.mocks.dart +++ b/isar/test/mocks/mocks.mocks.dart @@ -1,21 +1,25 @@ -// Mocks generated by Mockito 5.4.2 from annotations +// Mocks generated by Mockito 5.4.4 from annotations // in sentry_isar/test/mocks/mocks.dart. // Do not manually edit this file. -// ignore_for_file: no_leading_underscores_for_library_prefixes, invalid_use_of_internal_member -import 'dart:async' as _i3; -import 'dart:typed_data' as _i7; +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i4; +import 'dart:typed_data' as _i9; -import 'package:isar/isar.dart' as _i4; +import 'package:isar/isar.dart' as _i5; import 'package:mockito/mockito.dart' as _i1; -import 'package:mockito/src/dummies.dart' as _i6; +import 'package:mockito/src/dummies.dart' as _i8; import 'package:sentry/sentry.dart' as _i2; -import 'package:sentry/src/profiling.dart' as _i5; +import 'package:sentry/src/metrics/metric.dart' as _i7; +import 'package:sentry/src/metrics/metrics_api.dart' as _i3; +import 'package:sentry/src/profiling.dart' as _i6; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values // ignore_for_file: avoid_setters_without_getters // ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package // ignore_for_file: implementation_imports // ignore_for_file: invalid_use_of_visible_for_testing_member // ignore_for_file: prefer_const_constructors @@ -33,8 +37,8 @@ class _FakeSentryOptions_0 extends _i1.SmartFake implements _i2.SentryOptions { ); } -class _FakeSentryId_1 extends _i1.SmartFake implements _i2.SentryId { - _FakeSentryId_1( +class _FakeMetricsApi_1 extends _i1.SmartFake implements _i3.MetricsApi { + _FakeMetricsApi_1( Object parent, Invocation parentInvocation, ) : super( @@ -43,8 +47,8 @@ class _FakeSentryId_1 extends _i1.SmartFake implements _i2.SentryId { ); } -class _FakeScope_2 extends _i1.SmartFake implements _i2.Scope { - _FakeScope_2( +class _FakeSentryId_2 extends _i1.SmartFake implements _i2.SentryId { + _FakeSentryId_2( Object parent, Invocation parentInvocation, ) : super( @@ -53,8 +57,8 @@ class _FakeScope_2 extends _i1.SmartFake implements _i2.Scope { ); } -class _FakeHub_3 extends _i1.SmartFake implements _i2.Hub { - _FakeHub_3( +class _FakeScope_3 extends _i1.SmartFake implements _i2.Scope { + _FakeScope_3( Object parent, Invocation parentInvocation, ) : super( @@ -63,8 +67,8 @@ class _FakeHub_3 extends _i1.SmartFake implements _i2.Hub { ); } -class _FakeISentrySpan_4 extends _i1.SmartFake implements _i2.ISentrySpan { - _FakeISentrySpan_4( +class _FakeHub_4 extends _i1.SmartFake implements _i2.Hub { + _FakeHub_4( Object parent, Invocation parentInvocation, ) : super( @@ -73,8 +77,8 @@ class _FakeISentrySpan_4 extends _i1.SmartFake implements _i2.ISentrySpan { ); } -class _FakeFuture_5 extends _i1.SmartFake implements _i3.Future { - _FakeFuture_5( +class _FakeISentrySpan_5 extends _i1.SmartFake implements _i2.ISentrySpan { + _FakeISentrySpan_5( Object parent, Invocation parentInvocation, ) : super( @@ -83,9 +87,8 @@ class _FakeFuture_5 extends _i1.SmartFake implements _i3.Future { ); } -class _FakeIsarCollection_6 extends _i1.SmartFake - implements _i4.IsarCollection { - _FakeIsarCollection_6( +class _FakeFuture_6 extends _i1.SmartFake implements _i4.Future { + _FakeFuture_6( Object parent, Invocation parentInvocation, ) : super( @@ -94,8 +97,9 @@ class _FakeIsarCollection_6 extends _i1.SmartFake ); } -class _FakeIsar_7 extends _i1.SmartFake implements _i4.Isar { - _FakeIsar_7( +class _FakeIsarCollection_7 extends _i1.SmartFake + implements _i5.IsarCollection { + _FakeIsarCollection_7( Object parent, Invocation parentInvocation, ) : super( @@ -104,9 +108,8 @@ class _FakeIsar_7 extends _i1.SmartFake implements _i4.Isar { ); } -class _FakeCollectionSchema_8 extends _i1.SmartFake - implements _i4.CollectionSchema { - _FakeCollectionSchema_8( +class _FakeIsar_8 extends _i1.SmartFake implements _i5.Isar { + _FakeIsar_8( Object parent, Invocation parentInvocation, ) : super( @@ -115,9 +118,9 @@ class _FakeCollectionSchema_8 extends _i1.SmartFake ); } -class _FakeQueryBuilder_9 extends _i1.SmartFake - implements _i4.QueryBuilder { - _FakeQueryBuilder_9( +class _FakeCollectionSchema_9 extends _i1.SmartFake + implements _i5.CollectionSchema { + _FakeCollectionSchema_9( Object parent, Invocation parentInvocation, ) : super( @@ -126,8 +129,19 @@ class _FakeQueryBuilder_9 extends _i1.SmartFake ); } -class _FakeQuery_10 extends _i1.SmartFake implements _i4.Query { - _FakeQuery_10( +class _FakeQueryBuilder_10 extends _i1.SmartFake + implements _i5.QueryBuilder { + _FakeQueryBuilder_10( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeQuery_11 extends _i1.SmartFake implements _i5.Query { + _FakeQuery_11( Object parent, Invocation parentInvocation, ) : super( @@ -153,6 +167,15 @@ class MockHub extends _i1.Mock implements _i2.Hub { ), ) as _i2.SentryOptions); + @override + _i3.MetricsApi get metricsApi => (super.noSuchMethod( + Invocation.getter(#metricsApi), + returnValue: _FakeMetricsApi_1( + this, + Invocation.getter(#metricsApi), + ), + ) as _i3.MetricsApi); + @override bool get isEnabled => (super.noSuchMethod( Invocation.getter(#isEnabled), @@ -162,7 +185,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { @override _i2.SentryId get lastEventId => (super.noSuchMethod( Invocation.getter(#lastEventId), - returnValue: _FakeSentryId_1( + returnValue: _FakeSentryId_2( this, Invocation.getter(#lastEventId), ), @@ -171,14 +194,14 @@ class MockHub extends _i1.Mock implements _i2.Hub { @override _i2.Scope get scope => (super.noSuchMethod( Invocation.getter(#scope), - returnValue: _FakeScope_2( + returnValue: _FakeScope_3( this, Invocation.getter(#scope), ), ) as _i2.Scope); @override - set profilerFactory(_i5.SentryProfilerFactory? value) => super.noSuchMethod( + set profilerFactory(_i6.SentryProfilerFactory? value) => super.noSuchMethod( Invocation.setter( #profilerFactory, value, @@ -187,7 +210,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { ); @override - _i3.Future<_i2.SentryId> captureEvent( + _i4.Future<_i2.SentryId> captureEvent( _i2.SentryEvent? event, { dynamic stackTrace, _i2.Hint? hint, @@ -203,7 +226,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #withScope: withScope, }, ), - returnValue: _i3.Future<_i2.SentryId>.value(_FakeSentryId_1( + returnValue: _i4.Future<_i2.SentryId>.value(_FakeSentryId_2( this, Invocation.method( #captureEvent, @@ -215,10 +238,10 @@ class MockHub extends _i1.Mock implements _i2.Hub { }, ), )), - ) as _i3.Future<_i2.SentryId>); + ) as _i4.Future<_i2.SentryId>); @override - _i3.Future<_i2.SentryId> captureException( + _i4.Future<_i2.SentryId> captureException( dynamic throwable, { dynamic stackTrace, _i2.Hint? hint, @@ -234,7 +257,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #withScope: withScope, }, ), - returnValue: _i3.Future<_i2.SentryId>.value(_FakeSentryId_1( + returnValue: _i4.Future<_i2.SentryId>.value(_FakeSentryId_2( this, Invocation.method( #captureException, @@ -246,10 +269,10 @@ class MockHub extends _i1.Mock implements _i2.Hub { }, ), )), - ) as _i3.Future<_i2.SentryId>); + ) as _i4.Future<_i2.SentryId>); @override - _i3.Future<_i2.SentryId> captureMessage( + _i4.Future<_i2.SentryId> captureMessage( String? message, { _i2.SentryLevel? level, String? template, @@ -269,7 +292,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #withScope: withScope, }, ), - returnValue: _i3.Future<_i2.SentryId>.value(_FakeSentryId_1( + returnValue: _i4.Future<_i2.SentryId>.value(_FakeSentryId_2( this, Invocation.method( #captureMessage, @@ -283,22 +306,49 @@ class MockHub extends _i1.Mock implements _i2.Hub { }, ), )), - ) as _i3.Future<_i2.SentryId>); + ) as _i4.Future<_i2.SentryId>); @override - // ignore: deprecated_member_use - _i3.Future captureUserFeedback(_i2.SentryUserFeedback? userFeedback) => + _i4.Future captureUserFeedback(_i2.SentryUserFeedback? userFeedback) => (super.noSuchMethod( Invocation.method( #captureUserFeedback, [userFeedback], ), - returnValue: _i3.Future.value(), - returnValueForMissingStub: _i3.Future.value(), - ) as _i3.Future); + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); + + @override + _i4.Future<_i2.SentryId> captureFeedback( + _i2.SentryFeedback? feedback, { + _i2.Hint? hint, + _i2.ScopeCallback? withScope, + }) => + (super.noSuchMethod( + Invocation.method( + #captureFeedback, + [feedback], + { + #hint: hint, + #withScope: withScope, + }, + ), + returnValue: _i4.Future<_i2.SentryId>.value(_FakeSentryId_2( + this, + Invocation.method( + #captureFeedback, + [feedback], + { + #hint: hint, + #withScope: withScope, + }, + ), + )), + ) as _i4.Future<_i2.SentryId>); @override - _i3.Future addBreadcrumb( + _i4.Future addBreadcrumb( _i2.Breadcrumb? crumb, { _i2.Hint? hint, }) => @@ -308,9 +358,9 @@ class MockHub extends _i1.Mock implements _i2.Hub { [crumb], {#hint: hint}, ), - returnValue: _i3.Future.value(), - returnValueForMissingStub: _i3.Future.value(), - ) as _i3.Future); + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); @override void bindClient(_i2.SentryClient? client) => super.noSuchMethod( @@ -327,7 +377,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #clone, [], ), - returnValue: _FakeHub_3( + returnValue: _FakeHub_4( this, Invocation.method( #clone, @@ -337,21 +387,21 @@ class MockHub extends _i1.Mock implements _i2.Hub { ) as _i2.Hub); @override - _i3.Future close() => (super.noSuchMethod( + _i4.Future close() => (super.noSuchMethod( Invocation.method( #close, [], ), - returnValue: _i3.Future.value(), - returnValueForMissingStub: _i3.Future.value(), - ) as _i3.Future); + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); @override - _i3.FutureOr configureScope(_i2.ScopeCallback? callback) => + _i4.FutureOr configureScope(_i2.ScopeCallback? callback) => (super.noSuchMethod(Invocation.method( #configureScope, [callback], - )) as _i3.FutureOr); + )) as _i4.FutureOr); @override _i2.ISentrySpan startTransaction( @@ -384,7 +434,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #customSamplingContext: customSamplingContext, }, ), - returnValue: _FakeISentrySpan_4( + returnValue: _FakeISentrySpan_5( this, Invocation.method( #startTransaction, @@ -431,7 +481,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #onFinish: onFinish, }, ), - returnValue: _FakeISentrySpan_4( + returnValue: _FakeISentrySpan_5( this, Invocation.method( #startTransactionWithContext, @@ -450,25 +500,49 @@ class MockHub extends _i1.Mock implements _i2.Hub { ) as _i2.ISentrySpan); @override - _i3.Future<_i2.SentryId> captureTransaction( + _i4.Future<_i2.SentryId> captureTransaction( _i2.SentryTransaction? transaction, { _i2.SentryTraceContextHeader? traceContext, + _i2.Hint? hint, }) => (super.noSuchMethod( Invocation.method( #captureTransaction, [transaction], - {#traceContext: traceContext}, + { + #traceContext: traceContext, + #hint: hint, + }, ), - returnValue: _i3.Future<_i2.SentryId>.value(_FakeSentryId_1( + returnValue: _i4.Future<_i2.SentryId>.value(_FakeSentryId_2( this, Invocation.method( #captureTransaction, [transaction], - {#traceContext: traceContext}, + { + #traceContext: traceContext, + #hint: hint, + }, ), )), - ) as _i3.Future<_i2.SentryId>); + ) as _i4.Future<_i2.SentryId>); + + @override + _i4.Future<_i2.SentryId> captureMetrics( + Map>? metricsBuckets) => + (super.noSuchMethod( + Invocation.method( + #captureMetrics, + [metricsBuckets], + ), + returnValue: _i4.Future<_i2.SentryId>.value(_FakeSentryId_2( + this, + Invocation.method( + #captureMetrics, + [metricsBuckets], + ), + )), + ) as _i4.Future<_i2.SentryId>); @override void setSpanContext( @@ -492,7 +566,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { /// A class which mocks [Isar]. /// /// See the documentation for Mockito's code generation for more information. -class MockIsar extends _i1.Mock implements _i4.Isar { +class MockIsar extends _i1.Mock implements _i5.Isar { MockIsar() { _i1.throwOnMissingStub(this); } @@ -500,7 +574,10 @@ class MockIsar extends _i1.Mock implements _i4.Isar { @override String get name => (super.noSuchMethod( Invocation.getter(#name), - returnValue: '', + returnValue: _i8.dummyValue( + this, + Invocation.getter(#name), + ), ) as String); @override @@ -519,34 +596,34 @@ class MockIsar extends _i1.Mock implements _i4.Isar { ); @override - _i3.Future txn(_i3.Future Function()? callback) => + _i4.Future txn(_i4.Future Function()? callback) => (super.noSuchMethod( Invocation.method( #txn, [callback], ), - returnValue: _i6.ifNotNull( - _i6.dummyValueOrNull( + returnValue: _i8.ifNotNull( + _i8.dummyValueOrNull( this, Invocation.method( #txn, [callback], ), ), - (T v) => _i3.Future.value(v), + (T v) => _i4.Future.value(v), ) ?? - _FakeFuture_5( + _FakeFuture_6( this, Invocation.method( #txn, [callback], ), ), - ) as _i3.Future); + ) as _i4.Future); @override - _i3.Future writeTxn( - _i3.Future Function()? callback, { + _i4.Future writeTxn( + _i4.Future Function()? callback, { bool? silent = false, }) => (super.noSuchMethod( @@ -555,8 +632,8 @@ class MockIsar extends _i1.Mock implements _i4.Isar { [callback], {#silent: silent}, ), - returnValue: _i6.ifNotNull( - _i6.dummyValueOrNull( + returnValue: _i8.ifNotNull( + _i8.dummyValueOrNull( this, Invocation.method( #writeTxn, @@ -564,9 +641,9 @@ class MockIsar extends _i1.Mock implements _i4.Isar { {#silent: silent}, ), ), - (T v) => _i3.Future.value(v), + (T v) => _i4.Future.value(v), ) ?? - _FakeFuture_5( + _FakeFuture_6( this, Invocation.method( #writeTxn, @@ -574,7 +651,7 @@ class MockIsar extends _i1.Mock implements _i4.Isar { {#silent: silent}, ), ), - ) as _i3.Future); + ) as _i4.Future); @override T txnSync(T Function()? callback) => (super.noSuchMethod( @@ -582,7 +659,7 @@ class MockIsar extends _i1.Mock implements _i4.Isar { #txnSync, [callback], ), - returnValue: _i6.dummyValue( + returnValue: _i8.dummyValue( this, Invocation.method( #txnSync, @@ -602,7 +679,7 @@ class MockIsar extends _i1.Mock implements _i4.Isar { [callback], {#silent: silent}, ), - returnValue: _i6.dummyValue( + returnValue: _i8.dummyValue( this, Invocation.method( #writeTxnSync, @@ -613,7 +690,7 @@ class MockIsar extends _i1.Mock implements _i4.Isar { ) as T); @override - void attachCollections(Map>? collections) => + void attachCollections(Map>? collections) => super.noSuchMethod( Invocation.method( #attachCollections, @@ -623,36 +700,36 @@ class MockIsar extends _i1.Mock implements _i4.Isar { ); @override - _i4.IsarCollection collection() => (super.noSuchMethod( + _i5.IsarCollection collection() => (super.noSuchMethod( Invocation.method( #collection, [], ), - returnValue: _FakeIsarCollection_6( + returnValue: _FakeIsarCollection_7( this, Invocation.method( #collection, [], ), ), - ) as _i4.IsarCollection); + ) as _i5.IsarCollection); @override - _i4.IsarCollection? getCollectionByNameInternal(String? name) => + _i5.IsarCollection? getCollectionByNameInternal(String? name) => (super.noSuchMethod(Invocation.method( #getCollectionByNameInternal, [name], - )) as _i4.IsarCollection?); + )) as _i5.IsarCollection?); @override - _i3.Future clear() => (super.noSuchMethod( + _i4.Future clear() => (super.noSuchMethod( Invocation.method( #clear, [], ), - returnValue: _i3.Future.value(), - returnValueForMissingStub: _i3.Future.value(), - ) as _i3.Future); + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); @override void clearSync() => super.noSuchMethod( @@ -664,7 +741,7 @@ class MockIsar extends _i1.Mock implements _i4.Isar { ); @override - _i3.Future getSize({ + _i4.Future getSize({ bool? includeIndexes = false, bool? includeLinks = false, }) => @@ -677,8 +754,8 @@ class MockIsar extends _i1.Mock implements _i4.Isar { #includeLinks: includeLinks, }, ), - returnValue: _i3.Future.value(0), - ) as _i3.Future); + returnValue: _i4.Future.value(0), + ) as _i4.Future); @override int getSizeSync({ @@ -698,77 +775,80 @@ class MockIsar extends _i1.Mock implements _i4.Isar { ) as int); @override - _i3.Future copyToFile(String? targetPath) => (super.noSuchMethod( + _i4.Future copyToFile(String? targetPath) => (super.noSuchMethod( Invocation.method( #copyToFile, [targetPath], ), - returnValue: _i3.Future.value(), - returnValueForMissingStub: _i3.Future.value(), - ) as _i3.Future); + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); @override - _i3.Future close({bool? deleteFromDisk = false}) => (super.noSuchMethod( + _i4.Future close({bool? deleteFromDisk = false}) => (super.noSuchMethod( Invocation.method( #close, [], {#deleteFromDisk: deleteFromDisk}, ), - returnValue: _i3.Future.value(false), - ) as _i3.Future); + returnValue: _i4.Future.value(false), + ) as _i4.Future); @override - _i3.Future verify() => (super.noSuchMethod( + _i4.Future verify() => (super.noSuchMethod( Invocation.method( #verify, [], ), - returnValue: _i3.Future.value(), - returnValueForMissingStub: _i3.Future.value(), - ) as _i3.Future); + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); } /// A class which mocks [IsarCollection]. /// /// See the documentation for Mockito's code generation for more information. class MockIsarCollection extends _i1.Mock - implements _i4.IsarCollection { + implements _i5.IsarCollection { MockIsarCollection() { _i1.throwOnMissingStub(this); } @override - _i4.Isar get isar => (super.noSuchMethod( + _i5.Isar get isar => (super.noSuchMethod( Invocation.getter(#isar), - returnValue: _FakeIsar_7( + returnValue: _FakeIsar_8( this, Invocation.getter(#isar), ), - ) as _i4.Isar); + ) as _i5.Isar); @override - _i4.CollectionSchema get schema => (super.noSuchMethod( + _i5.CollectionSchema get schema => (super.noSuchMethod( Invocation.getter(#schema), - returnValue: _FakeCollectionSchema_8( + returnValue: _FakeCollectionSchema_9( this, Invocation.getter(#schema), ), - ) as _i4.CollectionSchema); + ) as _i5.CollectionSchema); @override String get name => (super.noSuchMethod( Invocation.getter(#name), - returnValue: '', + returnValue: _i8.dummyValue( + this, + Invocation.getter(#name), + ), ) as String); @override - _i3.Future get(int? id) => (super.noSuchMethod( + _i4.Future get(int? id) => (super.noSuchMethod( Invocation.method( #get, [id], ), - returnValue: _i3.Future.value(), - ) as _i3.Future); + returnValue: _i4.Future.value(), + ) as _i4.Future); @override OBJ? getSync(int? id) => (super.noSuchMethod(Invocation.method( @@ -777,13 +857,13 @@ class MockIsarCollection extends _i1.Mock )) as OBJ?); @override - _i3.Future> getAll(List? ids) => (super.noSuchMethod( + _i4.Future> getAll(List? ids) => (super.noSuchMethod( Invocation.method( #getAll, [ids], ), - returnValue: _i3.Future>.value([]), - ) as _i3.Future>); + returnValue: _i4.Future>.value([]), + ) as _i4.Future>); @override List getAllSync(List? ids) => (super.noSuchMethod( @@ -795,7 +875,7 @@ class MockIsarCollection extends _i1.Mock ) as List); @override - _i3.Future getByIndex( + _i4.Future getByIndex( String? indexName, List? key, ) => @@ -807,8 +887,8 @@ class MockIsarCollection extends _i1.Mock key, ], ), - returnValue: _i3.Future.value(), - ) as _i3.Future); + returnValue: _i4.Future.value(), + ) as _i4.Future); @override OBJ? getByIndexSync( @@ -824,7 +904,7 @@ class MockIsarCollection extends _i1.Mock )) as OBJ?); @override - _i3.Future> getAllByIndex( + _i4.Future> getAllByIndex( String? indexName, List>? keys, ) => @@ -836,8 +916,8 @@ class MockIsarCollection extends _i1.Mock keys, ], ), - returnValue: _i3.Future>.value([]), - ) as _i3.Future>); + returnValue: _i4.Future>.value([]), + ) as _i4.Future>); @override List getAllByIndexSync( @@ -856,13 +936,13 @@ class MockIsarCollection extends _i1.Mock ) as List); @override - _i3.Future put(OBJ? object) => (super.noSuchMethod( + _i4.Future put(OBJ? object) => (super.noSuchMethod( Invocation.method( #put, [object], ), - returnValue: _i3.Future.value(0), - ) as _i3.Future); + returnValue: _i4.Future.value(0), + ) as _i4.Future); @override int putSync( @@ -879,13 +959,13 @@ class MockIsarCollection extends _i1.Mock ) as int); @override - _i3.Future> putAll(List? objects) => (super.noSuchMethod( + _i4.Future> putAll(List? objects) => (super.noSuchMethod( Invocation.method( #putAll, [objects], ), - returnValue: _i3.Future>.value([]), - ) as _i3.Future>); + returnValue: _i4.Future>.value([]), + ) as _i4.Future>); @override List putAllSync( @@ -902,7 +982,7 @@ class MockIsarCollection extends _i1.Mock ) as List); @override - _i3.Future putByIndex( + _i4.Future putByIndex( String? indexName, OBJ? object, ) => @@ -914,8 +994,8 @@ class MockIsarCollection extends _i1.Mock object, ], ), - returnValue: _i3.Future.value(0), - ) as _i3.Future); + returnValue: _i4.Future.value(0), + ) as _i4.Future); @override int putByIndexSync( @@ -936,7 +1016,7 @@ class MockIsarCollection extends _i1.Mock ) as int); @override - _i3.Future> putAllByIndex( + _i4.Future> putAllByIndex( String? indexName, List? objects, ) => @@ -948,8 +1028,8 @@ class MockIsarCollection extends _i1.Mock objects, ], ), - returnValue: _i3.Future>.value([]), - ) as _i3.Future>); + returnValue: _i4.Future>.value([]), + ) as _i4.Future>); @override List putAllByIndexSync( @@ -970,13 +1050,13 @@ class MockIsarCollection extends _i1.Mock ) as List); @override - _i3.Future delete(int? id) => (super.noSuchMethod( + _i4.Future delete(int? id) => (super.noSuchMethod( Invocation.method( #delete, [id], ), - returnValue: _i3.Future.value(false), - ) as _i3.Future); + returnValue: _i4.Future.value(false), + ) as _i4.Future); @override bool deleteSync(int? id) => (super.noSuchMethod( @@ -988,13 +1068,13 @@ class MockIsarCollection extends _i1.Mock ) as bool); @override - _i3.Future deleteAll(List? ids) => (super.noSuchMethod( + _i4.Future deleteAll(List? ids) => (super.noSuchMethod( Invocation.method( #deleteAll, [ids], ), - returnValue: _i3.Future.value(0), - ) as _i3.Future); + returnValue: _i4.Future.value(0), + ) as _i4.Future); @override int deleteAllSync(List? ids) => (super.noSuchMethod( @@ -1006,7 +1086,7 @@ class MockIsarCollection extends _i1.Mock ) as int); @override - _i3.Future deleteByIndex( + _i4.Future deleteByIndex( String? indexName, List? key, ) => @@ -1018,8 +1098,8 @@ class MockIsarCollection extends _i1.Mock key, ], ), - returnValue: _i3.Future.value(false), - ) as _i3.Future); + returnValue: _i4.Future.value(false), + ) as _i4.Future); @override bool deleteByIndexSync( @@ -1038,7 +1118,7 @@ class MockIsarCollection extends _i1.Mock ) as bool); @override - _i3.Future deleteAllByIndex( + _i4.Future deleteAllByIndex( String? indexName, List>? keys, ) => @@ -1050,8 +1130,8 @@ class MockIsarCollection extends _i1.Mock keys, ], ), - returnValue: _i3.Future.value(0), - ) as _i3.Future); + returnValue: _i4.Future.value(0), + ) as _i4.Future); @override int deleteAllByIndexSync( @@ -1070,14 +1150,14 @@ class MockIsarCollection extends _i1.Mock ) as int); @override - _i3.Future clear() => (super.noSuchMethod( + _i4.Future clear() => (super.noSuchMethod( Invocation.method( #clear, [], ), - returnValue: _i3.Future.value(), - returnValueForMissingStub: _i3.Future.value(), - ) as _i3.Future); + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); @override void clearSync() => super.noSuchMethod( @@ -1089,18 +1169,18 @@ class MockIsarCollection extends _i1.Mock ); @override - _i3.Future importJsonRaw(_i7.Uint8List? jsonBytes) => + _i4.Future importJsonRaw(_i9.Uint8List? jsonBytes) => (super.noSuchMethod( Invocation.method( #importJsonRaw, [jsonBytes], ), - returnValue: _i3.Future.value(), - returnValueForMissingStub: _i3.Future.value(), - ) as _i3.Future); + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); @override - void importJsonRawSync(_i7.Uint8List? jsonBytes) => super.noSuchMethod( + void importJsonRawSync(_i9.Uint8List? jsonBytes) => super.noSuchMethod( Invocation.method( #importJsonRawSync, [jsonBytes], @@ -1109,15 +1189,15 @@ class MockIsarCollection extends _i1.Mock ); @override - _i3.Future importJson(List>? json) => + _i4.Future importJson(List>? json) => (super.noSuchMethod( Invocation.method( #importJson, [json], ), - returnValue: _i3.Future.value(), - returnValueForMissingStub: _i3.Future.value(), - ) as _i3.Future); + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); @override void importJsonSync(List>? json) => super.noSuchMethod( @@ -1129,9 +1209,9 @@ class MockIsarCollection extends _i1.Mock ); @override - _i4.QueryBuilder where({ + _i5.QueryBuilder where({ bool? distinct = false, - _i4.Sort? sort = _i4.Sort.asc, + _i5.Sort? sort = _i5.Sort.asc, }) => (super.noSuchMethod( Invocation.method( @@ -1142,7 +1222,7 @@ class MockIsarCollection extends _i1.Mock #sort: sort, }, ), - returnValue: _FakeQueryBuilder_9( + returnValue: _FakeQueryBuilder_10( this, Invocation.method( #where, @@ -1153,32 +1233,32 @@ class MockIsarCollection extends _i1.Mock }, ), ), - ) as _i4.QueryBuilder); + ) as _i5.QueryBuilder); @override - _i4.QueryBuilder filter() => + _i5.QueryBuilder filter() => (super.noSuchMethod( Invocation.method( #filter, [], ), - returnValue: _FakeQueryBuilder_9( + returnValue: _FakeQueryBuilder_10( this, Invocation.method( #filter, [], ), ), - ) as _i4.QueryBuilder); + ) as _i5.QueryBuilder); @override - _i4.Query buildQuery({ - List<_i4.WhereClause>? whereClauses = const [], + _i5.Query buildQuery({ + List<_i5.WhereClause>? whereClauses = const [], bool? whereDistinct = false, - _i4.Sort? whereSort = _i4.Sort.asc, - _i4.FilterOperation? filter, - List<_i4.SortProperty>? sortBy = const [], - List<_i4.DistinctProperty>? distinctBy = const [], + _i5.Sort? whereSort = _i5.Sort.asc, + _i5.FilterOperation? filter, + List<_i5.SortProperty>? sortBy = const [], + List<_i5.DistinctProperty>? distinctBy = const [], int? offset, int? limit, String? property, @@ -1199,7 +1279,7 @@ class MockIsarCollection extends _i1.Mock #property: property, }, ), - returnValue: _FakeQuery_10( + returnValue: _FakeQuery_11( this, Invocation.method( #buildQuery, @@ -1217,16 +1297,16 @@ class MockIsarCollection extends _i1.Mock }, ), ), - ) as _i4.Query); + ) as _i5.Query); @override - _i3.Future count() => (super.noSuchMethod( + _i4.Future count() => (super.noSuchMethod( Invocation.method( #count, [], ), - returnValue: _i3.Future.value(0), - ) as _i3.Future); + returnValue: _i4.Future.value(0), + ) as _i4.Future); @override int countSync() => (super.noSuchMethod( @@ -1238,7 +1318,7 @@ class MockIsarCollection extends _i1.Mock ) as int); @override - _i3.Future getSize({ + _i4.Future getSize({ bool? includeIndexes = false, bool? includeLinks = false, }) => @@ -1251,8 +1331,8 @@ class MockIsarCollection extends _i1.Mock #includeLinks: includeLinks, }, ), - returnValue: _i3.Future.value(0), - ) as _i3.Future); + returnValue: _i4.Future.value(0), + ) as _i4.Future); @override int getSizeSync({ @@ -1272,18 +1352,18 @@ class MockIsarCollection extends _i1.Mock ) as int); @override - _i3.Stream watchLazy({bool? fireImmediately = false}) => + _i4.Stream watchLazy({bool? fireImmediately = false}) => (super.noSuchMethod( Invocation.method( #watchLazy, [], {#fireImmediately: fireImmediately}, ), - returnValue: _i3.Stream.empty(), - ) as _i3.Stream); + returnValue: _i4.Stream.empty(), + ) as _i4.Stream); @override - _i3.Stream watchObject( + _i4.Stream watchObject( int? id, { bool? fireImmediately = false, }) => @@ -1293,11 +1373,11 @@ class MockIsarCollection extends _i1.Mock [id], {#fireImmediately: fireImmediately}, ), - returnValue: _i3.Stream.empty(), - ) as _i3.Stream); + returnValue: _i4.Stream.empty(), + ) as _i4.Stream); @override - _i3.Stream watchObjectLazy( + _i4.Stream watchObjectLazy( int? id, { bool? fireImmediately = false, }) => @@ -1307,21 +1387,21 @@ class MockIsarCollection extends _i1.Mock [id], {#fireImmediately: fireImmediately}, ), - returnValue: _i3.Stream.empty(), - ) as _i3.Stream); + returnValue: _i4.Stream.empty(), + ) as _i4.Stream); @override - _i3.Future verify(List? objects) => (super.noSuchMethod( + _i4.Future verify(List? objects) => (super.noSuchMethod( Invocation.method( #verify, [objects], ), - returnValue: _i3.Future.value(), - returnValueForMissingStub: _i3.Future.value(), - ) as _i3.Future); + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); @override - _i3.Future verifyLink( + _i4.Future verifyLink( String? linkName, List? sourceIds, List? targetIds, @@ -1335,7 +1415,7 @@ class MockIsarCollection extends _i1.Mock targetIds, ], ), - returnValue: _i3.Future.value(), - returnValueForMissingStub: _i3.Future.value(), - ) as _i3.Future); + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); } From b417e98bbb88ef16361d3de9008aba59a1d8d552 Mon Sep 17 00:00:00 2001 From: Martin Haintz Date: Tue, 19 Nov 2024 12:57:59 +0100 Subject: [PATCH 12/25] update sqflite mocks --- sqflite/test/mocks/mocks.mocks.dart | 315 ++++++++++++++++++++++++---- 1 file changed, 279 insertions(+), 36 deletions(-) diff --git a/sqflite/test/mocks/mocks.mocks.dart b/sqflite/test/mocks/mocks.mocks.dart index 11300b2dff..7626a8a13f 100644 --- a/sqflite/test/mocks/mocks.mocks.dart +++ b/sqflite/test/mocks/mocks.mocks.dart @@ -1,4 +1,4 @@ -// Mocks generated by Mockito 5.4.2 from annotations +// Mocks generated by Mockito 5.4.4 from annotations // in sentry_sqflite/test/mocks/mocks.dart. // Do not manually edit this file. @@ -8,16 +8,21 @@ import 'dart:async' as _i4; import 'package:mockito/mockito.dart' as _i1; import 'package:mockito/src/dummies.dart' as _i7; import 'package:sentry/sentry.dart' as _i2; -import 'package:sentry/src/sentry_tracer.dart' as _i5; -import 'package:sqflite_common/sql.dart' as _i6; +import 'package:sentry/src/metrics/metric.dart' as _i11; +import 'package:sentry/src/metrics/metrics_api.dart' as _i5; +import 'package:sentry/src/profiling.dart' as _i8; +import 'package:sentry/src/sentry_tracer.dart' as _i6; +import 'package:sqflite_common/sql.dart' as _i9; import 'package:sqflite_common/sqlite_api.dart' as _i3; -import 'mocks.dart' as _i8; +import 'mocks.dart' as _i10; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values // ignore_for_file: avoid_setters_without_getters // ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package // ignore_for_file: implementation_imports // ignore_for_file: invalid_use_of_visible_for_testing_member // ignore_for_file: prefer_const_constructors @@ -117,8 +122,8 @@ class _FakeSentryOptions_8 extends _i1.SmartFake implements _i2.SentryOptions { ); } -class _FakeSentryId_9 extends _i1.SmartFake implements _i2.SentryId { - _FakeSentryId_9( +class _FakeMetricsApi_9 extends _i1.SmartFake implements _i5.MetricsApi { + _FakeMetricsApi_9( Object parent, Invocation parentInvocation, ) : super( @@ -127,8 +132,8 @@ class _FakeSentryId_9 extends _i1.SmartFake implements _i2.SentryId { ); } -class _FakeScope_10 extends _i1.SmartFake implements _i2.Scope { - _FakeScope_10( +class _FakeSentryId_10 extends _i1.SmartFake implements _i2.SentryId { + _FakeSentryId_10( Object parent, Invocation parentInvocation, ) : super( @@ -137,8 +142,18 @@ class _FakeScope_10 extends _i1.SmartFake implements _i2.Scope { ); } -class _FakeHub_11 extends _i1.SmartFake implements _i2.Hub { - _FakeHub_11( +class _FakeScope_11 extends _i1.SmartFake implements _i2.Scope { + _FakeScope_11( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeHub_12 extends _i1.SmartFake implements _i2.Hub { + _FakeHub_12( Object parent, Invocation parentInvocation, ) : super( @@ -150,8 +165,7 @@ class _FakeHub_11 extends _i1.SmartFake implements _i2.Hub { /// A class which mocks [SentryTracer]. /// /// See the documentation for Mockito's code generation for more information. -// ignore: invalid_use_of_internal_member -class MockSentryTracer extends _i1.Mock implements _i5.SentryTracer { +class MockSentryTracer extends _i1.Mock implements _i6.SentryTracer { MockSentryTracer() { _i1.throwOnMissingStub(this); } @@ -159,8 +173,12 @@ class MockSentryTracer extends _i1.Mock implements _i5.SentryTracer { @override String get name => (super.noSuchMethod( Invocation.getter(#name), - returnValue: '', + returnValue: _i7.dummyValue( + this, + Invocation.getter(#name), + ), ) as String); + @override set name(String? _name) => super.noSuchMethod( Invocation.setter( @@ -169,12 +187,14 @@ class MockSentryTracer extends _i1.Mock implements _i5.SentryTracer { ), returnValueForMissingStub: null, ); + @override _i2.SentryTransactionNameSource get transactionNameSource => (super.noSuchMethod( Invocation.getter(#transactionNameSource), returnValue: _i2.SentryTransactionNameSource.custom, ) as _i2.SentryTransactionNameSource); + @override set transactionNameSource( _i2.SentryTransactionNameSource? _transactionNameSource) => @@ -185,6 +205,40 @@ class MockSentryTracer extends _i1.Mock implements _i5.SentryTracer { ), returnValueForMissingStub: null, ); + + @override + set profiler(_i8.SentryProfiler? _profiler) => super.noSuchMethod( + Invocation.setter( + #profiler, + _profiler, + ), + returnValueForMissingStub: null, + ); + + @override + set profileInfo(_i8.SentryProfileInfo? _profileInfo) => super.noSuchMethod( + Invocation.setter( + #profileInfo, + _profileInfo, + ), + returnValueForMissingStub: null, + ); + + @override + Map get measurements => (super.noSuchMethod( + Invocation.getter(#measurements), + returnValue: {}, + ) as Map); + + @override + set hint(_i2.Hint? hint) => super.noSuchMethod( + Invocation.setter( + #hint, + hint, + ), + returnValueForMissingStub: null, + ); + @override _i2.SentrySpanContext get context => (super.noSuchMethod( Invocation.getter(#context), @@ -193,6 +247,7 @@ class MockSentryTracer extends _i1.Mock implements _i5.SentryTracer { Invocation.getter(#context), ), ) as _i2.SentrySpanContext); + @override set origin(String? origin) => super.noSuchMethod( Invocation.setter( @@ -201,6 +256,7 @@ class MockSentryTracer extends _i1.Mock implements _i5.SentryTracer { ), returnValueForMissingStub: null, ); + @override DateTime get startTimestamp => (super.noSuchMethod( Invocation.getter(#startTimestamp), @@ -209,21 +265,25 @@ class MockSentryTracer extends _i1.Mock implements _i5.SentryTracer { Invocation.getter(#startTimestamp), ), ) as DateTime); + @override Map get data => (super.noSuchMethod( Invocation.getter(#data), returnValue: {}, ) as Map); + @override bool get finished => (super.noSuchMethod( Invocation.getter(#finished), returnValue: false, ) as bool); + @override List<_i2.SentrySpan> get children => (super.noSuchMethod( Invocation.getter(#children), returnValue: <_i2.SentrySpan>[], ) as List<_i2.SentrySpan>); + @override set throwable(dynamic throwable) => super.noSuchMethod( Invocation.setter( @@ -232,6 +292,7 @@ class MockSentryTracer extends _i1.Mock implements _i5.SentryTracer { ), returnValueForMissingStub: null, ); + @override set status(_i2.SpanStatus? status) => super.noSuchMethod( Invocation.setter( @@ -240,20 +301,18 @@ class MockSentryTracer extends _i1.Mock implements _i5.SentryTracer { ), returnValueForMissingStub: null, ); + @override Map get tags => (super.noSuchMethod( Invocation.getter(#tags), returnValue: {}, ) as Map); - @override - Map get measurements => (super.noSuchMethod( - Invocation.getter(#measurements), - returnValue: {}, - ) as Map); + @override _i4.Future finish({ _i2.SpanStatus? status, DateTime? endTimestamp, + _i2.Hint? hint, }) => (super.noSuchMethod( Invocation.method( @@ -262,11 +321,13 @@ class MockSentryTracer extends _i1.Mock implements _i5.SentryTracer { { #status: status, #endTimestamp: endTimestamp, + #hint: hint, }, ), returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override void removeData(String? key) => super.noSuchMethod( Invocation.method( @@ -275,6 +336,7 @@ class MockSentryTracer extends _i1.Mock implements _i5.SentryTracer { ), returnValueForMissingStub: null, ); + @override void removeTag(String? key) => super.noSuchMethod( Invocation.method( @@ -283,6 +345,7 @@ class MockSentryTracer extends _i1.Mock implements _i5.SentryTracer { ), returnValueForMissingStub: null, ); + @override void setData( String? key, @@ -298,6 +361,7 @@ class MockSentryTracer extends _i1.Mock implements _i5.SentryTracer { ), returnValueForMissingStub: null, ); + @override void setTag( String? key, @@ -313,6 +377,7 @@ class MockSentryTracer extends _i1.Mock implements _i5.SentryTracer { ), returnValueForMissingStub: null, ); + @override _i2.ISentrySpan startChild( String? operation, { @@ -340,6 +405,7 @@ class MockSentryTracer extends _i1.Mock implements _i5.SentryTracer { ), ), ) as _i2.ISentrySpan); + @override _i2.ISentrySpan startChildWithParentSpanId( _i2.SpanId? parentSpanId, @@ -374,6 +440,7 @@ class MockSentryTracer extends _i1.Mock implements _i5.SentryTracer { ), ), ) as _i2.ISentrySpan); + @override _i2.SentryTraceHeader toSentryTrace() => (super.noSuchMethod( Invocation.method( @@ -388,6 +455,7 @@ class MockSentryTracer extends _i1.Mock implements _i5.SentryTracer { ), ), ) as _i2.SentryTraceHeader); + @override void setMeasurement( String? name, @@ -405,6 +473,25 @@ class MockSentryTracer extends _i1.Mock implements _i5.SentryTracer { ), returnValueForMissingStub: null, ); + + @override + void setMeasurementFromChild( + String? name, + num? value, { + _i2.SentryMeasurementUnit? unit, + }) => + super.noSuchMethod( + Invocation.method( + #setMeasurementFromChild, + [ + name, + value, + ], + {#unit: unit}, + ), + returnValueForMissingStub: null, + ); + @override void scheduleFinish() => super.noSuchMethod( Invocation.method( @@ -428,6 +515,7 @@ class MockBatch extends _i1.Mock implements _i3.Batch { Invocation.getter(#length), returnValue: 0, ) as int); + @override _i4.Future> commit({ bool? exclusive, @@ -446,6 +534,7 @@ class MockBatch extends _i1.Mock implements _i3.Batch { ), returnValue: _i4.Future>.value([]), ) as _i4.Future>); + @override _i4.Future> apply({ bool? noResult, @@ -462,6 +551,7 @@ class MockBatch extends _i1.Mock implements _i3.Batch { ), returnValue: _i4.Future>.value([]), ) as _i4.Future>); + @override void rawInsert( String? sql, [ @@ -477,12 +567,13 @@ class MockBatch extends _i1.Mock implements _i3.Batch { ), returnValueForMissingStub: null, ); + @override void insert( String? table, Map? values, { String? nullColumnHack, - _i6.ConflictAlgorithm? conflictAlgorithm, + _i9.ConflictAlgorithm? conflictAlgorithm, }) => super.noSuchMethod( Invocation.method( @@ -498,6 +589,7 @@ class MockBatch extends _i1.Mock implements _i3.Batch { ), returnValueForMissingStub: null, ); + @override void rawUpdate( String? sql, [ @@ -513,13 +605,14 @@ class MockBatch extends _i1.Mock implements _i3.Batch { ), returnValueForMissingStub: null, ); + @override void update( String? table, Map? values, { String? where, List? whereArgs, - _i6.ConflictAlgorithm? conflictAlgorithm, + _i9.ConflictAlgorithm? conflictAlgorithm, }) => super.noSuchMethod( Invocation.method( @@ -536,6 +629,7 @@ class MockBatch extends _i1.Mock implements _i3.Batch { ), returnValueForMissingStub: null, ); + @override void rawDelete( String? sql, [ @@ -551,6 +645,7 @@ class MockBatch extends _i1.Mock implements _i3.Batch { ), returnValueForMissingStub: null, ); + @override void delete( String? table, { @@ -568,6 +663,7 @@ class MockBatch extends _i1.Mock implements _i3.Batch { ), returnValueForMissingStub: null, ); + @override void execute( String? sql, [ @@ -583,6 +679,7 @@ class MockBatch extends _i1.Mock implements _i3.Batch { ), returnValueForMissingStub: null, ); + @override void query( String? table, { @@ -614,6 +711,7 @@ class MockBatch extends _i1.Mock implements _i3.Batch { ), returnValueForMissingStub: null, ); + @override void rawQuery( String? sql, [ @@ -642,13 +740,18 @@ class MockDatabase extends _i1.Mock implements _i3.Database { @override String get path => (super.noSuchMethod( Invocation.getter(#path), - returnValue: '', + returnValue: _i7.dummyValue( + this, + Invocation.getter(#path), + ), ) as String); + @override bool get isOpen => (super.noSuchMethod( Invocation.getter(#isOpen), returnValue: false, ) as bool); + @override _i3.Database get database => (super.noSuchMethod( Invocation.getter(#database), @@ -657,6 +760,7 @@ class MockDatabase extends _i1.Mock implements _i3.Database { Invocation.getter(#database), ), ) as _i3.Database); + @override _i4.Future close() => (super.noSuchMethod( Invocation.method( @@ -666,6 +770,7 @@ class MockDatabase extends _i1.Mock implements _i3.Database { returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override _i4.Future transaction( _i4.Future Function(_i3.Transaction)? action, { @@ -697,6 +802,34 @@ class MockDatabase extends _i1.Mock implements _i3.Database { ), ), ) as _i4.Future); + + @override + _i4.Future readTransaction( + _i4.Future Function(_i3.Transaction)? action) => + (super.noSuchMethod( + Invocation.method( + #readTransaction, + [action], + ), + returnValue: _i7.ifNotNull( + _i7.dummyValueOrNull( + this, + Invocation.method( + #readTransaction, + [action], + ), + ), + (T v) => _i4.Future.value(v), + ) ?? + _FakeFuture_5( + this, + Invocation.method( + #readTransaction, + [action], + ), + ), + ) as _i4.Future); + @override _i4.Future devInvokeMethod( String? method, [ @@ -734,6 +867,7 @@ class MockDatabase extends _i1.Mock implements _i3.Database { ), ), ) as _i4.Future); + @override _i4.Future devInvokeSqlMethod( String? method, @@ -775,6 +909,7 @@ class MockDatabase extends _i1.Mock implements _i3.Database { ), ), ) as _i4.Future); + @override _i4.Future execute( String? sql, [ @@ -791,6 +926,7 @@ class MockDatabase extends _i1.Mock implements _i3.Database { returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override _i4.Future rawInsert( String? sql, [ @@ -806,12 +942,13 @@ class MockDatabase extends _i1.Mock implements _i3.Database { ), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override _i4.Future insert( String? table, Map? values, { String? nullColumnHack, - _i6.ConflictAlgorithm? conflictAlgorithm, + _i9.ConflictAlgorithm? conflictAlgorithm, }) => (super.noSuchMethod( Invocation.method( @@ -827,6 +964,7 @@ class MockDatabase extends _i1.Mock implements _i3.Database { ), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override _i4.Future>> query( String? table, { @@ -859,6 +997,7 @@ class MockDatabase extends _i1.Mock implements _i3.Database { returnValue: _i4.Future>>.value( >[]), ) as _i4.Future>>); + @override _i4.Future>> rawQuery( String? sql, [ @@ -875,6 +1014,7 @@ class MockDatabase extends _i1.Mock implements _i3.Database { returnValue: _i4.Future>>.value( >[]), ) as _i4.Future>>); + @override _i4.Future<_i3.QueryCursor> rawQueryCursor( String? sql, @@ -902,6 +1042,7 @@ class MockDatabase extends _i1.Mock implements _i3.Database { ), )), ) as _i4.Future<_i3.QueryCursor>); + @override _i4.Future<_i3.QueryCursor> queryCursor( String? table, { @@ -953,6 +1094,7 @@ class MockDatabase extends _i1.Mock implements _i3.Database { ), )), ) as _i4.Future<_i3.QueryCursor>); + @override _i4.Future rawUpdate( String? sql, [ @@ -968,13 +1110,14 @@ class MockDatabase extends _i1.Mock implements _i3.Database { ), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override _i4.Future update( String? table, Map? values, { String? where, List? whereArgs, - _i6.ConflictAlgorithm? conflictAlgorithm, + _i9.ConflictAlgorithm? conflictAlgorithm, }) => (super.noSuchMethod( Invocation.method( @@ -991,6 +1134,7 @@ class MockDatabase extends _i1.Mock implements _i3.Database { ), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override _i4.Future rawDelete( String? sql, [ @@ -1006,6 +1150,7 @@ class MockDatabase extends _i1.Mock implements _i3.Database { ), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override _i4.Future delete( String? table, { @@ -1023,6 +1168,7 @@ class MockDatabase extends _i1.Mock implements _i3.Database { ), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override _i3.Batch batch() => (super.noSuchMethod( Invocation.method( @@ -1055,6 +1201,7 @@ class MockDatabaseExecutor extends _i1.Mock implements _i3.DatabaseExecutor { Invocation.getter(#database), ), ) as _i3.Database); + @override _i4.Future execute( String? sql, [ @@ -1071,6 +1218,7 @@ class MockDatabaseExecutor extends _i1.Mock implements _i3.DatabaseExecutor { returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override _i4.Future rawInsert( String? sql, [ @@ -1086,12 +1234,13 @@ class MockDatabaseExecutor extends _i1.Mock implements _i3.DatabaseExecutor { ), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override _i4.Future insert( String? table, Map? values, { String? nullColumnHack, - _i6.ConflictAlgorithm? conflictAlgorithm, + _i9.ConflictAlgorithm? conflictAlgorithm, }) => (super.noSuchMethod( Invocation.method( @@ -1107,6 +1256,7 @@ class MockDatabaseExecutor extends _i1.Mock implements _i3.DatabaseExecutor { ), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override _i4.Future>> query( String? table, { @@ -1139,6 +1289,7 @@ class MockDatabaseExecutor extends _i1.Mock implements _i3.DatabaseExecutor { returnValue: _i4.Future>>.value( >[]), ) as _i4.Future>>); + @override _i4.Future>> rawQuery( String? sql, [ @@ -1155,6 +1306,7 @@ class MockDatabaseExecutor extends _i1.Mock implements _i3.DatabaseExecutor { returnValue: _i4.Future>>.value( >[]), ) as _i4.Future>>); + @override _i4.Future<_i3.QueryCursor> rawQueryCursor( String? sql, @@ -1182,6 +1334,7 @@ class MockDatabaseExecutor extends _i1.Mock implements _i3.DatabaseExecutor { ), )), ) as _i4.Future<_i3.QueryCursor>); + @override _i4.Future<_i3.QueryCursor> queryCursor( String? table, { @@ -1233,6 +1386,7 @@ class MockDatabaseExecutor extends _i1.Mock implements _i3.DatabaseExecutor { ), )), ) as _i4.Future<_i3.QueryCursor>); + @override _i4.Future rawUpdate( String? sql, [ @@ -1248,13 +1402,14 @@ class MockDatabaseExecutor extends _i1.Mock implements _i3.DatabaseExecutor { ), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override _i4.Future update( String? table, Map? values, { String? where, List? whereArgs, - _i6.ConflictAlgorithm? conflictAlgorithm, + _i9.ConflictAlgorithm? conflictAlgorithm, }) => (super.noSuchMethod( Invocation.method( @@ -1271,6 +1426,7 @@ class MockDatabaseExecutor extends _i1.Mock implements _i3.DatabaseExecutor { ), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override _i4.Future rawDelete( String? sql, [ @@ -1286,6 +1442,7 @@ class MockDatabaseExecutor extends _i1.Mock implements _i3.DatabaseExecutor { ), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override _i4.Future delete( String? table, { @@ -1303,6 +1460,7 @@ class MockDatabaseExecutor extends _i1.Mock implements _i3.DatabaseExecutor { ), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override _i3.Batch batch() => (super.noSuchMethod( Invocation.method( @@ -1335,27 +1493,49 @@ class MockHub extends _i1.Mock implements _i2.Hub { Invocation.getter(#options), ), ) as _i2.SentryOptions); + + @override + _i5.MetricsApi get metricsApi => (super.noSuchMethod( + Invocation.getter(#metricsApi), + returnValue: _FakeMetricsApi_9( + this, + Invocation.getter(#metricsApi), + ), + ) as _i5.MetricsApi); + @override bool get isEnabled => (super.noSuchMethod( Invocation.getter(#isEnabled), returnValue: false, ) as bool); + @override _i2.SentryId get lastEventId => (super.noSuchMethod( Invocation.getter(#lastEventId), - returnValue: _FakeSentryId_9( + returnValue: _FakeSentryId_10( this, Invocation.getter(#lastEventId), ), ) as _i2.SentryId); + @override _i2.Scope get scope => (super.noSuchMethod( Invocation.getter(#scope), - returnValue: _FakeScope_10( + returnValue: _FakeScope_11( this, Invocation.getter(#scope), ), ) as _i2.Scope); + + @override + set profilerFactory(_i8.SentryProfilerFactory? value) => super.noSuchMethod( + Invocation.setter( + #profilerFactory, + value, + ), + returnValueForMissingStub: null, + ); + @override _i4.Future<_i2.SentryId> captureEvent( _i2.SentryEvent? event, { @@ -1373,7 +1553,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #withScope: withScope, }, ), - returnValue: _i4.Future<_i2.SentryId>.value(_FakeSentryId_9( + returnValue: _i4.Future<_i2.SentryId>.value(_FakeSentryId_10( this, Invocation.method( #captureEvent, @@ -1386,6 +1566,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { ), )), ) as _i4.Future<_i2.SentryId>); + @override _i4.Future<_i2.SentryId> captureException( dynamic throwable, { @@ -1403,7 +1584,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #withScope: withScope, }, ), - returnValue: _i4.Future<_i2.SentryId>.value(_FakeSentryId_9( + returnValue: _i4.Future<_i2.SentryId>.value(_FakeSentryId_10( this, Invocation.method( #captureException, @@ -1416,6 +1597,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { ), )), ) as _i4.Future<_i2.SentryId>); + @override _i4.Future<_i2.SentryId> captureMessage( String? message, { @@ -1437,7 +1619,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #withScope: withScope, }, ), - returnValue: _i4.Future<_i2.SentryId>.value(_FakeSentryId_9( + returnValue: _i4.Future<_i2.SentryId>.value(_FakeSentryId_10( this, Invocation.method( #captureMessage, @@ -1452,8 +1634,8 @@ class MockHub extends _i1.Mock implements _i2.Hub { ), )), ) as _i4.Future<_i2.SentryId>); + @override - // ignore: deprecated_member_use _i4.Future captureUserFeedback(_i2.SentryUserFeedback? userFeedback) => (super.noSuchMethod( Invocation.method( @@ -1463,6 +1645,35 @@ class MockHub extends _i1.Mock implements _i2.Hub { returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + + @override + _i4.Future<_i2.SentryId> captureFeedback( + _i2.SentryFeedback? feedback, { + _i2.Hint? hint, + _i2.ScopeCallback? withScope, + }) => + (super.noSuchMethod( + Invocation.method( + #captureFeedback, + [feedback], + { + #hint: hint, + #withScope: withScope, + }, + ), + returnValue: _i4.Future<_i2.SentryId>.value(_FakeSentryId_10( + this, + Invocation.method( + #captureFeedback, + [feedback], + { + #hint: hint, + #withScope: withScope, + }, + ), + )), + ) as _i4.Future<_i2.SentryId>); + @override _i4.Future addBreadcrumb( _i2.Breadcrumb? crumb, { @@ -1477,6 +1688,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override void bindClient(_i2.SentryClient? client) => super.noSuchMethod( Invocation.method( @@ -1485,13 +1697,14 @@ class MockHub extends _i1.Mock implements _i2.Hub { ), returnValueForMissingStub: null, ); + @override _i2.Hub clone() => (super.noSuchMethod( Invocation.method( #clone, [], ), - returnValue: _FakeHub_11( + returnValue: _FakeHub_12( this, Invocation.method( #clone, @@ -1499,6 +1712,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { ), ), ) as _i2.Hub); + @override _i4.Future close() => (super.noSuchMethod( Invocation.method( @@ -1508,12 +1722,14 @@ class MockHub extends _i1.Mock implements _i2.Hub { returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override _i4.FutureOr configureScope(_i2.ScopeCallback? callback) => (super.noSuchMethod(Invocation.method( #configureScope, [callback], )) as _i4.FutureOr); + @override _i2.ISentrySpan startTransaction( String? name, @@ -1545,7 +1761,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #customSamplingContext: customSamplingContext, }, ), - returnValue: _i8.startTransactionShim( + returnValue: _i10.startTransactionShim( name, operation, description: description, @@ -1558,6 +1774,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { customSamplingContext: customSamplingContext, ), ) as _i2.ISentrySpan); + @override _i2.ISentrySpan startTransactionWithContext( _i2.SentryTransactionContext? transactionContext, { @@ -1600,26 +1817,52 @@ class MockHub extends _i1.Mock implements _i2.Hub { ), ), ) as _i2.ISentrySpan); + @override _i4.Future<_i2.SentryId> captureTransaction( _i2.SentryTransaction? transaction, { _i2.SentryTraceContextHeader? traceContext, + _i2.Hint? hint, }) => (super.noSuchMethod( Invocation.method( #captureTransaction, [transaction], - {#traceContext: traceContext}, + { + #traceContext: traceContext, + #hint: hint, + }, ), - returnValue: _i4.Future<_i2.SentryId>.value(_FakeSentryId_9( + returnValue: _i4.Future<_i2.SentryId>.value(_FakeSentryId_10( this, Invocation.method( #captureTransaction, [transaction], - {#traceContext: traceContext}, + { + #traceContext: traceContext, + #hint: hint, + }, ), )), ) as _i4.Future<_i2.SentryId>); + + @override + _i4.Future<_i2.SentryId> captureMetrics( + Map>? metricsBuckets) => + (super.noSuchMethod( + Invocation.method( + #captureMetrics, + [metricsBuckets], + ), + returnValue: _i4.Future<_i2.SentryId>.value(_FakeSentryId_10( + this, + Invocation.method( + #captureMetrics, + [metricsBuckets], + ), + )), + ) as _i4.Future<_i2.SentryId>); + @override void setSpanContext( dynamic throwable, From 1ead661888f854a3fcbf3cfa18dee050e2bfa1b1 Mon Sep 17 00:00:00 2001 From: Martin Haintz Date: Tue, 19 Nov 2024 13:20:23 +0100 Subject: [PATCH 13/25] add script to run builder for all packages --- scripts/run-builder.sh | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100755 scripts/run-builder.sh diff --git a/scripts/run-builder.sh b/scripts/run-builder.sh new file mode 100755 index 0000000000..5a425f1f81 --- /dev/null +++ b/scripts/run-builder.sh @@ -0,0 +1,17 @@ +#!/bin/bash +set -euo pipefail + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd $SCRIPT_DIR/.. + +for pkg in {dart,drift,flutter,hive,isar,sqflite,}; do + # Navigate into package + cd $pkg + flutter clean + flutter pub get + ## Run build_runner + flutter pub run build_runner build --delete-conflicting-outputs + ## Run tests + flutter test + cd .. +done \ No newline at end of file From fdadb89cda1f25ffa61041652ce6900290ef1c29 Mon Sep 17 00:00:00 2001 From: Martin Haintz Date: Tue, 19 Nov 2024 14:05:40 +0100 Subject: [PATCH 14/25] fix streamed response copier --- .../src/utils/streamed_response_copier.dart | 16 ++- .../utils/streamed_response_copier_test.dart | 127 ++++++++++++++++++ 2 files changed, 139 insertions(+), 4 deletions(-) create mode 100644 dart/test/utils/streamed_response_copier_test.dart diff --git a/dart/lib/src/utils/streamed_response_copier.dart b/dart/lib/src/utils/streamed_response_copier.dart index 7087fa3dbf..a09ffbd213 100644 --- a/dart/lib/src/utils/streamed_response_copier.dart +++ b/dart/lib/src/utils/streamed_response_copier.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:io'; import 'package:http/http.dart'; class StreamedResponseCopier { @@ -26,6 +25,10 @@ class StreamedResponseCopier { /// Get a copied StreamedResponse StreamedResponse copy() { + if (_streamController.isClosed) { + throw StateError( + 'Cannot create a new stream after the copier is disposed'); + } final Stream> replayStream = _getReplayStream(); return StreamedResponse( replayStream, @@ -40,8 +43,11 @@ class StreamedResponseCopier { /// Create a stream that replays the cached data and listens to future updates Stream> _getReplayStream() async* { + // Create a snapshot of the current cache to iterate over + final cacheSnapshot = List>.from(_cache); + // Replay cached data - for (final chunk in _cache) { + for (final chunk in cacheSnapshot) { yield chunk; } @@ -52,7 +58,9 @@ class StreamedResponseCopier { } /// Dispose resources when done - void dispose() { - _streamController.close(); + Future dispose() async { + if (!_streamController.isClosed) { + await _streamController.close(); + } } } diff --git a/dart/test/utils/streamed_response_copier_test.dart b/dart/test/utils/streamed_response_copier_test.dart new file mode 100644 index 0000000000..5c0e7f86ad --- /dev/null +++ b/dart/test/utils/streamed_response_copier_test.dart @@ -0,0 +1,127 @@ +import 'dart:async'; + +import 'package:http/http.dart'; +import 'package:sentry/src/utils/streamed_response_copier.dart'; +import 'package:test/test.dart'; + +void main() { + group('StreamedResponseCopier', () { + late StreamController> streamController; + late StreamedResponse originalResponse; + late StreamedResponseCopier copier; + + setUp(() { + streamController = StreamController>(); + originalResponse = StreamedResponse( + streamController.stream, + 200, + contentLength: 100, + headers: {'Content-Type': 'application/json'}, + reasonPhrase: 'OK', + ); + copier = StreamedResponseCopier(originalResponse); + }); + + tearDown(() { + copier.dispose(); + }); + + test('forwards original stream data to copies', () async { + final copiedResponse = copier.copy(); + final receivedData = >[]; + + copiedResponse.stream.listen(receivedData.add); + + streamController.add([1, 2, 3]); + streamController.add([4, 5, 6]); + await streamController.close(); + + await Future.delayed(Duration(milliseconds: 100)); // Wait for async tasks + expect(receivedData, [ + [1, 2, 3], + [4, 5, 6] + ]); + }); + + test('caches data and replays in subsequent copies', () async { + streamController.add([1, 2, 3]); + await Future.delayed(Duration(milliseconds: 100)); // Wait for cache + + final copiedResponse = copier.copy(); + final receivedData = >[]; + + copiedResponse.stream.listen(receivedData.add); + await Future.delayed(Duration(milliseconds: 100)); // Wait for replay + + expect(receivedData, [ + [1, 2, 3] + ]); + }); + + test('handles errors in the original stream', () async { + final copiedResponse = copier.copy(); + final errors = []; + + copiedResponse.stream.listen( + (_) {}, + onError: errors.add, + ); + + streamController.addError(Exception('Test error')); + await Future.delayed(Duration(milliseconds: 100)); // Wait for async tasks + + expect(errors.length, 1); + expect(errors.first.toString(), contains('Test error')); + }); + + test('closes copied streams when original stream is done', () async { + final copiedResponse = copier.copy(); + final isDone = Completer(); + + copiedResponse.stream.listen( + (_) {}, + onDone: () => isDone.complete(true), + ); + + await streamController.close(); + + expect(await isDone.future, isTrue); + }); + + test('disposes resources correctly', () async { + await copier.dispose(); + + expect( + () => copier.copy(), + throwsStateError, + ); + }); + + test('copies include original response metadata', () { + final copiedResponse = copier.copy(); + + expect(copiedResponse.statusCode, originalResponse.statusCode); + expect(copiedResponse.contentLength, originalResponse.contentLength); + expect(copiedResponse.headers, originalResponse.headers); + expect(copiedResponse.reasonPhrase, originalResponse.reasonPhrase); + }); + + test('streams replay cached data and listen to future updates', () async { + streamController.add([1, 2, 3]); + await Future.delayed(Duration(milliseconds: 100)); // Wait for cache + + final copiedResponse = copier.copy(); + final receivedData = >[]; + + copiedResponse.stream.listen(receivedData.add); + await Future.delayed(Duration(milliseconds: 100)); // Wait for cache + streamController.add([4, 5, 6]); + await streamController.close(); + + expect(receivedData, [ + [1, 2, 3], + [4, 5, 6] + ]); + }); + }); +} From f773568d2a6667ccb59aea2177fa283ed1070d1d Mon Sep 17 00:00:00 2001 From: Martin Haintz Date: Tue, 19 Nov 2024 14:09:58 +0100 Subject: [PATCH 15/25] fix dart analyze --- dart/lib/src/http_client/tracing_client.dart | 1 - dart/lib/src/noop_sentry_span.dart | 3 --- dart/lib/src/sentry_span_interface.dart | 3 --- dart/lib/src/sentry_tracer.dart | 1 - dio/test/mocks/mock_hub.dart | 2 +- 5 files changed, 1 insertion(+), 9 deletions(-) diff --git a/dart/lib/src/http_client/tracing_client.dart b/dart/lib/src/http_client/tracing_client.dart index 5dea250d74..8c95bbaef3 100644 --- a/dart/lib/src/http_client/tracing_client.dart +++ b/dart/lib/src/http_client/tracing_client.dart @@ -1,6 +1,5 @@ import 'package:http/http.dart'; import '../../sentry.dart'; -import '../utils/http_deep_copy_streamed_response.dart'; import '../utils/streamed_response_copier.dart'; /// A [http](https://pub.dev/packages/http)-package compatible HTTP client diff --git a/dart/lib/src/noop_sentry_span.dart b/dart/lib/src/noop_sentry_span.dart index eabe7f9954..1819c62bb3 100644 --- a/dart/lib/src/noop_sentry_span.dart +++ b/dart/lib/src/noop_sentry_span.dart @@ -1,8 +1,5 @@ import '../sentry.dart'; import 'metrics/local_metrics_aggregator.dart'; -import 'protocol.dart'; -import 'tracing.dart'; -import 'utils.dart'; class NoOpSentrySpan extends ISentrySpan { NoOpSentrySpan._(); diff --git a/dart/lib/src/sentry_span_interface.dart b/dart/lib/src/sentry_span_interface.dart index b7b65f39f5..af91a4d8fa 100644 --- a/dart/lib/src/sentry_span_interface.dart +++ b/dart/lib/src/sentry_span_interface.dart @@ -1,10 +1,7 @@ -import 'package:http/http.dart'; import 'package:meta/meta.dart'; import '../sentry.dart'; import 'metrics/local_metrics_aggregator.dart'; -import 'protocol.dart'; -import 'tracing.dart'; /// Represents performance monitoring Span. abstract class ISentrySpan { diff --git a/dart/lib/src/sentry_tracer.dart b/dart/lib/src/sentry_tracer.dart index 021db25fc5..4383bc1c3b 100644 --- a/dart/lib/src/sentry_tracer.dart +++ b/dart/lib/src/sentry_tracer.dart @@ -1,6 +1,5 @@ import 'dart:async'; -import 'package:http/http.dart'; import 'package:meta/meta.dart'; import '../sentry.dart'; diff --git a/dio/test/mocks/mock_hub.dart b/dio/test/mocks/mock_hub.dart index b10bb07ac0..b40ee1ee22 100644 --- a/dio/test/mocks/mock_hub.dart +++ b/dio/test/mocks/mock_hub.dart @@ -117,7 +117,7 @@ class MockHub with NoSuchMethodProvider implements Hub { Future captureTransaction( SentryTransaction transaction, { SentryTraceContextHeader? traceContext, - Hint? hint + Hint? hint, }) async { captureTransactionCalls.add(transaction); return transaction.eventId; From b0bca7d7e96304e16985e7907cf91ca71883df70 Mon Sep 17 00:00:00 2001 From: Martin Haintz Date: Tue, 19 Nov 2024 14:15:14 +0100 Subject: [PATCH 16/25] fix analyzer and format --- dart/lib/src/http_client/tracing_client.dart | 1 - hive/test/mocks/mocks.mocks.dart | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/dart/lib/src/http_client/tracing_client.dart b/dart/lib/src/http_client/tracing_client.dart index 8c95bbaef3..35b076f0dd 100644 --- a/dart/lib/src/http_client/tracing_client.dart +++ b/dart/lib/src/http_client/tracing_client.dart @@ -16,7 +16,6 @@ class TracingClient extends BaseClient { @override Future send(BaseRequest request) async { // see https://develop.sentry.dev/sdk/performance/#header-sentry-trace - int? statusCode; final stopwatch = Stopwatch(); stopwatch.start(); diff --git a/hive/test/mocks/mocks.mocks.dart b/hive/test/mocks/mocks.mocks.dart index 9cf52423ef..8899aa596e 100644 --- a/hive/test/mocks/mocks.mocks.dart +++ b/hive/test/mocks/mocks.mocks.dart @@ -428,10 +428,10 @@ class MockHub extends _i1.Mock implements _i2.Hub { @override _i5.Future<_i2.SentryId> captureTransaction( - _i2.SentryTransaction? transaction, { - _i2.SentryTraceContextHeader? traceContext, - _i2.Hint? hint, - }) => + _i2.SentryTransaction? transaction, { + _i2.SentryTraceContextHeader? traceContext, + _i2.Hint? hint, + }) => (super.noSuchMethod( Invocation.method( #captureTransaction, From 9e2ff1264458bacff57ccc1ac5a8db4a65e9e4fe Mon Sep 17 00:00:00 2001 From: Martin Haintz Date: Tue, 19 Nov 2024 14:38:41 +0100 Subject: [PATCH 17/25] update flutter mocks and fix tests --- .../load_contexts_integration_test.dart | 2 +- flutter/test/mocks.mocks.dart | 156 ++++++------------ 2 files changed, 49 insertions(+), 109 deletions(-) diff --git a/flutter/test/integrations/load_contexts_integration_test.dart b/flutter/test/integrations/load_contexts_integration_test.dart index caed2f3293..f311069750 100644 --- a/flutter/test/integrations/load_contexts_integration_test.dart +++ b/flutter/test/integrations/load_contexts_integration_test.dart @@ -128,7 +128,7 @@ void main() { const expectedId = '1'; String? actualId; - fixture.options.beforeSendTransaction = (transaction) { + fixture.options.beforeSendTransaction = (transaction, hint) { actualIp = transaction.user?.ipAddress; actualId = transaction.user?.id; return transaction; diff --git a/flutter/test/mocks.mocks.dart b/flutter/test/mocks.mocks.dart index 45c3d2eabb..7c571b7d26 100644 --- a/flutter/test/mocks.mocks.dart +++ b/flutter/test/mocks.mocks.dart @@ -435,39 +435,8 @@ class _FakeViewConfiguration_35 extends _i1.SmartFake ); } -class _FakeSceneBuilder_36 extends _i1.SmartFake implements _i6.SceneBuilder { - _FakeSceneBuilder_36( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} - -class _FakePictureRecorder_37 extends _i1.SmartFake - implements _i6.PictureRecorder { - _FakePictureRecorder_37( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} - -class _FakeCanvas_38 extends _i1.SmartFake implements _i6.Canvas { - _FakeCanvas_38( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} - -class _FakeWidget_39 extends _i1.SmartFake implements _i9.Widget { - _FakeWidget_39( +class _FakeWidget_36 extends _i1.SmartFake implements _i9.Widget { + _FakeWidget_36( Object parent, Invocation parentInvocation, ) : super( @@ -480,8 +449,8 @@ class _FakeWidget_39 extends _i1.SmartFake implements _i9.Widget { super.toString(); } -class _FakeSentryOptions_40 extends _i1.SmartFake implements _i2.SentryOptions { - _FakeSentryOptions_40( +class _FakeSentryOptions_37 extends _i1.SmartFake implements _i2.SentryOptions { + _FakeSentryOptions_37( Object parent, Invocation parentInvocation, ) : super( @@ -490,8 +459,8 @@ class _FakeSentryOptions_40 extends _i1.SmartFake implements _i2.SentryOptions { ); } -class _FakeMetricsApi_41 extends _i1.SmartFake implements _i13.MetricsApi { - _FakeMetricsApi_41( +class _FakeMetricsApi_38 extends _i1.SmartFake implements _i13.MetricsApi { + _FakeMetricsApi_38( Object parent, Invocation parentInvocation, ) : super( @@ -500,8 +469,8 @@ class _FakeMetricsApi_41 extends _i1.SmartFake implements _i13.MetricsApi { ); } -class _FakeScope_42 extends _i1.SmartFake implements _i2.Scope { - _FakeScope_42( +class _FakeScope_39 extends _i1.SmartFake implements _i2.Scope { + _FakeScope_39( Object parent, Invocation parentInvocation, ) : super( @@ -510,8 +479,8 @@ class _FakeScope_42 extends _i1.SmartFake implements _i2.Scope { ); } -class _FakeHub_43 extends _i1.SmartFake implements _i2.Hub { - _FakeHub_43( +class _FakeHub_40 extends _i1.SmartFake implements _i2.Hub { + _FakeHub_40( Object parent, Invocation parentInvocation, ) : super( @@ -629,6 +598,15 @@ class MockSentryTracer extends _i1.Mock implements _i3.SentryTracer { returnValue: {}, ) as Map); + @override + set hint(_i2.Hint? hint) => super.noSuchMethod( + Invocation.setter( + #hint, + hint, + ), + returnValueForMissingStub: null, + ); + @override _i2.SentrySpanContext get context => (super.noSuchMethod( Invocation.getter(#context), @@ -702,6 +680,7 @@ class MockSentryTracer extends _i1.Mock implements _i3.SentryTracer { _i11.Future finish({ _i2.SpanStatus? status, DateTime? endTimestamp, + _i2.Hint? hint, }) => (super.noSuchMethod( Invocation.method( @@ -710,6 +689,7 @@ class MockSentryTracer extends _i1.Mock implements _i3.SentryTracer { { #status: status, #endTimestamp: endTimestamp, + #hint: hint, }, ), returnValue: _i11.Future.value(), @@ -1215,6 +1195,7 @@ class MockSentrySpan extends _i1.Mock implements _i2.SentrySpan { _i11.Future finish({ _i2.SpanStatus? status, DateTime? endTimestamp, + _i2.Hint? hint, }) => (super.noSuchMethod( Invocation.method( @@ -1223,6 +1204,7 @@ class MockSentrySpan extends _i1.Mock implements _i2.SentrySpan { { #status: status, #endTimestamp: endTimestamp, + #hint: hint, }, ), returnValue: _i11.Future.value(), @@ -1471,6 +1453,7 @@ class MockSentryClient extends _i1.Mock implements _i2.SentryClient { _i2.SentryTransaction? transaction, { _i2.Scope? scope, _i2.SentryTraceContextHeader? traceContext, + _i2.Hint? hint, }) => (super.noSuchMethod( Invocation.method( @@ -1479,6 +1462,7 @@ class MockSentryClient extends _i1.Mock implements _i2.SentryClient { { #scope: scope, #traceContext: traceContext, + #hint: hint, }, ), returnValue: _i11.Future<_i2.SentryId>.value(_FakeSentryId_5( @@ -1489,6 +1473,7 @@ class MockSentryClient extends _i1.Mock implements _i2.SentryClient { { #scope: scope, #traceContext: traceContext, + #hint: hint, }, ), )), @@ -2957,15 +2942,6 @@ class MockWidgetsFlutterBinding extends _i1.Mock returnValueForMissingStub: null, ); - @override - void handleViewFocusChanged(_i6.ViewFocusEvent? event) => super.noSuchMethod( - Invocation.method( - #handleViewFocusChanged, - [event], - ), - returnValueForMissingStub: null, - ); - @override _i11.Future<_i6.AppExitResponse> handleRequestAppExit() => (super.noSuchMethod( @@ -3216,51 +3192,6 @@ class MockWidgetsFlutterBinding extends _i1.Mock ), ) as _i10.ViewConfiguration); - @override - _i6.SceneBuilder createSceneBuilder() => (super.noSuchMethod( - Invocation.method( - #createSceneBuilder, - [], - ), - returnValue: _FakeSceneBuilder_36( - this, - Invocation.method( - #createSceneBuilder, - [], - ), - ), - ) as _i6.SceneBuilder); - - @override - _i6.PictureRecorder createPictureRecorder() => (super.noSuchMethod( - Invocation.method( - #createPictureRecorder, - [], - ), - returnValue: _FakePictureRecorder_37( - this, - Invocation.method( - #createPictureRecorder, - [], - ), - ), - ) as _i6.PictureRecorder); - - @override - _i6.Canvas createCanvas(_i6.PictureRecorder? recorder) => (super.noSuchMethod( - Invocation.method( - #createCanvas, - [recorder], - ), - returnValue: _FakeCanvas_38( - this, - Invocation.method( - #createCanvas, - [recorder], - ), - ), - ) as _i6.Canvas); - @override void handleMetricsChanged() => super.noSuchMethod( Invocation.method( @@ -3380,22 +3311,24 @@ class MockWidgetsFlutterBinding extends _i1.Mock ); @override - _i11.Future handlePopRoute() => (super.noSuchMethod( + _i11.Future handlePopRoute() => (super.noSuchMethod( Invocation.method( #handlePopRoute, [], ), - returnValue: _i11.Future.value(false), - ) as _i11.Future); + returnValue: _i11.Future.value(), + returnValueForMissingStub: _i11.Future.value(), + ) as _i11.Future); @override - _i11.Future handlePushRoute(String? route) => (super.noSuchMethod( + _i11.Future handlePushRoute(String? route) => (super.noSuchMethod( Invocation.method( #handlePushRoute, [route], ), - returnValue: _i11.Future.value(false), - ) as _i11.Future); + returnValue: _i11.Future.value(), + returnValueForMissingStub: _i11.Future.value(), + ) as _i11.Future); @override _i9.Widget wrapWithDefaultView(_i9.Widget? rootWidget) => (super.noSuchMethod( @@ -3403,7 +3336,7 @@ class MockWidgetsFlutterBinding extends _i1.Mock #wrapWithDefaultView, [rootWidget], ), - returnValue: _FakeWidget_39( + returnValue: _FakeWidget_36( this, Invocation.method( #wrapWithDefaultView, @@ -3459,7 +3392,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { @override _i2.SentryOptions get options => (super.noSuchMethod( Invocation.getter(#options), - returnValue: _FakeSentryOptions_40( + returnValue: _FakeSentryOptions_37( this, Invocation.getter(#options), ), @@ -3468,7 +3401,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { @override _i13.MetricsApi get metricsApi => (super.noSuchMethod( Invocation.getter(#metricsApi), - returnValue: _FakeMetricsApi_41( + returnValue: _FakeMetricsApi_38( this, Invocation.getter(#metricsApi), ), @@ -3492,7 +3425,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { @override _i2.Scope get scope => (super.noSuchMethod( Invocation.getter(#scope), - returnValue: _FakeScope_42( + returnValue: _FakeScope_39( this, Invocation.getter(#scope), ), @@ -3675,7 +3608,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #clone, [], ), - returnValue: _FakeHub_43( + returnValue: _FakeHub_40( this, Invocation.method( #clone, @@ -3793,19 +3726,26 @@ class MockHub extends _i1.Mock implements _i2.Hub { _i11.Future<_i2.SentryId> captureTransaction( _i2.SentryTransaction? transaction, { _i2.SentryTraceContextHeader? traceContext, + _i2.Hint? hint, }) => (super.noSuchMethod( Invocation.method( #captureTransaction, [transaction], - {#traceContext: traceContext}, + { + #traceContext: traceContext, + #hint: hint, + }, ), returnValue: _i11.Future<_i2.SentryId>.value(_FakeSentryId_5( this, Invocation.method( #captureTransaction, [transaction], - {#traceContext: traceContext}, + { + #traceContext: traceContext, + #hint: hint, + }, ), )), ) as _i11.Future<_i2.SentryId>); From 8896a1e39234a1711361330d4912df527647899a Mon Sep 17 00:00:00 2001 From: Martin Haintz Date: Tue, 19 Nov 2024 15:06:17 +0100 Subject: [PATCH 18/25] fix mocks --- flutter/test/mocks.mocks.dart | 129 ++++++++++++++++++++++++++++------ 1 file changed, 106 insertions(+), 23 deletions(-) diff --git a/flutter/test/mocks.mocks.dart b/flutter/test/mocks.mocks.dart index 7c571b7d26..b61d8590ad 100644 --- a/flutter/test/mocks.mocks.dart +++ b/flutter/test/mocks.mocks.dart @@ -435,8 +435,39 @@ class _FakeViewConfiguration_35 extends _i1.SmartFake ); } -class _FakeWidget_36 extends _i1.SmartFake implements _i9.Widget { - _FakeWidget_36( +class _FakeSceneBuilder_36 extends _i1.SmartFake implements _i6.SceneBuilder { + _FakeSceneBuilder_36( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakePictureRecorder_37 extends _i1.SmartFake + implements _i6.PictureRecorder { + _FakePictureRecorder_37( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeCanvas_38 extends _i1.SmartFake implements _i6.Canvas { + _FakeCanvas_38( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeWidget_39 extends _i1.SmartFake implements _i9.Widget { + _FakeWidget_39( Object parent, Invocation parentInvocation, ) : super( @@ -449,8 +480,8 @@ class _FakeWidget_36 extends _i1.SmartFake implements _i9.Widget { super.toString(); } -class _FakeSentryOptions_37 extends _i1.SmartFake implements _i2.SentryOptions { - _FakeSentryOptions_37( +class _FakeSentryOptions_40 extends _i1.SmartFake implements _i2.SentryOptions { + _FakeSentryOptions_40( Object parent, Invocation parentInvocation, ) : super( @@ -459,8 +490,8 @@ class _FakeSentryOptions_37 extends _i1.SmartFake implements _i2.SentryOptions { ); } -class _FakeMetricsApi_38 extends _i1.SmartFake implements _i13.MetricsApi { - _FakeMetricsApi_38( +class _FakeMetricsApi_41 extends _i1.SmartFake implements _i13.MetricsApi { + _FakeMetricsApi_41( Object parent, Invocation parentInvocation, ) : super( @@ -469,8 +500,8 @@ class _FakeMetricsApi_38 extends _i1.SmartFake implements _i13.MetricsApi { ); } -class _FakeScope_39 extends _i1.SmartFake implements _i2.Scope { - _FakeScope_39( +class _FakeScope_42 extends _i1.SmartFake implements _i2.Scope { + _FakeScope_42( Object parent, Invocation parentInvocation, ) : super( @@ -479,8 +510,8 @@ class _FakeScope_39 extends _i1.SmartFake implements _i2.Scope { ); } -class _FakeHub_40 extends _i1.SmartFake implements _i2.Hub { - _FakeHub_40( +class _FakeHub_43 extends _i1.SmartFake implements _i2.Hub { + _FakeHub_43( Object parent, Invocation parentInvocation, ) : super( @@ -2942,6 +2973,15 @@ class MockWidgetsFlutterBinding extends _i1.Mock returnValueForMissingStub: null, ); + @override + void handleViewFocusChanged(_i6.ViewFocusEvent? event) => super.noSuchMethod( + Invocation.method( + #handleViewFocusChanged, + [event], + ), + returnValueForMissingStub: null, + ); + @override _i11.Future<_i6.AppExitResponse> handleRequestAppExit() => (super.noSuchMethod( @@ -3192,6 +3232,51 @@ class MockWidgetsFlutterBinding extends _i1.Mock ), ) as _i10.ViewConfiguration); + @override + _i6.SceneBuilder createSceneBuilder() => (super.noSuchMethod( + Invocation.method( + #createSceneBuilder, + [], + ), + returnValue: _FakeSceneBuilder_36( + this, + Invocation.method( + #createSceneBuilder, + [], + ), + ), + ) as _i6.SceneBuilder); + + @override + _i6.PictureRecorder createPictureRecorder() => (super.noSuchMethod( + Invocation.method( + #createPictureRecorder, + [], + ), + returnValue: _FakePictureRecorder_37( + this, + Invocation.method( + #createPictureRecorder, + [], + ), + ), + ) as _i6.PictureRecorder); + + @override + _i6.Canvas createCanvas(_i6.PictureRecorder? recorder) => (super.noSuchMethod( + Invocation.method( + #createCanvas, + [recorder], + ), + returnValue: _FakeCanvas_38( + this, + Invocation.method( + #createCanvas, + [recorder], + ), + ), + ) as _i6.Canvas); + @override void handleMetricsChanged() => super.noSuchMethod( Invocation.method( @@ -3311,24 +3396,22 @@ class MockWidgetsFlutterBinding extends _i1.Mock ); @override - _i11.Future handlePopRoute() => (super.noSuchMethod( + _i11.Future handlePopRoute() => (super.noSuchMethod( Invocation.method( #handlePopRoute, [], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i11.Future.value(false), + ) as _i11.Future); @override - _i11.Future handlePushRoute(String? route) => (super.noSuchMethod( + _i11.Future handlePushRoute(String? route) => (super.noSuchMethod( Invocation.method( #handlePushRoute, [route], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i11.Future.value(false), + ) as _i11.Future); @override _i9.Widget wrapWithDefaultView(_i9.Widget? rootWidget) => (super.noSuchMethod( @@ -3336,7 +3419,7 @@ class MockWidgetsFlutterBinding extends _i1.Mock #wrapWithDefaultView, [rootWidget], ), - returnValue: _FakeWidget_36( + returnValue: _FakeWidget_39( this, Invocation.method( #wrapWithDefaultView, @@ -3392,7 +3475,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { @override _i2.SentryOptions get options => (super.noSuchMethod( Invocation.getter(#options), - returnValue: _FakeSentryOptions_37( + returnValue: _FakeSentryOptions_40( this, Invocation.getter(#options), ), @@ -3401,7 +3484,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { @override _i13.MetricsApi get metricsApi => (super.noSuchMethod( Invocation.getter(#metricsApi), - returnValue: _FakeMetricsApi_38( + returnValue: _FakeMetricsApi_41( this, Invocation.getter(#metricsApi), ), @@ -3425,7 +3508,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { @override _i2.Scope get scope => (super.noSuchMethod( Invocation.getter(#scope), - returnValue: _FakeScope_39( + returnValue: _FakeScope_42( this, Invocation.getter(#scope), ), @@ -3608,7 +3691,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #clone, [], ), - returnValue: _FakeHub_40( + returnValue: _FakeHub_43( this, Invocation.method( #clone, From 9b4000b125b1d15d219f50fbca95ea0b26a9e853 Mon Sep 17 00:00:00 2001 From: Martin Haintz Date: Tue, 19 Nov 2024 15:32:42 +0100 Subject: [PATCH 19/25] fix analyze options --- isar/analysis_options.yaml | 1 + sqflite/analysis_options.yaml | 1 + 2 files changed, 2 insertions(+) diff --git a/isar/analysis_options.yaml b/isar/analysis_options.yaml index 92c8931384..28ddbe2636 100644 --- a/isar/analysis_options.yaml +++ b/isar/analysis_options.yaml @@ -20,6 +20,7 @@ analyzer: unnecessary_import: ignore exclude: - example/** + - test/mocks/mocks.mocks.dart linter: rules: diff --git a/sqflite/analysis_options.yaml b/sqflite/analysis_options.yaml index 92c8931384..28ddbe2636 100644 --- a/sqflite/analysis_options.yaml +++ b/sqflite/analysis_options.yaml @@ -20,6 +20,7 @@ analyzer: unnecessary_import: ignore exclude: - example/** + - test/mocks/mocks.mocks.dart linter: rules: From 86ffb802aaf03aa1ef876f217822eb05d5727629 Mon Sep 17 00:00:00 2001 From: Martin Haintz Date: Tue, 19 Nov 2024 17:07:13 +0100 Subject: [PATCH 20/25] cleanup and code reformating --- dart/lib/src/http_client/tracing_client.dart | 4 --- dart/lib/src/hub.dart | 8 ++++-- dart/lib/src/protocol/sentry_span.dart | 6 ++-- dart/lib/src/sentry_tracer.dart | 12 ++++++-- .../http_deep_copy_streamed_response.dart | 28 ------------------- 5 files changed, 19 insertions(+), 39 deletions(-) delete mode 100644 dart/lib/src/utils/http_deep_copy_streamed_response.dart diff --git a/dart/lib/src/http_client/tracing_client.dart b/dart/lib/src/http_client/tracing_client.dart index 35b076f0dd..4d9ef82a5e 100644 --- a/dart/lib/src/http_client/tracing_client.dart +++ b/dart/lib/src/http_client/tracing_client.dart @@ -16,8 +16,6 @@ class TracingClient extends BaseClient { @override Future send(BaseRequest request) async { // see https://develop.sentry.dev/sdk/performance/#header-sentry-trace - final stopwatch = Stopwatch(); - stopwatch.start(); final urlDetails = HttpSanitizer.sanitizeUrl(request.url.toString()); @@ -43,7 +41,6 @@ class TracingClient extends BaseClient { StreamedResponse? originalResponse; final hint = Hint(); - // List copiedResponses = []; try { if (containsTargetOrMatchesRegExp( _hub.options.tracePropagationTargets, request.url.toString())) { @@ -88,7 +85,6 @@ class TracingClient extends BaseClient { rethrow; } finally { await span?.finish(hint: hint); - stopwatch.stop(); } return originalResponse; } diff --git a/dart/lib/src/hub.dart b/dart/lib/src/hub.dart index 073627f5df..f3e58bfc53 100644 --- a/dart/lib/src/hub.dart +++ b/dart/lib/src/hub.dart @@ -614,8 +614,12 @@ class Hub { ); } else { try { - sentryId = await item.client.captureTransaction(transaction, - scope: item.scope, traceContext: traceContext, hint: hint); + sentryId = await item.client.captureTransaction( + transaction, + scope: item.scope, + traceContext: traceContext, + hint: hint, + ); } catch (exception, stackTrace) { _options.logger( SentryLevel.error, diff --git a/dart/lib/src/protocol/sentry_span.dart b/dart/lib/src/protocol/sentry_span.dart index 338f8816a6..712ca4f69f 100644 --- a/dart/lib/src/protocol/sentry_span.dart +++ b/dart/lib/src/protocol/sentry_span.dart @@ -7,8 +7,10 @@ import '../metrics/local_metrics_aggregator.dart'; import '../sentry_tracer.dart'; -typedef OnFinishedCallback = Future Function( - {DateTime? endTimestamp, Hint? hint}); +typedef OnFinishedCallback = Future Function({ + DateTime? endTimestamp, + Hint? hint, +}); class SentrySpan extends ISentrySpan { final SentrySpanContext _context; diff --git a/dart/lib/src/sentry_tracer.dart b/dart/lib/src/sentry_tracer.dart index 4383bc1c3b..ae18a94e1f 100644 --- a/dart/lib/src/sentry_tracer.dart +++ b/dart/lib/src/sentry_tracer.dart @@ -168,8 +168,11 @@ class SentryTracer extends ISentrySpan { ? await profiler?.finishFor(transaction) : null; - await _hub.captureTransaction(transaction, - traceContext: traceContext(), hint: _hint); + await _hub.captureTransaction( + transaction, + traceContext: traceContext(), + hint: _hint, + ); } finally { profiler?.dispose(); } @@ -287,7 +290,10 @@ class SentryTracer extends ISentrySpan { final finishStatus = _finishStatus; if (finishStatus.finishing) { await finish( - status: finishStatus.status, endTimestamp: endTimestamp, hint: hint); + status: finishStatus.status, + endTimestamp: endTimestamp, + hint: hint, + ); } } diff --git a/dart/lib/src/utils/http_deep_copy_streamed_response.dart b/dart/lib/src/utils/http_deep_copy_streamed_response.dart deleted file mode 100644 index 95c7e6058c..0000000000 --- a/dart/lib/src/utils/http_deep_copy_streamed_response.dart +++ /dev/null @@ -1,28 +0,0 @@ -import 'package:http/http.dart'; -import 'package:meta/meta.dart'; - -/// Helper to deep copy the StreamedResponse of a web request -@internal -Future> deepCopyStreamedResponse( - StreamedResponse originalResponse, int copies) async { - final List bufferedData = []; - - await for (final List chunk in originalResponse.stream) { - bufferedData.addAll(chunk); - } - - List copiedElements = []; - for (int i = 1; i <= copies; i++) { - copiedElements.add(StreamedResponse( - Stream.fromIterable([bufferedData]), - originalResponse.statusCode, - contentLength: originalResponse.contentLength, - request: originalResponse.request, - headers: originalResponse.headers, - reasonPhrase: originalResponse.reasonPhrase, - isRedirect: originalResponse.isRedirect, - persistentConnection: originalResponse.persistentConnection, - )); - } - return copiedElements; -} From b325b0923e121987ace31cccf84b3ac0bee5f869 Mon Sep 17 00:00:00 2001 From: Martin Haintz Date: Tue, 19 Nov 2024 17:07:52 +0100 Subject: [PATCH 21/25] revert changes --- .../http_client/failed_request_client.dart | 113 ++++++++++++++++-- .../src/http_client/sentry_http_client.dart | 85 ------------- 2 files changed, 101 insertions(+), 97 deletions(-) diff --git a/dart/lib/src/http_client/failed_request_client.dart b/dart/lib/src/http_client/failed_request_client.dart index 74fcb24569..8e441a0f1e 100644 --- a/dart/lib/src/http_client/failed_request_client.dart +++ b/dart/lib/src/http_client/failed_request_client.dart @@ -1,9 +1,13 @@ import 'package:http/http.dart'; -import '../utils/http_deep_copy_streamed_response.dart'; +import '../hint.dart'; +import '../type_check_hint.dart'; +import '../utils/streamed_response_copier.dart'; import '../utils/tracing_utils.dart'; import 'sentry_http_client_error.dart'; +import '../protocol.dart'; import '../hub.dart'; import '../hub_adapter.dart'; +import '../throwable_mechanism.dart'; import 'sentry_http_client.dart'; /// A [http](https://pub.dev/packages/http)-package compatible HTTP client @@ -96,30 +100,31 @@ class FailedRequestClient extends BaseClient { int? statusCode; Object? exception; StackTrace? stackTrace; - StreamedResponse? streamedResponse; - List copiedResponses = []; + StreamedResponse? originalResponse; + StreamedResponse? copiedResponse; final stopwatch = Stopwatch(); stopwatch.start(); try { - streamedResponse = await _client.send(request); - copiedResponses = await deepCopyStreamedResponse(streamedResponse, 2); - statusCode = copiedResponses[0].statusCode; - return copiedResponses[0]; + originalResponse = await _client.send(request); + final copier = StreamedResponseCopier(originalResponse); + originalResponse = copier.copy(); + copiedResponse = copier.copy(); + statusCode = originalResponse.statusCode; + return originalResponse; } catch (e, st) { exception = e; stackTrace = st; rethrow; } finally { stopwatch.stop(); - await _captureEventIfNeeded( request, statusCode, exception, stackTrace, - copiedResponses.isNotEmpty ? copiedResponses[1] : null, + copiedResponse, stopwatch.elapsed, ); } @@ -148,10 +153,10 @@ class FailedRequestClient extends BaseClient { } final reason = 'HTTP Client Error with status code: $statusCode'; + exception ??= SentryHttpClientError(reason); - await captureEvent( - _hub, - exception: exception ?? SentryHttpClientError(reason), + await _captureEvent( + exception: exception, stackTrace: stackTrace, request: request, requestDuration: duration, @@ -162,6 +167,90 @@ class FailedRequestClient extends BaseClient { @override void close() => _client.close(); + + // See https://develop.sentry.dev/sdk/event-payloads/request/ + Future _captureEvent({ + required Object? exception, + StackTrace? stackTrace, + String? reason, + required Duration requestDuration, + required BaseRequest request, + required StreamedResponse? response, + }) async { + final sentryRequest = SentryRequest.fromUri( + method: request.method, + headers: _hub.options.sendDefaultPii ? request.headers : null, + uri: request.url, + data: _hub.options.sendDefaultPii ? _getDataFromRequest(request) : null, + // ignore: deprecated_member_use_from_same_package + other: { + 'content_length': request.contentLength.toString(), + 'duration': requestDuration.toString(), + }, + ); + + final mechanism = Mechanism( + type: 'SentryHttpClient', + description: reason, + ); + + bool? snapshot; + if (exception is SentryHttpClientError) { + snapshot = true; + } + + final throwableMechanism = ThrowableMechanism( + mechanism, + exception, + snapshot: snapshot, + ); + + final event = SentryEvent( + throwable: throwableMechanism, + request: sentryRequest, + timestamp: _hub.options.clock(), + ); + + final hint = Hint.withMap({TypeCheckHint.httpRequest: request}); + + if (response != null) { + event.contexts.response = SentryResponse( + headers: _hub.options.sendDefaultPii ? response.headers : null, + bodySize: response.contentLength, + statusCode: response.statusCode, + ); + hint.set(TypeCheckHint.httpResponse, response); + } + + await _hub.captureEvent( + event, + stackTrace: stackTrace, + hint: hint, + ); + } + + // Types of Request can be found here: + // https://pub.dev/documentation/http/latest/http/http-library.html + Object? _getDataFromRequest(BaseRequest request) { + final contentLength = request.contentLength; + if (contentLength == null) { + return null; + } + if (!_hub.options.maxRequestBodySize.shouldAddBody(contentLength)) { + return null; + } + if (request is MultipartRequest) { + final data = {...request.fields}; + return data; + } + + if (request is Request) { + return request.body; + } + + // There's nothing we can do for a StreamedRequest + return null; + } } extension _ListX on List { diff --git a/dart/lib/src/http_client/sentry_http_client.dart b/dart/lib/src/http_client/sentry_http_client.dart index c42777ed22..2a3800d95c 100644 --- a/dart/lib/src/http_client/sentry_http_client.dart +++ b/dart/lib/src/http_client/sentry_http_client.dart @@ -160,88 +160,3 @@ class SentryStatusCode { return '$_min..$_max'; } } - -@internal -// See https://develop.sentry.dev/sdk/event-payloads/request/ -Future captureEvent( - Hub hub, { - Object? exception, - StackTrace? stackTrace, - String? reason, - required Duration requestDuration, - required BaseRequest request, - required StreamedResponse? response, -}) async { - final sentryRequest = SentryRequest.fromUri( - method: request.method, - headers: hub.options.sendDefaultPii ? request.headers : null, - uri: request.url, - data: hub.options.sendDefaultPii ? _getDataFromRequest(hub, request) : null, - // ignore: deprecated_member_use_from_same_package - other: { - 'content_length': request.contentLength.toString(), - 'duration': requestDuration.toString(), - }, - ); - - final mechanism = Mechanism( - type: 'SentryHttpClient', - description: reason, - ); - - bool? snapshot; - if (exception is SentryHttpClientError) { - snapshot = true; - } - - final throwableMechanism = ThrowableMechanism( - mechanism, - exception, - snapshot: snapshot, - ); - - final event = SentryEvent( - throwable: throwableMechanism, - request: sentryRequest, - timestamp: hub.options.clock(), - ); - - final hint = Hint.withMap({TypeCheckHint.httpRequest: request}); - - if (response != null) { - event.contexts.response = SentryResponse( - headers: hub.options.sendDefaultPii ? response.headers : null, - bodySize: response.contentLength, - statusCode: response.statusCode); - hint.set(TypeCheckHint.httpResponse, response); - } - - await hub.captureEvent( - event, - stackTrace: stackTrace, - hint: hint, - ); -} - -// Types of Request can be found here: -// https://pub.dev/documentation/http/latest/http/http-library.html -Object? _getDataFromRequest(Hub hub, BaseRequest request) { - final contentLength = request.contentLength; - if (contentLength == null) { - return null; - } - if (!hub.options.maxRequestBodySize.shouldAddBody(contentLength)) { - return null; - } - if (request is MultipartRequest) { - final data = {...request.fields}; - return data; - } - - if (request is Request) { - return request.body; - } - - // There's nothing we can do for a StreamedRequest - return null; -} From b38f597510a5d7e57affec88638fb6910ffd17b2 Mon Sep 17 00:00:00 2001 From: Martin Haintz Date: Tue, 19 Nov 2024 17:13:09 +0100 Subject: [PATCH 22/25] remove unused import --- dart/lib/src/http_client/sentry_http_client.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/dart/lib/src/http_client/sentry_http_client.dart b/dart/lib/src/http_client/sentry_http_client.dart index 2a3800d95c..aafe6da301 100644 --- a/dart/lib/src/http_client/sentry_http_client.dart +++ b/dart/lib/src/http_client/sentry_http_client.dart @@ -1,5 +1,4 @@ import 'package:http/http.dart'; -import 'package:meta/meta.dart'; import '../../sentry.dart'; import 'tracing_client.dart'; import 'breadcrumb_client.dart'; From 47f50aa4d4056dedd52485b9c29dfd8dfec36a10 Mon Sep 17 00:00:00 2001 From: Martin Haintz Date: Wed, 20 Nov 2024 11:03:58 +0100 Subject: [PATCH 23/25] removed hint from tracer --- dart/lib/src/protocol/sentry_span.dart | 5 ++- dart/lib/src/sentry_tracer.dart | 9 +--- .../test/http_client/tracing_client_test.dart | 42 ++++++++++++++----- 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/dart/lib/src/protocol/sentry_span.dart b/dart/lib/src/protocol/sentry_span.dart index 712ca4f69f..8ad14eabe2 100644 --- a/dart/lib/src/protocol/sentry_span.dart +++ b/dart/lib/src/protocol/sentry_span.dart @@ -39,6 +39,8 @@ class SentrySpan extends ISentrySpan { @override final SentryTracesSamplingDecision? samplingDecision; + late final Hint? hint; + SentrySpan( this._tracer, this._context, @@ -63,11 +65,10 @@ class SentrySpan extends ISentrySpan { DateTime? endTimestamp, Hint? hint, }) async { - _tracer.hint ??= hint; - if (finished) { return; } + this.hint = hint; if (status != null) { _status = status; diff --git a/dart/lib/src/sentry_tracer.dart b/dart/lib/src/sentry_tracer.dart index ae18a94e1f..7cbff7ebf1 100644 --- a/dart/lib/src/sentry_tracer.dart +++ b/dart/lib/src/sentry_tracer.dart @@ -33,12 +33,6 @@ class SentryTracer extends ISentrySpan { late SentryTransactionNameSource transactionNameSource; - Hint? _hint; - @internal - Hint? get hint => _hint; - @internal - set hint(Hint? hint) => _hint = hint; - SentryTraceContextHeader? _sentryTraceContextHeader; // Profiler attached to this tracer. @@ -103,7 +97,6 @@ class SentryTracer extends ISentrySpan { DateTime? endTimestamp, Hint? hint, }) async { - _hint ??= hint; final commonEndTimestamp = endTimestamp ?? _hub.options.clock(); _autoFinishAfterTimer?.cancel(); _finishStatus = SentryTracerFinishStatus.finishing(status); @@ -171,7 +164,7 @@ class SentryTracer extends ISentrySpan { await _hub.captureTransaction( transaction, traceContext: traceContext(), - hint: _hint, + hint: hint, ); } finally { profiler?.dispose(); diff --git a/dart/test/http_client/tracing_client_test.dart b/dart/test/http_client/tracing_client_test.dart index 32cff3af0b..0ccd6ed41d 100644 --- a/dart/test/http_client/tracing_client_test.dart +++ b/dart/test/http_client/tracing_client_test.dart @@ -54,7 +54,8 @@ void main() { )).called(1); }); - test('beforeSendTransaction called with response as hint for captured span', + test( + 'beforeSendTransaction called with two httpResponses inside captured span', () async { SentryTransaction? transaction; Hint? hint; @@ -65,7 +66,9 @@ void main() { return transaction; }; - final responseBody = "test response body"; + String firstResponseBody = "first response body"; + String secondResponseBody = "first response body"; + String responseBody = firstResponseBody; final sut = fixture.getSut( client: fixture.getClient( statusCode: 200, reason: 'OK', body: responseBody), @@ -76,19 +79,38 @@ void main() { bindToScope: true, ); - final originalResponse = await sut.get(requestUri); - final originalResponseBody = originalResponse.body; + final firstOriginalResponse = await sut.get(requestUri); + final firstOriginalResponseBody = firstOriginalResponse.body; + + responseBody = secondResponseBody; + final secondOriginalResponse = await sut.get(requestUri); + final secondOriginalResponseBody = secondOriginalResponse.body; await tr.finish(); - final httpResponse = - hint!.get(TypeCheckHint.httpResponse) as StreamedResponse; - final httpResponseBody = await httpResponse.stream.bytesToString(); + final transactionHintHttpResponse = + hint!.get(TypeCheckHint.httpResponse) as StreamedResponse?; + + final firstHint = transaction!.spans[0].hint!; + final secondHint = transaction!.spans[1].hint!; + + final firstHintHttpResponse = + firstHint.get(TypeCheckHint.httpResponse) as StreamedResponse; + final secondHintHttpResponse = + secondHint.get(TypeCheckHint.httpResponse) as StreamedResponse; + + final firstHintHttpResponseBody = + await firstHintHttpResponse.stream.bytesToString(); + final secondHintHttpResponseBody = + await secondHintHttpResponse.stream.bytesToString(); + + expect(transactionHintHttpResponse, null); - expect(httpResponse.statusCode, 200); - expect(httpResponseBody, responseBody); + expect(firstHintHttpResponseBody, firstResponseBody); + expect(firstOriginalResponseBody, firstResponseBody); - expect(originalResponseBody, responseBody); + expect(secondHintHttpResponseBody, secondResponseBody); + expect(secondOriginalResponseBody, secondResponseBody); }); test('captured span if successful request without Pii', () async { From 537230b4768153430cf658c122d58cb193c61c16 Mon Sep 17 00:00:00 2001 From: Martin Haintz Date: Mon, 25 Nov 2024 09:23:19 +0100 Subject: [PATCH 24/25] fix changelog example --- CHANGELOG.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7381653285..193784f746 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,13 +6,13 @@ - Make response body accessible via hint in `beforSend` callback for failed web requests or if tracing is enabled in `SentryHttpClient` ([#2293](https://github.com/getsentry/sentry-dart/pull/2293)) ```dart - options.beforeSend = (event, hint) async { - final response = hint.get(TypeCheckHint.httpResponse); - if (response is StreamedResponse) { - final body = await response.stream.bytesToString(); - // user can now use it - } - return event; + options.beforeSendTransaction = (transaction, hint) { + final firstHint = transaction!.spans[0].hint; + final firstResponseBody = firstHint.get(TypeCheckHint.httpResponse); + final secondHint = transaction!.spans[1].hint; + final secondResponseBody = secondHint.get(TypeCheckHint.httpResponse); + // user can now use it + return transaction; }; ``` - Support for screenshot PII content masking ([#2361](https://github.com/getsentry/sentry-dart/pull/2361)) From d9c26748b68c078ba4870a016ce838b39f0a86b2 Mon Sep 17 00:00:00 2001 From: Martin Haintz Date: Mon, 2 Dec 2024 11:26:06 +0100 Subject: [PATCH 25/25] fix changelog example --- CHANGELOG.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 193784f746..d82af27d30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,12 +7,12 @@ - Make response body accessible via hint in `beforSend` callback for failed web requests or if tracing is enabled in `SentryHttpClient` ([#2293](https://github.com/getsentry/sentry-dart/pull/2293)) ```dart options.beforeSendTransaction = (transaction, hint) { - final firstHint = transaction!.spans[0].hint; - final firstResponseBody = firstHint.get(TypeCheckHint.httpResponse); - final secondHint = transaction!.spans[1].hint; - final secondResponseBody = secondHint.get(TypeCheckHint.httpResponse); + final firstHint = transaction.spans[0].hint; + final firstResponseBody = firstHint?.get(TypeCheckHint.httpResponse); + final secondHint = transaction.spans[1].hint; + final secondResponseBody = secondHint?.get(TypeCheckHint.httpResponse); // user can now use it - return transaction; + return transaction; }; ``` - Support for screenshot PII content masking ([#2361](https://github.com/getsentry/sentry-dart/pull/2361))