diff --git a/docs/platforms/dart/guides/flutter/migration.mdx b/docs/platforms/dart/guides/flutter/migration.mdx index 9668157805786..7cfea40713b24 100644 --- a/docs/platforms/dart/guides/flutter/migration.mdx +++ b/docs/platforms/dart/guides/flutter/migration.mdx @@ -1,8 +1,205 @@ --- title: Migration Guide sidebar_order: 8000 +description: "Learn how to migrate your Flutter application between major versions of the Sentry SDK." --- +## Migrating From `sentry_flutter` `9.x` to `sentry_flutter` `10.x` + + + +This guide is a draft for the upcoming v10 release. It reflects `v10-branch` through `10.0.0-alpha.5` and may change before the stable release. + + + +Version 10 raises the minimum supported platform versions, removes deprecated APIs, and changes several telemetry defaults. The changes below include the core Dart SDK changes that affect Flutter applications. + +### Minimum Supported Versions + +Update your local development environment and CI before upgrading: + +| Dependency | Minimum Version | +| ----------------------- | --------------- | +| Dart | `3.12.0` | +| Flutter | `3.44.0` | +| iOS deployment target | `15.0` | +| macOS deployment target | `12.0` | + +Update any directly declared Sentry integration packages, such as `sentry_dio` or `sentry_logging`, to the matching v10 release as well. While testing the prerelease, use `10.0.0-alpha.5`: + +```yaml {filename:pubspec.yaml} +dependencies: + sentry_flutter: 10.0.0-alpha.5 +``` + +The integration dependency constraints also change: + +| Package | Required Dependency | +| ---------------- | ------------------------------------------------------- | +| `sentry_flutter` | `jni >=1.0.0 <1.1.0` (previously `0.14.2`) | +| `sentry_dio` | `dio ^5.8.0` (previously `^5.2.0`) | +| `sentry_link` | `gql_link >=0.5.1 <2.0.0` (previously `>=0.5.0 <2.0.0`) | + +Update conflicting direct dependencies or dependency overrides before running `flutter pub get`. + +### Android Builds Use Flutter's Kotlin Support + +The Sentry Flutter plugin no longer applies or bundles its own Kotlin Gradle Plugin. It relies on Flutter 3.44's Kotlin support. If you customize Android build configuration, update it for Flutter 3.44 rather than relying on Sentry to supply Kotlin. This change does not require upgrading your app to AGP 9. + +### Apple Builds Use Swift Package Manager + +The Sentry Flutter plugin no longer supports CocoaPods. On iOS and macOS, it uses Swift Package Manager to install the native Sentry Cocoa SDK, which has been upgraded to v9. If you initialize Sentry separately in native code or call its Swift/Objective-C APIs directly, also review the [Sentry Cocoa v8-to-v9 migration guide](/platforms/apple/migration/v8-to-v9/). + +Flutter 3.44 enables Swift Package Manager by default and migrates your project when you run the app. If you previously disabled it, re-enable it and remove any project-level `enable-swift-package-manager: false` setting: + +```bash +flutter config --enable-swift-package-manager +flutter pub get +``` + +Set the iOS and macOS deployment targets in Xcode to the minimum versions listed above. For custom targets, flavors, or projects that don't migrate automatically, follow [Flutter's Swift Package Manager migration instructions](https://docs.flutter.dev/packages-and-plugins/swift-package-manager/for-app-developers/). + +Other Flutter plugins may still require CocoaPods. Only remove your application's CocoaPods integration once all of its dependencies support Swift Package Manager. + +### Logs and Metrics Are Always Enabled + +Remove assignments to `options.enableLogs` and `options.enableMetrics`. These options no longer exist. Calls to `Sentry.logger` and `Sentry.metrics` send telemetry without an enable flag. To filter logs or metrics, return `null` from `beforeSendLog` or `beforeSendMetric`. + +If you use `sentry_logging`, adding `LoggingIntegration` now also forwards records as Sentry logs, with a default minimum level of `Level.INFO`. If you previously disabled logs and want to keep only breadcrumbs and error events, set `minSentryLogLevel` to `Level.OFF`: + +```dart +import 'package:logging/logging.dart'; +import 'package:sentry_logging/sentry_logging.dart'; + +// Inside your SentryFlutter.init options callback: +options.addIntegration(LoggingIntegration(minSentryLogLevel: Level.OFF)); +``` + +The `Sentry.logger` and `Sentry.logger.fmt` methods now return `void`. Remove `await` from log calls. Update custom implementations of `SentryLogger` and `SentryLoggerFormatter` to match these return types. Custom `Hub.captureLog` overrides now return `Future` instead of `FutureOr`. + +Replace `SentryLogAttribute` with `SentryAttribute`, using the same typed factories such as `SentryAttribute.string(...)`. If you construct `SentryLog` directly, its `traceId` is now a required, non-nullable `SentryId`. Prefer `Sentry.logger` for application logging so the SDK supplies trace context. + +### Telemetry Callbacks Receive a Hint + +Add a second `Hint` parameter to `beforeSendLog`, `beforeSendMetric`, and `beforeSendSpan`, even if you don't use it: + +```dart +options.beforeSendLog = (log, hint) { + return log; +}; + +options.beforeSendMetric = (metric, hint) { + return metric; +}; + +options.beforeSendSpan = (span, hint) { + span.removeAttribute('private.attribute'); +}; +``` + +`beforeSendSpan` modifies the span in place. It cannot drop spans by returning `null`; use `options.ignoreSpans` to filter spans in stream mode. + +### App Start Is a Standalone Trace + +On Android and iOS, app start is now reported as its own `app.start` root when tracing is enabled. It is no longer attached to the initial `ui.load` transaction and has its own sampling decision. + +Remove `options.enableStandaloneAppStartTracing` assignments. The standalone path is now the default, and the option has been removed. Update custom sampling rules, dashboards, and alerts that assume app start belongs to the first navigation transaction. A sampler that only accepts `ui.load` roots may exclude app start. + +If startup work continues past the first frame, call `SentryFlutter.extendAppStart()` before the first frame renders and `await SentryFlutter.finishExtendedAppStart()` when that work finishes. An extension that reaches the 30-second app-start deadline is dropped, and the reported duration falls back to the first frame. + +Transaction mode (`SentryTraceLifecycle.static`) remains the default. Upgrading to v10 does not require switching to stream mode. If you choose to switch, follow the stream mode migration guide and use the two-parameter `beforeSendSpan` signature shown above. + +### Native Failed Requests Are Opt-In + +On iOS and macOS, `captureNativeFailedRequests` now defaults to `false` and no longer accepts `null`. It no longer falls back to `captureFailedRequests`. + +To continue capturing failed HTTP requests made by the native SDK's network instrumentation, opt in explicitly: + +```dart +options.captureNativeFailedRequests = true; +``` + +Dart-side failed request capture through `SentryHttpClient` and `sentry_dio` is still controlled independently by `captureFailedRequests`, which defaults to `true`. + +### Profiling and Deprecated APIs Are Removed + +Remove `options.profilesSampleRate`. The Flutter SDK no longer captures profiles, and there is no replacement profiling option in v10. + +Update code that uses the following APIs: + +| Removed or Internal API | Migration | +| --------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `SentryFeedbackWidget` | Use `SentryFeedbackForm`. | +| Deprecated `copyWith(...)` methods on SDK data classes | Assign mutable fields directly. | +| Deprecated protocol `clone()` methods | Stop calling them; remaining SDK clone helpers are internal. Construct a new object explicitly if you need an independent copy. | +| `PerformanceCollector`, `PerformanceContinuousCollector`, `options.performanceCollectors`, `options.addPerformanceCollector(...)` | Remove custom collector registration. These deprecated APIs have been removed. | +| `BindingWrapper`, `options.bindingUtils` | Remove custom binding-wrapper overrides. `SentryWidgetsFlutterBinding` remains public. | +| `options.log`, `SdkLogCallback` | Remove usage of these diagnostic logging APIs. Use `options.debug` and `options.diagnosticLevel` to configure SDK diagnostics, or `Sentry.logger` for application logs. | + +The `SentryEventLike` mixin has also been removed with `copyWith`. Use `SentryEvent` as the common type for events and transactions (`SentryTransaction` extends `SentryEvent`). + +`Sentry.clone()`, `Hub.clone()`, and `Scope.clone()` are now internal APIs. Remove direct calls to them. For capture-specific context, use the capture method's `withScope` callback. + +For example, mutate events in `beforeSend` instead of using `copyWith`: + +```dart +options.beforeSend = (event, hint) { + event.release = 'my-release'; + return event; +}; +``` + +### Feature Flags Use the Current Scope + +Feature flag evaluations now belong to the current hub and scope, rather than `FeatureFlagsIntegration`. If you accessed that integration directly, replace those calls with `await Sentry.addFeatureFlag('flag-name', true)`. + +Existing calls to `Sentry.addFeatureFlag` continue to work. Custom `Hub` implementations must implement `addFeatureFlag(String flag, bool result)`. + +### Span Attribute Names Have Changed + +Update queries, dashboards, alerts, and callbacks that read the old attribute keys: + +| Previous Attribute | v10 Attribute | Affected Instrumentation | +| ------------------------------ | ------------------------- | ------------------------------ | +| `db.system` | `db.system.name` | Database integrations | +| `db.name` | `db.namespace` | Drift, Hive, Isar, and sqflite | +| `db.operation` | `db.operation.name` | Supabase | +| `db.table` | `db.collection.name` | Supabase | +| `db.collection` | `db.collection.name` | Isar | +| `url` | `url.full` | HTTP spans | +| `http.response_content_length` | `http.response.body.size` | HTTP spans | +| `app_start_type` | `app.vitals.start.type` | App start | + +Drift's database system value changes from `db.sqlite` to `sqlite`. Supabase replaces the raw filter list under `db.query` and the SQL under `db.sql.query` with a parameterized SQL statement under `db.query.text`, and adds `db.query.summary`. The SQL statement uses placeholders for values and is emitted regardless of `sendDefaultPii`. + +The `sentry_file` integration no longer emits `file.async`. `SentrySpanData` has been removed. If you referenced this internal class, use the attribute strings listed above in application code. `SemanticAttributesConstants` and `ProposedSemanticAttributes` are also internal APIs. + +For custom code that used internal constants, the old `appApp*`, `osBuild`, `deviceConnectionType`, `deviceLocale`, and `deviceTimezone` constants have been removed. Use the corresponding attribute strings: `app.build`, `app.identifier`, `app.name`, `app.start_time`, `app.version`, `os.build_id`, `network.connection.type`, `culture.locale`, and `culture.timezone`. The `appVitalsStartValue` constant moves to `ProposedSemanticAttributes`; its wire key remains `app.vitals.start.value`. + +Database breadcrumb data also uses `db.system.name` and `db.namespace` instead of `db.system` and `db.name` in Hive, Isar, and sqflite. Update `beforeBreadcrumb` callbacks that read these fields. + +### Error Processing and Release Health + +Error sampling through `sampleRate` now happens after event processors and `beforeSend`. These callbacks run even for events that are subsequently sampled out, so review callbacks that perform expensive work or have side effects. An event dropped by `beforeSend` is reported as a `before_send` discard rather than a `sample_rate` discard. + +On Android, iOS, and macOS, unhandled Flutter errors now mark sessions as unhandled rather than crashed. Unhandled errors dropped by `sampleRate` also affect release health. Review release-health comparisons across the upgrade because session classification and sampling behavior have changed. + +### HTTP Error Capture and Grouping + +Review HTTP error filters, grouping rules, and alert volumes after upgrading: + +- `SentryHttpClient` reports failed HTTP status responses with the stable exception type `SentryHttpClientError`, and its message no longer starts with `Exception:`. +- `sentry_dio` uses the stable exception type `DioException`, including in obfuscated builds. Default error messages become `HTTP Client Error with status code: ` or `HTTP Client Error: `. Custom Dio string builders are preserved. +- `sentry_dio` now captures connection failures without a status code, such as timeouts, DNS failures, and certificate errors, when failed-request capture is enabled and the target matches. Caller-initiated cancellations without a status code are excluded. +- `sentry_dio` matches `failedRequestTargets` against the resolved full URL instead of the relative request path. Update patterns that assumed a path-only value. +- `sentry_supabase` uses the stable exception type `SentrySupabaseClientError`, and its message no longer starts with `Exception:`. + +Dio events now include response status and metadata in `event.contexts.response`; response bodies remain on `hint.response`. Failed-request capture through `SentryHttpClient` and Dio excludes requests to the configured DSN host to prevent recursive error reporting. + +### Sensitive Content Masking + +The SDK now masks Flutter `SensitiveContent` widgets marked `sensitive` or `autoSensitive` by default in Session Replay and screenshots. A `notSensitive` widget still goes through the other masking rules; it does not automatically unmask its contents. Review captured output if your app uses these widgets with custom privacy rules. + ## Migrating from `sentry_flutter` `8.x` to `sentry_flutter` `9.x` ### General