diff --git a/CHANGELOG.md b/CHANGELOG.md index 32ea957b22..291f37989a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +### Features + +- Add `nativeDatabasePath` option to `SentryFlutterOptions` to set the database path for Sentry Native ([#3236](https://github.com/getsentry/sentry-dart/pull/3236)) + ## 9.7.0-beta.3 ### Fixes diff --git a/packages/flutter/ffi-native.yaml b/packages/flutter/ffi-native.yaml index cdb28b223b..9527530c3b 100644 --- a/packages/flutter/ffi-native.yaml +++ b/packages/flutter/ffi-native.yaml @@ -19,6 +19,7 @@ functions: - sentry_options_set_dist - sentry_options_set_max_breadcrumbs - sentry_options_set_handler_path + - sentry_options_set_database_path - sentry_set_user - sentry_remove_user - sentry_add_breadcrumb diff --git a/packages/flutter/lib/src/native/c/binding.dart b/packages/flutter/lib/src/native/c/binding.dart index a2b62705ce..9b10e2ff76 100644 --- a/packages/flutter/lib/src/native/c/binding.dart +++ b/packages/flutter/lib/src/native/c/binding.dart @@ -640,6 +640,52 @@ class SentryNative { void Function( ffi.Pointer, ffi.Pointer)>(); + /// Sets the path to the Sentry Database Directory. + /// + /// Sentry will use this path to persist user consent, sessions, and other + /// artifacts in case of a crash. This will also be used by the crashpad backend + /// if it is configured. + /// + /// The directory is used for "cached" data, which needs to persist across + /// application restarts to ensure proper flagging of release-health sessions, + /// but might otherwise be safely purged regularly. + /// + /// It is roughly equivalent to the type of `AppData/Local` on Windows and + /// `XDG_CACHE_HOME` on Linux, and equivalent runtime directories on other + /// platforms. + /// + /// It is recommended that users set an explicit absolute path, depending + /// on their apps runtime directory. The path will be created if it does not + /// exist, and will be resolved to an absolute path inside of `sentry_init`. The + /// directory should not be shared with other application data/configuration, as + /// sentry-native will enumerate and possibly delete files in that directory. An + /// example might be `$XDG_CACHE_HOME/your-app/sentry` + /// + /// If no explicit path it set, sentry-native will default to `.sentry-native` in + /// the current working directory, with no specific platform-specific handling. + /// + /// `path` is assumed to be in platform-specific filesystem path encoding. + /// API Users on windows are encouraged to use + /// `sentry_options_set_database_pathw` instead. + void options_set_database_path( + ffi.Pointer opts, + ffi.Pointer path, + ) { + return _options_set_database_path( + opts, + path, + ); + } + + late final _options_set_database_pathPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, + ffi.Pointer)>>('sentry_options_set_database_path'); + late final _options_set_database_path = + _options_set_database_pathPtr.asFunction< + void Function( + ffi.Pointer, ffi.Pointer)>(); + /// Initializes the Sentry SDK with the specified options. /// /// This takes ownership of the options. After the options have been set diff --git a/packages/flutter/lib/src/native/c/sentry_native.dart b/packages/flutter/lib/src/native/c/sentry_native.dart index d1f99129bc..793d103a23 100644 --- a/packages/flutter/lib/src/native/c/sentry_native.dart +++ b/packages/flutter/lib/src/native/c/sentry_native.dart @@ -69,6 +69,10 @@ class SentryNative with SentryNativeSafeInvoker implements SentryNativeBinding { cOptions, options.enableAutoSessionTracking ? 1 : 0); native.options_set_dist(cOptions, c.str(options.dist)); native.options_set_max_breadcrumbs(cOptions, options.maxBreadcrumbs); + if (options.nativeDatabasePath != null) { + native.options_set_database_path( + cOptions, c.str(options.nativeDatabasePath)); + } if (options.proxy != null) { // sentry-native expects a single string and it doesn't support different types or authentication options.log(SentryLevel.warning, diff --git a/packages/flutter/lib/src/sentry_flutter_options.dart b/packages/flutter/lib/src/sentry_flutter_options.dart index b25ecdfd56..0de7aebfe6 100644 --- a/packages/flutter/lib/src/sentry_flutter_options.dart +++ b/packages/flutter/lib/src/sentry_flutter_options.dart @@ -291,6 +291,30 @@ class SentryFlutterOptions extends SentryOptions { /// Screen content masking is enabled by default. final privacy = SentryPrivacyOptions(); + /// Specifies the file system path to the Sentry database directory + /// used by the Sentry Native SDK. + /// + /// ### Default + /// If `null` (the default), the database directory is created at + /// `.sentry-native` in the current working directory (CWD). + /// + /// ### Recommendation + /// While relying on the default path may be sufficient during development, + /// **it is strongly recommended** to provide an explicit path in production + /// environments. Doing so ensures consistent and predictable behavior across + /// deployments. + /// + /// ### Platform Support + /// This option only applies to platforms that integrate the Sentry Native SDK + /// directly: + /// - **Linux (Desktop)** + /// - **Windows (Desktop)** + /// + /// ### References + /// For additional details, see: + /// https://docs.sentry.io/platforms/native/configuration/options/#database-path + String? nativeDatabasePath; + /// By using this, you are disabling native [Breadcrumb] tracking and instead /// you are just tracking [Breadcrumb]s which result from events available /// in the current Flutter environment. diff --git a/packages/flutter/test/sentry_native/sentry_native_test_ffi.dart b/packages/flutter/test/sentry_native/sentry_native_test_ffi.dart index c5d803c928..1954e7db13 100644 --- a/packages/flutter/test/sentry_native/sentry_native_test_ffi.dart +++ b/packages/flutter/test/sentry_native/sentry_native_test_ffi.dart @@ -139,6 +139,28 @@ void main() { await sut.init(MockHub()); }); + test('init creates native database path directory when configured', + () async { + final dbDir = Directory( + '${helper.nativeTestRoot}/db-${backend.actualValue.name}'); + if (dbDir.existsSync()) { + dbDir.deleteSync(recursive: true); + } + + options.nativeDatabasePath = dbDir.path; + + addTearDown(() { + if (dbDir.existsSync()) { + dbDir.deleteSync(recursive: true); + } + }); + addTearDown(sut.close); + + await sut.init(MockHub()); + + expect(dbDir.existsSync(), isTrue); + }); + test('app start', () { expect(sut.fetchNativeAppStart(), null); });