diff --git a/CHANGELOG.md b/CHANGELOG.md index c60dd83616..8bf320db48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ ### Breaking Changes - Android `minSdkVersion` is now 19 (Flutter already defines 19-20 as best effort) +- Deprecate `extra` in favor of `contexts` ([#1435](https://github.com/getsentry/sentry-dart/pull/1435)) ## 7.5.2 diff --git a/dart/example/bin/event_example.dart b/dart/example/bin/event_example.dart index 8eeb4b8ad1..e7ba4c4dd6 100644 --- a/dart/example/bin/event_example.dart +++ b/dart/example/bin/event_example.dart @@ -7,6 +7,7 @@ final event = SentryEvent( environment: 'Test', message: SentryMessage('This is an example Dart event.'), tags: const {'project-id': '7371'}, + // ignore: deprecated_member_use extra: const {'section': '1'}, // fingerprint: const ['example-dart'], fingerprint forces events to group together user: SentryUser( @@ -14,6 +15,7 @@ final event = SentryEvent( username: 'first-user', email: 'first@user.lan', // ipAddress: '127.0.0.1', sendDefaultPii feature is enabled + // ignore: deprecated_member_use extras: {'first-sign-in': '2020-01-01'}, ), breadcrumbs: [ diff --git a/dart/example/bin/example.dart b/dart/example/bin/example.dart index 65ed722edd..5163f341f7 100644 --- a/dart/example/bin/example.dart +++ b/dart/example/bin/example.dart @@ -45,6 +45,7 @@ Future runApp() async { username: 'first-user', email: 'first@user.lan', // ipAddress: '127.0.0.1', sendDefaultPii feature is enabled + // ignore: deprecated_member_use extras: {'first-sign-in': '2020-01-01'}, )); scope diff --git a/dart/example_web/web/event.dart b/dart/example_web/web/event.dart index 4bdc2fe94b..6e3e8b3e0b 100644 --- a/dart/example_web/web/event.dart +++ b/dart/example_web/web/event.dart @@ -7,6 +7,7 @@ final event = SentryEvent( environment: 'Test', message: SentryMessage('This is an example Dart event.'), tags: const {'project-id': '7371'}, + // ignore: deprecated_member_use, deprecated_member_use_from_same_package extra: const {'section': '1'}, // fingerprint: const ['example-dart'], user: SentryUser( diff --git a/dart/lib/src/protocol/sentry_event.dart b/dart/lib/src/protocol/sentry_event.dart index 44fdcccbb3..946d49edd6 100644 --- a/dart/lib/src/protocol/sentry_event.dart +++ b/dart/lib/src/protocol/sentry_event.dart @@ -13,7 +13,8 @@ class SentryEvent with SentryEventLike { DateTime? timestamp, Map? modules, Map? tags, - Map? extra, + @Deprecated('Additional Data is deprecated in favor of structured [Contexts] and should be avoided when possible') + Map? extra, List? fingerprint, List? breadcrumbs, List? exceptions, @@ -40,6 +41,7 @@ class SentryEvent with SentryEventLike { contexts = contexts ?? Contexts(), modules = modules != null ? Map.from(modules) : null, tags = tags != null ? Map.from(tags) : null, + // ignore: deprecated_member_use_from_same_package extra = extra != null ? Map.from(extra) : null, fingerprint = fingerprint != null ? List.from(fingerprint) : null, breadcrumbs = breadcrumbs != null ? List.from(breadcrumbs) : null, @@ -128,6 +130,8 @@ class SentryEvent with SentryEventLike { /// /// Sentry.io docs do not talk about restrictions on the values, other than /// they must be JSON-serializable. + @Deprecated( + 'Additional Data is deprecated in favor of structured [Contexts] and should be avoided when possible') final Map? extra; /// List of breadcrumbs for this event. @@ -201,7 +205,8 @@ class SentryEvent with SentryEventLike { SentryLevel? level, String? culprit, Map? tags, - Map? extra, + @Deprecated('Additional Data is deprecated in favor of structured [Contexts] and should be avoided when possible') + Map? extra, List? fingerprint, SentryUser? user, Contexts? contexts, @@ -229,6 +234,7 @@ class SentryEvent with SentryEventLike { level: level ?? this.level, culprit: culprit ?? this.culprit, tags: (tags != null ? Map.from(tags) : null) ?? this.tags, + // ignore: deprecated_member_use_from_same_package extra: (extra != null ? Map.from(extra) : null) ?? this.extra, fingerprint: (fingerprint != null ? List.from(fingerprint) : null) ?? this.fingerprint, @@ -286,6 +292,7 @@ class SentryEvent with SentryEventLike { timestampJson != null ? DateTime.tryParse(timestampJson) : null, modules: modules, tags: tags, + // ignore: deprecated_member_use_from_same_package extra: extra, fingerprint: fingerprintJson?.map((e) => e as String).toList(growable: false), @@ -374,6 +381,7 @@ class SentryEvent with SentryEventLike { if (level != null) 'level': level!.name, if (culprit != null) 'culprit': culprit, if (tags?.isNotEmpty ?? false) 'tags': tags, + // ignore: deprecated_member_use_from_same_package if (extra?.isNotEmpty ?? false) 'extra': extra, if (type != null) 'type': type, if (fingerprint?.isNotEmpty ?? false) 'fingerprint': fingerprint, diff --git a/dart/lib/src/protocol/sentry_transaction.dart b/dart/lib/src/protocol/sentry_transaction.dart index 74f30ea67a..eae52f9450 100644 --- a/dart/lib/src/protocol/sentry_transaction.dart +++ b/dart/lib/src/protocol/sentry_transaction.dart @@ -26,7 +26,8 @@ class SentryTransaction extends SentryEvent { String? transaction, dynamic throwable, Map? tags, - Map? extra, + @Deprecated('Additional Data is deprecated in favor of structured [Contexts] and should be avoided when possible') + Map? extra, SentryUser? user, Contexts? contexts, List? breadcrumbs, @@ -46,6 +47,7 @@ class SentryTransaction extends SentryEvent { transaction: transaction ?? _tracer.name, throwable: throwable ?? _tracer.throwable, tags: tags ?? _tracer.tags, + // ignore: deprecated_member_use_from_same_package extra: extra ?? _tracer.data, user: user, contexts: contexts, @@ -116,7 +118,8 @@ class SentryTransaction extends SentryEvent { SentryLevel? level, String? culprit, Map? tags, - Map? extra, + @Deprecated('Additional Data is deprecated in favor of structured [Contexts] and should be avoided when possible') + Map? extra, List? fingerprint, SentryUser? user, Contexts? contexts, @@ -142,6 +145,7 @@ class SentryTransaction extends SentryEvent { transaction: transaction ?? this.transaction, throwable: throwable ?? this.throwable, tags: (tags != null ? Map.from(tags) : null) ?? this.tags, + // ignore: deprecated_member_use_from_same_package extra: (extra != null ? Map.from(extra) : null) ?? this.extra, user: user ?? this.user, contexts: contexts ?? this.contexts, diff --git a/dart/lib/src/scope.dart b/dart/lib/src/scope.dart index fc7dcf669f..f9cb3796aa 100644 --- a/dart/lib/src/scope.dart +++ b/dart/lib/src/scope.dart @@ -285,6 +285,7 @@ class Scope { ? event.breadcrumbs : List.from(_breadcrumbs), tags: tags.isNotEmpty ? _mergeEventTags(event) : event.tags, + // ignore: deprecated_member_use_from_same_package extra: extra.isNotEmpty ? _mergeEventExtra(event) : event.extra, ); @@ -362,6 +363,7 @@ class Scope { /// the event extra will be kept. Map _mergeEventExtra(SentryEvent event) => extra.map((key, value) => MapEntry(key, value)) + // ignore: deprecated_member_use_from_same_package ..addAll(event.extra ?? {}); /// If scope and event have a user, the user of the event takes diff --git a/dart/test/mocks.dart b/dart/test/mocks.dart index 3711db437b..82430d96e8 100644 --- a/dart/test/mocks.dart +++ b/dart/test/mocks.dart @@ -22,6 +22,7 @@ final fakeEvent = SentryEvent( transaction: '/example/app', level: SentryLevel.warning, tags: const {'project-id': '7371'}, + // ignore: deprecated_member_use_from_same_package extra: const {'company-name': 'Dart Inc'}, fingerprint: const ['example-dart'], modules: const {'module1': 'factory'}, diff --git a/dart/test/scope_test.dart b/dart/test/scope_test.dart index 5ab75e56b9..e8d2e08bf9 100644 --- a/dart/test/scope_test.dart +++ b/dart/test/scope_test.dart @@ -389,6 +389,7 @@ void main() { test('apply context to event', () async { final event = SentryEvent( tags: const {'etag': '987'}, + // ignore: deprecated_member_use_from_same_package extra: const {'e-infos': 'abc'}, ); final scope = Scope(SentryOptions(dsn: fakeDsn)) @@ -413,7 +414,9 @@ void main() { expect(updatedEvent?.tags, {'etag': '987', 'build': '579', 'page-locale': 'en-us'}); expect( - updatedEvent?.extra, {'e-infos': 'abc', 'company-name': 'Dart Inc'}); + // ignore: deprecated_member_use_from_same_package + updatedEvent?.extra, + {'e-infos': 'abc', 'company-name': 'Dart Inc'}); expect(updatedEvent?.contexts['theme'], {'value': 'material'}); }); diff --git a/dart/test/sentry_client_test.dart b/dart/test/sentry_client_test.dart index c055f3449f..484dd009a5 100644 --- a/dart/test/sentry_client_test.dart +++ b/dart/test/sentry_client_test.dart @@ -672,6 +672,7 @@ void main() { final event = SentryEvent( tags: const {eventTagKey: eventTagValue}, + // ignore: deprecated_member_use_from_same_package extra: const {eventExtraKey: eventExtraValue}, modules: const {eventExtraKey: eventExtraValue}, level: SentryLevel.warning, @@ -709,6 +710,7 @@ void main() { scopeTagKey: scopeTagValue, eventTagKey: eventTagValue, }); + // ignore: deprecated_member_use_from_same_package expect(capturedEvent.extra, { scopeExtraKey: scopeExtraValue, eventExtraKey: eventExtraValue, @@ -1018,6 +1020,7 @@ void main() { final event = await eventFromEnvelope(capturedEnvelope); expect(event.tags!.containsKey('theme'), true); + // ignore: deprecated_member_use_from_same_package expect(event.extra!.containsKey('host'), true); expect(event.modules!.containsKey('core'), true); expect(event.sdk!.integrations.contains('testIntegration'), true); @@ -1057,6 +1060,7 @@ void main() { fixture.options.addEventProcessor(FunctionEventProcessor( (event, {hint}) => event ..tags!.addAll({'theme': 'material'}) + // ignore: deprecated_member_use_from_same_package ..extra!['host'] = '0.0.0.1' ..modules!.addAll({'core': '1.0'}) ..breadcrumbs!.add(Breadcrumb(message: 'processor crumb')) @@ -1074,6 +1078,7 @@ void main() { final event = await eventFromEnvelope(capturedEnvelope); expect(event.tags!.containsKey('theme'), true); + // ignore: deprecated_member_use_from_same_package expect(event.extra!.containsKey('host'), true); expect(event.modules!.containsKey('core'), true); expect(event.sdk!.integrations.contains('testIntegration'), true); @@ -1620,6 +1625,7 @@ Future asyncBeforeSendTransactionCallbackDropEvent( SentryEvent? beforeSendCallback(SentryEvent event, {Hint? hint}) { return event ..tags!.addAll({'theme': 'material'}) + // ignore: deprecated_member_use_from_same_package ..extra!['host'] = '0.0.0.1' ..modules!.addAll({'core': '1.0'}) ..breadcrumbs!.add(Breadcrumb(message: 'processor crumb')) @@ -1632,6 +1638,7 @@ SentryTransaction? beforeSendTransactionCallback( SentryTransaction transaction) { return transaction ..tags!.addAll({'theme': 'material'}) + // ignore: deprecated_member_use_from_same_package ..extra!['host'] = '0.0.0.1' ..sdk!.addIntegration('testIntegration') ..sdk!.addPackage('test-pkg', '1.0') diff --git a/dart/test/sentry_envelope_test.dart b/dart/test/sentry_envelope_test.dart index 30ae7b0190..063be42ba9 100644 --- a/dart/test/sentry_envelope_test.dart +++ b/dart/test/sentry_envelope_test.dart @@ -171,6 +171,7 @@ void main() { // This test passes if no exceptions are thrown, thus no asserts. // This is a test for https://github.com/getsentry/sentry-dart/issues/523 test('serialize with non-serializable class', () async { + // ignore: deprecated_member_use_from_same_package final event = SentryEvent(extra: {'non-ecodable': NonEncodable()}); final sut = SentryEnvelope.fromEvent( event, diff --git a/dart/test/sentry_event_test.dart b/dart/test/sentry_event_test.dart index 2fb1a7d451..58fb946110 100644 --- a/dart/test/sentry_event_test.dart +++ b/dart/test/sentry_event_test.dart @@ -97,6 +97,7 @@ void main() { expect(sentryEvent.level, isNull); expect(sentryEvent.culprit, isNull); expect(sentryEvent.tags, isNull); + // ignore: deprecated_member_use_from_same_package expect(sentryEvent.extra, isNull); expect(sentryEvent.breadcrumbs, isNull); expect(sentryEvent.user, isNull); @@ -199,6 +200,7 @@ void main() { 'a': 'b', 'c': 'd', }, + // ignore: deprecated_member_use_from_same_package extra: const { 'e': 'f', 'g': 2, @@ -441,6 +443,7 @@ void main() { exceptions: [SentryException(type: null, value: null)], threads: [SentryThread(stacktrace: SentryStackTrace(frames: []))], tags: {}, + // ignore: deprecated_member_use_from_same_package extra: {}, contexts: Contexts(), fingerprint: [], diff --git a/dart/test/sentry_tracer_test.dart b/dart/test/sentry_tracer_test.dart index c66a6a1524..e0818e71fa 100644 --- a/dart/test/sentry_tracer_test.dart +++ b/dart/test/sentry_tracer_test.dart @@ -101,6 +101,7 @@ void main() { final tr = fixture.hub.captureTransactionCalls.first; + // ignore: deprecated_member_use_from_same_package expect(tr.transaction.extra?['test'], 'test'); }); @@ -114,6 +115,7 @@ void main() { final tr = fixture.hub.captureTransactionCalls.first; + // ignore: deprecated_member_use_from_same_package expect(tr.transaction.extra?['test'], isNull); }); @@ -126,6 +128,7 @@ void main() { final tr = fixture.hub.captureTransactionCalls.first; + // ignore: deprecated_member_use_from_same_package expect(tr.transaction.extra?['test'], {'key': 'value'}); }); diff --git a/dio/test/mocks.dart b/dio/test/mocks.dart index 05ba6639cb..83454cbfb3 100644 --- a/dio/test/mocks.dart +++ b/dio/test/mocks.dart @@ -22,6 +22,7 @@ final fakeEvent = SentryEvent( transaction: '/example/app', level: SentryLevel.warning, tags: const {'project-id': '7371'}, + // ignore: deprecated_member_use extra: const {'company-name': 'Dart Inc'}, fingerprint: const ['example-dart'], modules: const {'module1': 'factory'}, diff --git a/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart b/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart index 7a5ba16310..571625f31c 100644 --- a/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart +++ b/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart @@ -121,6 +121,8 @@ class FlutterEnricherEventProcessor implements EventProcessor { final defaultRouteName = _window?.defaultRouteName; // A FlutterEngine has no renderViewElement if it was started or is // accessed from an isolate different to the main isolate. + + // to keep compatibility with older versions // ignore: deprecated_member_use final hasRenderView = _widgetsBinding?.renderViewElement != null; diff --git a/flutter/lib/src/integrations/load_contexts_integration.dart b/flutter/lib/src/integrations/load_contexts_integration.dart index 2c7e7e686b..710d7d0924 100644 --- a/flutter/lib/src/integrations/load_contexts_integration.dart +++ b/flutter/lib/src/integrations/load_contexts_integration.dart @@ -100,6 +100,7 @@ class _LoadContextsIntegrationEventProcessor implements EventProcessor { final extraMap = infos['extra'] as Map?; if (extraMap != null && extraMap.isNotEmpty) { + // ignore: deprecated_member_use final extras = event.extra ?? {}; final newExtras = Map.from(extraMap); @@ -108,6 +109,8 @@ class _LoadContextsIntegrationEventProcessor implements EventProcessor { extras[extra.key] = extra.value; } } + + // ignore: deprecated_member_use event = event.copyWith(extra: extras); } diff --git a/flutter/lib/src/view_hierarchy/sentry_tree_walker.dart b/flutter/lib/src/view_hierarchy/sentry_tree_walker.dart index 5ca6ec09fa..2a85bf49be 100644 --- a/flutter/lib/src/view_hierarchy/sentry_tree_walker.dart +++ b/flutter/lib/src/view_hierarchy/sentry_tree_walker.dart @@ -293,6 +293,7 @@ class _TreeWalker { } SentryViewHierarchy? walkWidgetTree(WidgetsBinding instance) { + // to keep compatibility with older versions // ignore: deprecated_member_use final rootElement = instance.renderViewElement; if (rootElement == null) { diff --git a/flutter/test/integrations/load_contexts_integrations_test.dart b/flutter/test/integrations/load_contexts_integrations_test.dart index 8af94e787c..c6bb98f0b7 100644 --- a/flutter/test/integrations/load_contexts_integrations_test.dart +++ b/flutter/test/integrations/load_contexts_integrations_test.dart @@ -50,6 +50,7 @@ void main() { packages: packages, ), tags: tags, + // ignore: deprecated_member_use extra: extra, user: user, dist: dist, @@ -312,8 +313,11 @@ void main() { final e = getEvent(extra: {'key': 'flutter', 'key-a': 'flutter'}); final event = await fixture.options.eventProcessors.first.apply(e); + // ignore: deprecated_member_use expect(event?.extra?['key'], 'flutter'); + // ignore: deprecated_member_use expect(event?.extra?['key-a'], 'flutter'); + // ignore: deprecated_member_use expect(event?.extra?['key-b'], 'native'); }); diff --git a/logging/lib/src/extension.dart b/logging/lib/src/extension.dart index 62a78a0b7d..8ea4a9e19d 100644 --- a/logging/lib/src/extension.dart +++ b/logging/lib/src/extension.dart @@ -28,6 +28,7 @@ extension LogRecordX on LogRecord { level: level.toSentryLevel(), message: SentryMessage(message), throwable: error, + // ignore: deprecated_member_use extra: { if (object != null) 'LogRecord.object': object!, 'LogRecord.sequenceNumber': sequenceNumber, diff --git a/logging/test/logging_integration_test.dart b/logging/test/logging_integration_test.dart index edeef57e5d..5ddb50cf3e 100644 --- a/logging/test/logging_integration_test.dart +++ b/logging/test/logging_integration_test.dart @@ -144,6 +144,7 @@ void main() { expect(event.level, SentryLevel.warning); expect(event.logger, 'FooBarLogger'); expect(event.throwable, exception); + // ignore: deprecated_member_use expect(event.extra?['LogRecord.sequenceNumber'], isNotNull); expect(fixture.hub.events.first.stackTrace, stackTrace); });