From cf7784557078f405ab8dfdac20edca2f1ef075e4 Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Mon, 31 Jul 2023 16:23:43 +0200 Subject: [PATCH 1/8] Move iterable utlis from extension to class --- dart/lib/src/protocol/sentry_request.dart | 4 ++-- dart/lib/src/protocol/sentry_response.dart | 4 ++-- dart/lib/src/utils/iterable_extension.dart | 8 -------- dart/lib/src/utils/iterable_utils.dart | 19 +++++++++++++++++++ dart/test/sentry_client_test.dart | 6 ++++-- 5 files changed, 27 insertions(+), 14 deletions(-) delete mode 100644 dart/lib/src/utils/iterable_extension.dart create mode 100644 dart/lib/src/utils/iterable_utils.dart diff --git a/dart/lib/src/protocol/sentry_request.dart b/dart/lib/src/protocol/sentry_request.dart index 9689c8a974..fb89fb5ffa 100644 --- a/dart/lib/src/protocol/sentry_request.dart +++ b/dart/lib/src/protocol/sentry_request.dart @@ -1,6 +1,6 @@ import 'package:meta/meta.dart'; -import '../utils/iterable_extension.dart'; +import '../utils/iterable_utils.dart'; import '../utils/http_sanitizer.dart'; /// The Request interface contains information on a HTTP request related to the event. @@ -85,7 +85,7 @@ class SentryRequest { _headers = headers != null ? Map.from(headers) : null, // Look for a 'Set-Cookie' header (case insensitive) if not given. cookies = cookies ?? - headers?.entries + IterableUtils(headers?.entries) .firstWhereOrNull((e) => e.key.toLowerCase() == 'cookie') ?.value, _env = env != null ? Map.from(env) : null, diff --git a/dart/lib/src/protocol/sentry_response.dart b/dart/lib/src/protocol/sentry_response.dart index 91faaa37eb..5dbc12b8c6 100644 --- a/dart/lib/src/protocol/sentry_response.dart +++ b/dart/lib/src/protocol/sentry_response.dart @@ -1,6 +1,6 @@ import 'package:meta/meta.dart'; import 'contexts.dart'; -import '../utils/iterable_extension.dart'; +import '../utils/iterable_utils.dart'; /// The response interface contains information on a HTTP request related to the event. @immutable @@ -53,7 +53,7 @@ class SentryResponse { _headers = headers != null ? Map.from(headers) : null, // Look for a 'Set-Cookie' header (case insensitive) if not given. cookies = cookies ?? - headers?.entries + IterableUtils(headers?.entries) .firstWhereOrNull((e) => e.key.toLowerCase() == 'set-cookie') ?.value; diff --git a/dart/lib/src/utils/iterable_extension.dart b/dart/lib/src/utils/iterable_extension.dart deleted file mode 100644 index 34c2c60943..0000000000 --- a/dart/lib/src/utils/iterable_extension.dart +++ /dev/null @@ -1,8 +0,0 @@ -extension IterableExtension on Iterable { - T? firstWhereOrNull(bool Function(T item) predicate) { - for (var item in this) { - if (predicate(item)) return item; - } - return null; - } -} diff --git a/dart/lib/src/utils/iterable_utils.dart b/dart/lib/src/utils/iterable_utils.dart new file mode 100644 index 0000000000..6de34c0f31 --- /dev/null +++ b/dart/lib/src/utils/iterable_utils.dart @@ -0,0 +1,19 @@ +import 'package:meta/meta.dart'; + +@internal +class IterableUtils { + IterableUtils(this.iterable); + + Iterable? iterable; + + T? firstWhereOrNull(bool Function(T item) predicate) { + final iterable = this.iterable; + if (iterable == null) { + return null; + } + for (var item in iterable) { + if (predicate(item)) return item; + } + return null; + } +} diff --git a/dart/test/sentry_client_test.dart b/dart/test/sentry_client_test.dart index 484dd009a5..f622bace28 100644 --- a/dart/test/sentry_client_test.dart +++ b/dart/test/sentry_client_test.dart @@ -12,6 +12,7 @@ import 'package:sentry/src/sentry_item_type.dart'; import 'package:sentry/src/sentry_stack_trace_factory.dart'; import 'package:sentry/src/sentry_tracer.dart'; import 'package:sentry/src/transport/data_category.dart'; +import 'package:sentry/src/utils/iterable_utils.dart'; import 'package:test/test.dart'; import 'mocks.dart'; @@ -1426,8 +1427,9 @@ void main() { await sut.captureEvent(fakeEvent, hint: hint); final capturedEnvelope = (fixture.transport).envelopes.first; - final attachmentItem = capturedEnvelope.items.firstWhereOrNull( - (element) => element.header.type == SentryItemType.attachment); + final attachmentItem = IterableUtils(capturedEnvelope.items) + .firstWhereOrNull( + (element) => element.header.type == SentryItemType.attachment); expect(attachmentItem?.header.attachmentType, SentryAttachment.typeAttachmentDefault); }); From 9758c3914897693b12fe92dd84224ccb3a2c9d9a Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Mon, 31 Jul 2023 16:24:28 +0200 Subject: [PATCH 2/8] mark isolate utils as internal --- dart/lib/src/utils/isolate_utils.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dart/lib/src/utils/isolate_utils.dart b/dart/lib/src/utils/isolate_utils.dart index ce523b0d63..3e9c4b20bc 100644 --- a/dart/lib/src/utils/isolate_utils.dart +++ b/dart/lib/src/utils/isolate_utils.dart @@ -1,4 +1,7 @@ +import 'package:meta/meta.dart'; + import '_io_get_isolate_name.dart' if (dart.library.html) '_web_get_isolate_name.dart' as isolate_getter; +@internal String? getIsolateName() => isolate_getter.getIsolateName(); From 0d2408d6ccf0fdf59f6045e802abd8b79d10d141 Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Tue, 1 Aug 2023 10:12:59 +0200 Subject: [PATCH 3/8] replace to key.toStringValue extension --- dart/lib/src/utils/iterable_utils.dart | 4 ++-- .../sentry_user_interaction_widget.dart | 3 ++- flutter/lib/src/view_hierarchy/sentry_tree_walker.dart | 2 +- flutter/lib/src/widget_utils.dart | 10 +++++++--- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/dart/lib/src/utils/iterable_utils.dart b/dart/lib/src/utils/iterable_utils.dart index 6de34c0f31..20a875da9c 100644 --- a/dart/lib/src/utils/iterable_utils.dart +++ b/dart/lib/src/utils/iterable_utils.dart @@ -6,13 +6,13 @@ class IterableUtils { Iterable? iterable; - T? firstWhereOrNull(bool Function(T item) predicate) { + T? firstWhereOrNull(bool Function(T item) test) { final iterable = this.iterable; if (iterable == null) { return null; } for (var item in iterable) { - if (predicate(item)) return item; + if (test(item)) return item; } return null; } diff --git a/flutter/lib/src/user_interaction/sentry_user_interaction_widget.dart b/flutter/lib/src/user_interaction/sentry_user_interaction_widget.dart index f98a919065..46b25e5cb3 100644 --- a/flutter/lib/src/user_interaction/sentry_user_interaction_widget.dart +++ b/flutter/lib/src/user_interaction/sentry_user_interaction_widget.dart @@ -313,7 +313,8 @@ class _SentryUserInteractionWidgetState void _onTappedAt(Offset position) { final tappedWidget = _getElementAt(position); - final keyValue = tappedWidget?.element.widget.key?.toStringValue(); + final keyValue = + WidgetUtils.toStringValue(tappedWidget?.element.widget.key); if (tappedWidget == null || keyValue == null) { return; } diff --git a/flutter/lib/src/view_hierarchy/sentry_tree_walker.dart b/flutter/lib/src/view_hierarchy/sentry_tree_walker.dart index 2a85bf49be..41b03f4808 100644 --- a/flutter/lib/src/view_hierarchy/sentry_tree_walker.dart +++ b/flutter/lib/src/view_hierarchy/sentry_tree_walker.dart @@ -281,7 +281,7 @@ class _TreeWalker { return SentryViewHierarchyElement( element.widget.runtimeType.toString(), depth: element.depth, - identifier: element.widget.key?.toStringValue(), + identifier: WidgetUtils.toStringValue(element.widget.key), width: width, height: height, x: x, diff --git a/flutter/lib/src/widget_utils.dart b/flutter/lib/src/widget_utils.dart index 9d63b8d5a3..97d51a990a 100644 --- a/flutter/lib/src/widget_utils.dart +++ b/flutter/lib/src/widget_utils.dart @@ -1,8 +1,12 @@ import 'package:flutter/widgets.dart'; +import 'package:meta/meta.dart'; -extension WidgetExtension on Key { - String? toStringValue() { - final key = this; +@internal +class WidgetUtils { + static String? toStringValue(Key? key) { + if (key == null) { + return null; + } if (key is ValueKey) { return key.value; } else if (key is ValueKey) { From b90ea83df209e483972800a2a878183d2a501582 Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Tue, 1 Aug 2023 10:24:17 +0200 Subject: [PATCH 4/8] mark internal extensions private where possible --- .../src/client_reports/discard_reason.dart | 21 -------- .../src/client_reports/discarded_event.dart | 48 ++++++++++++++++++- .../http_client/failed_request_client.dart | 4 +- dart/lib/src/transport/data_category.dart | 42 ---------------- dart/lib/src/transport/rate_limit_parser.dart | 24 +++++++++- dart/lib/src/utils/http_sanitizer.dart | 3 +- dart/test/utils/http_sanitizer_test.dart | 2 +- dio/lib/src/failed_request_interceptor.dart | 4 +- 8 files changed, 76 insertions(+), 72 deletions(-) diff --git a/dart/lib/src/client_reports/discard_reason.dart b/dart/lib/src/client_reports/discard_reason.dart index 1b990f8dd2..81c3a45dd0 100644 --- a/dart/lib/src/client_reports/discard_reason.dart +++ b/dart/lib/src/client_reports/discard_reason.dart @@ -12,24 +12,3 @@ enum DiscardReason { cacheOverflow, rateLimitBackoff, } - -extension OutcomeExtension on DiscardReason { - String toStringValue() { - switch (this) { - case DiscardReason.beforeSend: - return 'before_send'; - case DiscardReason.eventProcessor: - return 'event_processor'; - case DiscardReason.sampleRate: - return 'sample_rate'; - case DiscardReason.networkError: - return 'network_error'; - case DiscardReason.queueOverflow: - return 'queue_overflow'; - case DiscardReason.cacheOverflow: - return 'cache_overflow'; - case DiscardReason.rateLimitBackoff: - return 'ratelimit_backoff'; - } - } -} diff --git a/dart/lib/src/client_reports/discarded_event.dart b/dart/lib/src/client_reports/discarded_event.dart index 0b989aa4cf..1e216804c3 100644 --- a/dart/lib/src/client_reports/discarded_event.dart +++ b/dart/lib/src/client_reports/discarded_event.dart @@ -13,9 +13,53 @@ class DiscardedEvent { Map toJson() { return { - 'reason': reason.toStringValue(), - 'category': category.toStringValue(), + 'reason': reason._toStringValue(), + 'category': category._toStringValue(), 'quantity': quantity, }; } } + +extension _OutcomeExtension on DiscardReason { + String _toStringValue() { + switch (this) { + case DiscardReason.beforeSend: + return 'before_send'; + case DiscardReason.eventProcessor: + return 'event_processor'; + case DiscardReason.sampleRate: + return 'sample_rate'; + case DiscardReason.networkError: + return 'network_error'; + case DiscardReason.queueOverflow: + return 'queue_overflow'; + case DiscardReason.cacheOverflow: + return 'cache_overflow'; + case DiscardReason.rateLimitBackoff: + return 'ratelimit_backoff'; + } + } +} + +extension _DataCategoryExtension on DataCategory { + String _toStringValue() { + switch (this) { + case DataCategory.all: + return '__all__'; + case DataCategory.dataCategoryDefault: + return 'default'; + case DataCategory.error: + return 'error'; + case DataCategory.session: + return 'session'; + case DataCategory.transaction: + return 'transaction'; + case DataCategory.attachment: + return 'attachment'; + case DataCategory.security: + return 'security'; + case DataCategory.unknown: + return 'unknown'; + } + } +} diff --git a/dart/lib/src/http_client/failed_request_client.dart b/dart/lib/src/http_client/failed_request_client.dart index 98df59194f..d86be0328a 100644 --- a/dart/lib/src/http_client/failed_request_client.dart +++ b/dart/lib/src/http_client/failed_request_client.dart @@ -135,7 +135,7 @@ class FailedRequestClient extends BaseClient { // Only check `failedRequestStatusCodes` & `failedRequestTargets` if no exception was thrown. if (exception == null) { - if (!failedRequestStatusCodes.containsStatusCode(statusCode)) { + if (!failedRequestStatusCodes._containsStatusCode(statusCode)) { return; } if (!containsTargetOrMatchesRegExp( @@ -246,7 +246,7 @@ class FailedRequestClient extends BaseClient { } extension _ListX on List { - bool containsStatusCode(int? statusCode) { + bool _containsStatusCode(int? statusCode) { if (statusCode == null) { return false; } diff --git a/dart/lib/src/transport/data_category.dart b/dart/lib/src/transport/data_category.dart index 1843acfacb..37d1969970 100644 --- a/dart/lib/src/transport/data_category.dart +++ b/dart/lib/src/transport/data_category.dart @@ -10,45 +10,3 @@ enum DataCategory { unknown } -extension DataCategoryExtension on DataCategory { - static DataCategory fromStringValue(String stringValue) { - switch (stringValue) { - case '__all__': - return DataCategory.all; - case 'default': - return DataCategory.dataCategoryDefault; - case 'error': - return DataCategory.error; - case 'session': - return DataCategory.session; - case 'transaction': - return DataCategory.transaction; - case 'attachment': - return DataCategory.attachment; - case 'security': - return DataCategory.security; - } - return DataCategory.unknown; - } - - String toStringValue() { - switch (this) { - case DataCategory.all: - return '__all__'; - case DataCategory.dataCategoryDefault: - return 'default'; - case DataCategory.error: - return 'error'; - case DataCategory.session: - return 'session'; - case DataCategory.transaction: - return 'transaction'; - case DataCategory.attachment: - return 'attachment'; - case DataCategory.security: - return 'security'; - case DataCategory.unknown: - return 'unknown'; - } - } -} diff --git a/dart/lib/src/transport/rate_limit_parser.dart b/dart/lib/src/transport/rate_limit_parser.dart index 63f4f179d1..c735fe9ce0 100644 --- a/dart/lib/src/transport/rate_limit_parser.dart +++ b/dart/lib/src/transport/rate_limit_parser.dart @@ -29,7 +29,7 @@ class RateLimitParser { if (allCategories.isNotEmpty) { final categoryValues = allCategories.split(';'); for (final categoryValue in categoryValues) { - final category = DataCategoryExtension.fromStringValue(categoryValue); + final category = _DataCategoryExtension._fromStringValue(categoryValue); if (category != DataCategory.unknown) { rateLimits.add(RateLimit(category, duration)); } @@ -56,3 +56,25 @@ class RateLimitParser { } } } + +extension _DataCategoryExtension on DataCategory { + static DataCategory _fromStringValue(String stringValue) { + switch (stringValue) { + case '__all__': + return DataCategory.all; + case 'default': + return DataCategory.dataCategoryDefault; + case 'error': + return DataCategory.error; + case 'session': + return DataCategory.session; + case 'transaction': + return DataCategory.transaction; + case 'attachment': + return DataCategory.attachment; + case 'security': + return DataCategory.security; + } + return DataCategory.unknown; + } +} diff --git a/dart/lib/src/utils/http_sanitizer.dart b/dart/lib/src/utils/http_sanitizer.dart index c131cc0c4e..2e5de505a9 100644 --- a/dart/lib/src/utils/http_sanitizer.dart +++ b/dart/lib/src/utils/http_sanitizer.dart @@ -60,7 +60,7 @@ class HttpSanitizer { } } -extension UriPath on Uri { +extension _UriPath on Uri { String _urlWithRedactedAuth() { var buffer = ''; if (scheme.isNotEmpty) { @@ -78,6 +78,7 @@ extension UriPath on Uri { } } +@internal extension SanitizedSentryRequest on SentryRequest { SentryRequest sanitized() { final urlDetails = HttpSanitizer.sanitizeUrl(url) ?? UrlDetails(); diff --git a/dart/test/utils/http_sanitizer_test.dart b/dart/test/utils/http_sanitizer_test.dart index f9967c2778..2a4e0a58be 100644 --- a/dart/test/utils/http_sanitizer_test.dart +++ b/dart/test/utils/http_sanitizer_test.dart @@ -182,7 +182,7 @@ void main() { }); } -extension StringExtension on String { +extension _StringExtension on String { String _capitalize() { return "${this[0].toUpperCase()}${substring(1).toLowerCase()}"; } diff --git a/dio/lib/src/failed_request_interceptor.dart b/dio/lib/src/failed_request_interceptor.dart index 60ea4a0133..ecdd8ab2fa 100644 --- a/dio/lib/src/failed_request_interceptor.dart +++ b/dio/lib/src/failed_request_interceptor.dart @@ -27,7 +27,7 @@ class FailedRequestInterceptor extends Interceptor { final captureFailedRequests = _hub.options.captureFailedRequests; final containsStatusCode = - _failedRequestStatusCodes.containsStatusCode(err.response?.statusCode); + _failedRequestStatusCodes._containsStatusCode(err.response?.statusCode); final containsRequestTarget = containsTargetOrMatchesRegExp( _failedRequestTargets, err.requestOptions.path, @@ -46,7 +46,7 @@ class FailedRequestInterceptor extends Interceptor { } extension _ListX on List { - bool containsStatusCode(int? statusCode) { + bool _containsStatusCode(int? statusCode) { if (statusCode == null) { return false; } From c1af05a958a04365a492262290dc5cef2079e32b Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Tue, 1 Aug 2023 10:46:54 +0200 Subject: [PATCH 5/8] format --- dart/lib/src/transport/data_category.dart | 1 - dart/lib/src/transport/rate_limit_parser.dart | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dart/lib/src/transport/data_category.dart b/dart/lib/src/transport/data_category.dart index 37d1969970..38340e2630 100644 --- a/dart/lib/src/transport/data_category.dart +++ b/dart/lib/src/transport/data_category.dart @@ -9,4 +9,3 @@ enum DataCategory { security, unknown } - diff --git a/dart/lib/src/transport/rate_limit_parser.dart b/dart/lib/src/transport/rate_limit_parser.dart index c735fe9ce0..a7ddadc52c 100644 --- a/dart/lib/src/transport/rate_limit_parser.dart +++ b/dart/lib/src/transport/rate_limit_parser.dart @@ -29,7 +29,8 @@ class RateLimitParser { if (allCategories.isNotEmpty) { final categoryValues = allCategories.split(';'); for (final categoryValue in categoryValues) { - final category = _DataCategoryExtension._fromStringValue(categoryValue); + final category = + _DataCategoryExtension._fromStringValue(categoryValue); if (category != DataCategory.unknown) { rateLimits.add(RateLimit(category, duration)); } From 86a4917d706f4c8740a36ee3726397ec9cf24b4c Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Tue, 1 Aug 2023 10:48:00 +0200 Subject: [PATCH 6/8] add changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48ec8862bd..63952c27d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Mark exceptions not handled by the user as `handled: false` ([#1535](https://github.com/getsentry/sentry-dart/pull/1535)) - This will affect your release health data, and is therefore considered a breaking change. +- Do not leak extensions of external classes ([#1576](https://github.com/getsentry/sentry-dart/pull/1576)) ## 7.9.0 From 8a055f740300f35ea0a85abc4a437872574cab56 Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Mon, 14 Aug 2023 16:05:33 +0200 Subject: [PATCH 7/8] make helper method static --- dart/lib/src/protocol/sentry_request.dart | 7 ++++--- dart/lib/src/protocol/sentry_response.dart | 8 +++++--- dart/lib/src/utils/iterable_utils.dart | 12 +++++------- dart/test/sentry_client_test.dart | 7 ++++--- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/dart/lib/src/protocol/sentry_request.dart b/dart/lib/src/protocol/sentry_request.dart index fb89fb5ffa..b5ee7d003c 100644 --- a/dart/lib/src/protocol/sentry_request.dart +++ b/dart/lib/src/protocol/sentry_request.dart @@ -85,9 +85,10 @@ class SentryRequest { _headers = headers != null ? Map.from(headers) : null, // Look for a 'Set-Cookie' header (case insensitive) if not given. cookies = cookies ?? - IterableUtils(headers?.entries) - .firstWhereOrNull((e) => e.key.toLowerCase() == 'cookie') - ?.value, + IterableUtils.firstWhereOrNull( + headers?.entries, + (MapEntry e) => e.key.toLowerCase() == 'cookie', + )?.value, _env = env != null ? Map.from(env) : null, _other = other != null ? Map.from(other) : null; diff --git a/dart/lib/src/protocol/sentry_response.dart b/dart/lib/src/protocol/sentry_response.dart index 5dbc12b8c6..6008ea8730 100644 --- a/dart/lib/src/protocol/sentry_response.dart +++ b/dart/lib/src/protocol/sentry_response.dart @@ -53,9 +53,11 @@ class SentryResponse { _headers = headers != null ? Map.from(headers) : null, // Look for a 'Set-Cookie' header (case insensitive) if not given. cookies = cookies ?? - IterableUtils(headers?.entries) - .firstWhereOrNull((e) => e.key.toLowerCase() == 'set-cookie') - ?.value; + IterableUtils.firstWhereOrNull( + headers?.entries, + (MapEntry e) => + e.key.toLowerCase() == 'set-cookie', + )?.value; /// Deserializes a [SentryResponse] from JSON [Map]. factory SentryResponse.fromJson(Map json) { diff --git a/dart/lib/src/utils/iterable_utils.dart b/dart/lib/src/utils/iterable_utils.dart index 20a875da9c..c2fb5e5c69 100644 --- a/dart/lib/src/utils/iterable_utils.dart +++ b/dart/lib/src/utils/iterable_utils.dart @@ -1,13 +1,11 @@ import 'package:meta/meta.dart'; @internal -class IterableUtils { - IterableUtils(this.iterable); - - Iterable? iterable; - - T? firstWhereOrNull(bool Function(T item) test) { - final iterable = this.iterable; +class IterableUtils { + static T? firstWhereOrNull( + Iterable? iterable, + bool Function(T item) test, + ) { if (iterable == null) { return null; } diff --git a/dart/test/sentry_client_test.dart b/dart/test/sentry_client_test.dart index f622bace28..5d1c543c00 100644 --- a/dart/test/sentry_client_test.dart +++ b/dart/test/sentry_client_test.dart @@ -1427,9 +1427,10 @@ void main() { await sut.captureEvent(fakeEvent, hint: hint); final capturedEnvelope = (fixture.transport).envelopes.first; - final attachmentItem = IterableUtils(capturedEnvelope.items) - .firstWhereOrNull( - (element) => element.header.type == SentryItemType.attachment); + final attachmentItem = IterableUtils.firstWhereOrNull( + capturedEnvelope.items, + (SentryEnvelopeItem e) => e.header.type == SentryItemType.attachment, + ); expect(attachmentItem?.header.attachmentType, SentryAttachment.typeAttachmentDefault); }); From 7630cb0d7a93e0b3f2fb912f4f882624757c2cb5 Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Tue, 22 Aug 2023 10:46:42 +0200 Subject: [PATCH 8/8] update changelog --- CHANGELOG.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b931854afe..7942e0deef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,12 +6,11 @@ - Mark exceptions not handled by the user as `handled: false` ([#1535](https://github.com/getsentry/sentry-dart/pull/1535)) - This will affect your release health data, and is therefore considered a breaking change. -- Do not leak extensions of external classes ([#1576](https://github.com/getsentry/sentry-dart/pull/1576)) - - Refrain from overwriting the span status for unfinished spans ([#1577](https://github.com/getsentry/sentry-dart/pull/1577)) - Older self-hosted sentry instances will drop transactions containing unfinished spans. - This change was introduced in [relay/#1690](https://github.com/getsentry/relay/pull/1690) and released with [22.12.0](https://github.com/getsentry/relay/releases/tag/22.12.0) - +- Do not leak extensions of external classes ([#1576](https://github.com/getsentry/sentry-dart/pull/1576)) + ## 7.9.0 ### Features