diff --git a/docs/platforms/android/features/index.mdx b/docs/platforms/android/features/index.mdx
index 0b05761c55247..252de23cbd1aa 100644
--- a/docs/platforms/android/features/index.mdx
+++ b/docs/platforms/android/features/index.mdx
@@ -43,7 +43,7 @@ Let us know if you have feedback by filing a Cold and warm app starts.
- Slow and frozen frames.
- OkHttp request spans.
- - SQLite and Room query spans.
+ - SQLite query spans.
- File I/O spans.
- Apollo request spans.
- Distributed tracing through OkHttp and Apollo integrations.
diff --git a/docs/platforms/android/integrations/room-and-sqlite/img/room-sqlite-instrumentation.png b/docs/platforms/android/integrations/room-and-sqlite/img/room-sqlite-instrumentation.png
deleted file mode 100644
index 71061c02732cf..0000000000000
Binary files a/docs/platforms/android/integrations/room-and-sqlite/img/room-sqlite-instrumentation.png and /dev/null differ
diff --git a/docs/platforms/android/integrations/room-and-sqlite/img/sqlite-instrumentation.png b/docs/platforms/android/integrations/room-and-sqlite/img/sqlite-instrumentation.png
new file mode 100644
index 0000000000000..6751fc14e4465
Binary files /dev/null and b/docs/platforms/android/integrations/room-and-sqlite/img/sqlite-instrumentation.png differ
diff --git a/docs/platforms/android/integrations/room-and-sqlite/index.mdx b/docs/platforms/android/integrations/room-and-sqlite/index.mdx
index e4f52e00c1be9..501ee0b26c2a9 100644
--- a/docs/platforms/android/integrations/room-and-sqlite/index.mdx
+++ b/docs/platforms/android/integrations/room-and-sqlite/index.mdx
@@ -1,67 +1,56 @@
---
-title: Room and SQLite
+title: SQLite
caseStyle: camelCase
supportLevel: production
sdk: sentry.java.android.sqlite
description: >-
- Learn more about the Sentry Room and AndroidX SQLite integrations for the
- Android SDK.
+ Instrument SQLite databases – including Room and SQLDelight – via SentrySQLiteDriver and SentrySupportSQLiteOpenHelper.
categories:
- mobile
og_image: /og-images/platforms-android-integrations-room-and-sqlite.png
---
-
+The `sentry-android-sqlite` library generates spans for your SQLite queries, whether you use [Room](https://developer.android.com/training/data-storage/room/), [SQLDelight](https://sqldelight.github.io/sqldelight/), or another persistence library. It does so by wrapping your existing `SQLiteDriver` or `SupportSQLiteOpenHelper`.
-Supported in Sentry's Android SDK version `4.0.0` and above.
+If you're using the Sentry Android Gradle Plugin, wrapping is performed automatically. (See [Auto-Instrumentation](#auto-instrumentation) for more details.)
-Supported in Sentry Android Gradle Plugin version `3.0.0` and above.
+Room users can also take advantage of our [auto-instrumentation of DAO methods](#room-dao-methods).
-Custom instrumentation is supported in Sentry's Android SDK, version `6.21.0` and above.
+
-
+Check out our [migration advice](#migrating-from-supportsqliteopenhelper-to-sqlitedriver) if you're migrating from `SupportSQLiteOpenHelper` to `SQLiteDriver`.
-## Auto-Installation With the Sentry Android Gradle Plugin
+Spans require [tracing to be enabled](/platforms/android/tracing/#configure-the-sample-rate).
-The [Sentry Android Gradle Plugin](/platforms/android/configuration/gradle/) provides Room and AndroidX SQLite support through bytecode manipulation. The source can be found [on GitHub](https://github.com/getsentry/sentry-android-gradle-plugin/tree/main/plugin-build/src/main/kotlin/io/sentry/android/gradle/instrumentation).
+
-On this page, we get you up and running with Sentry's Room and SQLite Integration, so that it will automatically start a span from an active transaction that's bound to the scope of each sqlite/dao query.
+## Auto-Instrumentation
### Install
-To use the Room and AndroidX SQLite integration, add the Sentry Android Gradle plugin and the Sentry Android SDK (version `4.0.0` or above) in `build.gradle`:
-
-```groovy
-plugins {
- id "io.sentry.android.gradle" version "{{@inject packages.version('sentry.java.android.gradle-plugin', '3.0.0') }}"
-}
-
-dependencies {
- implementation 'io.sentry:sentry-android:{{@inject packages.version('sentry.java.android', '5.0.0') }}'
-}
-```
-
-```kotlin
-plugins {
- id("io.sentry.android.gradle") version "{{@inject packages.version('sentry.java.android.gradle-plugin', '3.0.0') }}"
-}
+The [Sentry Android Gradle Plugin](/platforms/android/configuration/gradle/) (SAGP) uses bytecode manipulation to automatically wrap your driver and/or open helper.†
-dependencies {
- implementation("io.sentry:sentry-android:{{@inject packages.version('sentry.java.android', '5.0.0') }}")
-}
-```
+To use the SAGP, follow the [plugin installation instructions](/platforms/android/configuration/gradle/). The SAGP [auto-installs](/platforms/android/configuration/gradle/#auto-installation) the Sentry Android SDK by default.
-
+
+ † For now, the SAGP only auto-wraps uses of `SQLiteDriver` with Room. Any
+ non-Room uses of the driver must be wrapped manually. SAGP auto-wraps open
+ helpers in all contexts.
+
-Make sure, that [tracing](/platforms/android/tracing/#configure-the-sample-rate) is enabled.
+The type or call site wrapped depends on the SAGP version:
-
+| API | Minimum SAGP version | Coverage |
+| ------------------------- | -------------------- | -------------------------------------------------------------------------- |
+| `SQLiteDriver` | `≥6.13.0` | `Room.databaseBuilder().setDriver(...)` call sites |
+| `SupportSQLiteOpenHelper` | `≥3.0.0` | `FrameworkSQLiteOpenHelperFactory` |
+| `SupportSQLiteOpenHelper` | `≥3.11.0` | Any `SupportSQLiteOpenHelper.Factory` (SQLDelight, custom factories, etc.) |
### Configure
-In general, no further configuration is required as the auto-instrumentation is enabled by default. If you would like to disable the database instrumentation feature, we expose a configuration option for that:
+No additional configuration is required, as database auto-instrumentation is enabled by default. To disable it, use the `DATABASE` instrumentation feature:
-```groovy
+```groovy {filename:build.gradle}
import io.sentry.android.gradle.extensions.InstrumentationFeature
sentry {
@@ -72,7 +61,7 @@ sentry {
}
```
-```kotlin
+```kotlin {filename:build.gradle.kts}
import java.util.EnumSet
import io.sentry.android.gradle.extensions.InstrumentationFeature
@@ -84,45 +73,56 @@ sentry {
}
```
-## Manual Installation
-
-
+Disabling `DATABASE` instrumentation disables `SQLiteDriver` wrapping, `SupportSQLiteOpenHelper` wrapping, and Room DAO spans.
-Supported in Sentry's Android SDK, version `6.21.0` and above.
+See our [Gradle](/platforms/android/configuration/gradle/) page for other SAGP configuration options.
-
+## Manual Instrumentation
### Install
-Sentry captures data by wrapping a `SupportSQLiteOpenHelper.Factory`. To add the SQLite integration, initialize the [Android SDK](/platforms/android/), then add the `sentry-android-sqlite` dependency using Gradle:
+If you don't use the SAGP, you can always wrap your driver or open helper explicitly. Add the Sentry Android SDK and the `sentry-android-sqlite` artifact:
-```groovy
-implementation 'io.sentry:sentry-android:{{@inject packages.version('sentry.java.android', '6.21.0') }}'
-implementation 'io.sentry:sentry-android-sqlite:{{@inject packages.version('sentry.java.android.sqlite', '6.21.0') }}'
+```groovy {filename:build.gradle}
+dependencies {
+ implementation 'io.sentry:sentry-android:{{@inject packages.version('sentry.java.android', '8.45.0') }}'
+ implementation 'io.sentry:sentry-android-sqlite:{{@inject packages.version('sentry.java.android.sqlite', '8.45.0') }}'
+}
```
-### Configure
+```kotlin {filename:build.gradle.kts}
+dependencies {
+ implementation("io.sentry:sentry-android:{{@inject packages.version('sentry.java.android', '8.45.0') }}")
+ implementation("io.sentry:sentry-android-sqlite:{{@inject packages.version('sentry.java.android.sqlite', '8.45.0') }}")
+}
+```
-No configuration is required. Just wrap your `SupportSQLiteOpenHelper` instance in `SentrySupportSQLiteOpenHelper`.
+The `sentry-android-sqlite` artifact ships both wrappers; the minimum version depends on which API you need to wrap:
-```kotlin
-import io.sentry.android.sqlite.SentrySupportSQLiteOpenHelper
+| API | Minimum `sentry-android-sqlite` version |
+| ------------------------- | --------------------------------------- |
+| `SQLiteDriver` | `≥8.45.0` |
+| `SupportSQLiteOpenHelper` | `≥6.21.0` |
-private val myOpenHelper = MyOpenHelper()
-private val instrumentedOpenHelper = SentrySupportSQLiteOpenHelper.create(myOpenHelper)
-```
+### Configure
-```java
-import io.sentry.android.sqlite.SentrySupportSQLiteOpenHelper;
+Wrap your driver or open helper directly with `SentrySQLiteDriver.create(...)` or `SentrySupportSQLiteOpenHelper.create(...)`. Use the wrapped instance wherever you would have used the unwrapped one. For most teams, that means wiring it into Room or SQLDelight:
-private final SupportSQLiteOpenHelper myOpenHelper = new MyOpenHelper();
-private final SupportSQLiteOpenHelper instrumentedOpenHelper = SentrySupportSQLiteOpenHelper.create(myOpenHelper);
-```
+#### Room
-Room is supported when using the default `FrameworkSQLiteOpenHelperFactory` provided by the `androidx.sqlite` package, but any custom `SupportSQLiteOpenHelper` can be used.
+```kotlin {tabTitle:SQLiteDriver} {mdExpandTabs}
+import androidx.room.Room
+import androidx.sqlite.driver.AndroidSQLiteDriver
+import io.sentry.sqlite.SentrySQLiteDriver
-```kotlin
+val database = Room.databaseBuilder(context, MyDatabase::class.java, "dbName")
+ .setDriver(SentrySQLiteDriver.create(AndroidSQLiteDriver()))
+ .build()
+```
+
+```kotlin {tabTitle:SupportSQLiteOpenHelper}
import androidx.room.Room
+import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory
import io.sentry.android.sqlite.SentrySupportSQLiteOpenHelper
val database = Room.databaseBuilder(context, MyDatabase::class.java, "dbName")
@@ -132,92 +132,132 @@ val database = Room.databaseBuilder(context, MyDatabase::class.java, "dbName")
.build()
```
+**Note**: If you're using the AndroidX [`SupportSQLiteDriver`](https://developer.android.com/reference/kotlin/androidx/sqlite/driver/SupportSQLiteDriver), you'll want to make sure you're wrapping the open helper but ***not*** the support driver itself. See the alert under the [migration section](#migrating-from-supportsqliteopenhelper-to-sqlitedriver) for more details.
+
+#### SQLDelight
+
+```kotlin
+import androidx.sqlite.db.SupportSQLiteOpenHelper
+import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory
+import app.cash.sqldelight.driver.android.AndroidSqliteDriver
+import io.sentry.android.sqlite.SentrySupportSQLiteOpenHelper
+
+val driver = AndroidSqliteDriver(
+ schema = MyDatabase.Schema,
+ context = context,
+ name = "myapp.db",
+ factory = SupportSQLiteOpenHelper.Factory { configuration ->
+ SentrySupportSQLiteOpenHelper.create(FrameworkSQLiteOpenHelperFactory().create(configuration))
+ },
+)
+```
+
```java
-import androidx.room.Room;
+import androidx.sqlite.db.SupportSQLiteOpenHelper;
+import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory;
+import app.cash.sqldelight.driver.android.AndroidSqliteDriver;
import io.sentry.android.sqlite.SentrySupportSQLiteOpenHelper;
-final MyDatabase database = Room.databaseBuilder(context, MyDatabase.class, "dbName")
- .openHelperFactory (configuration ->
- SentrySupportSQLiteOpenHelper.create(new FrameworkSQLiteOpenHelperFactory().create(configuration))
- )
- .build();
+SupportSQLiteOpenHelper.Factory factory = configuration ->
+ SentrySupportSQLiteOpenHelper.create(new FrameworkSQLiteOpenHelperFactory().create(configuration));
+
+AndroidSqliteDriver driver = new AndroidSqliteDriver(
+ MyDatabase.Companion.getSchema(),
+ context,
+ "myapp.db",
+ factory
+);
```
+**Note**: SQLDelight doesn't currently support `SQLiteDriver`.
+
+## Migrating from SupportSQLiteOpenHelper to SQLiteDriver
+
+
+
+This section doesn't apply to migrations to AndroidX's [`SupportSQLiteDriver`](https://developer.android.com/reference/kotlin/androidx/sqlite/driver/SupportSQLiteDriver) (the bridge adapter for Room `[2.7, 3.0)`).
+
+The support driver consumes your existing `SupportSQLiteOpenHelper`, so continue to use `SentrySupportSQLiteOpenHelper` to wrap your helper as before.
+
+
+
+If you're switching your app's SQLite API from `SupportSQLiteOpenHelper` to `SQLiteDriver`, you may need to update your Sentry dependencies:
+
+| Path | Previous minimum | New minimum |
+| -------------------------------- | ------------------------------------ | ------------------------------------- |
+| Manual instrumentation | `sentry-android-sqlite` `6.21.0` | `sentry-android-sqlite` `8.45.0` |
+| Auto-instrumentation† | Sentry Android Gradle Plugin `3.11.0` | Sentry Android Gradle Plugin `6.13.0` |
+
+
+ † SAGP installs `sentry-android-sqlite` transitively when your project depends
+ on `androidx.sqlite:sqlite`, so you typically don't need to add it. But if your
+ project explicitly pins `sentry-android-sqlite`, bump it to `≥8.45.0`.
+
+
+Replace `SentrySupportSQLiteOpenHelper.create(openHelper)` with `SentrySQLiteDriver.create(driver)`, and you're all set! (See [Manual Instrumentation → Room](#room) for the full call-site context.)
+
+**Note on span attributes**: `SentrySQLiteDriver` derives the `db.name` span attribute from the base name of the file path passed to `open()` (for example, `/data/.../my.db` → `my.db`), while `SentrySupportSQLiteOpenHelper` uses AndroidX's `databaseName` verbatim.
+
+**Note on span durations**: Due to underlying API differences, `SQLiteDriver` and `SupportSQLiteOpenHelper` span durations may differ. Driver spans are limited to work performed by the database during statement execution, while open helpers may also track time spent on statement preparation or work the owning app performs consuming native SQLite output.
+
## Verify
-Assuming you have the following (reduced) code snippet performing a database query on a Room Dao:
+To confirm that your wrapped driver or open helper is producing spans, execute a query inside a Sentry transaction and check for the SQL span in [sentry.io](https://sentry.io).
-```kotlin
-import android.os.Bundle
-import android.widget.Button
-import androidx.activity.ComponentActivity
-import androidx.room.Database
-import androidx.room.Dao
-import androidx.room.Insert
-import androidx.room.OnConflictStrategy
-import androidx.room.RoomDatabase
+```kotlin {tabTitle:SQLiteDriver} {mdExpandTabs}
import io.sentry.Sentry
import io.sentry.SpanStatus
-import kotlinx.coroutines.withContext
-
-@Dao
-abstract class TracksDao {
- @Insert(onConflict = OnConflictStrategy.REPLACE)
- abstract suspend fun insert(track: Track): Long
-}
+import io.sentry.TransactionOptions
-@Database(
- entities = [Track::class],
- version = 1,
- exportSchema = false
+// `driver` is your SentrySQLiteDriver-wrapped instance (see Configure section above).
+val transaction = Sentry.startTransaction(
+ "DB Smoke Test",
+ "db.query",
+ TransactionOptions().apply { isBindToScope = true },
)
-abstract class TracksDatabase : RoomDatabase() {
- abstract fun tracksDao(): TracksDao
+
+driver.open(":memory:").use { connection ->
+ connection.prepare("SELECT 1").use { it.step() }
}
-class EditActivity : ComponentActivity() {
- private lateinit var database: TracksDatabase
+transaction.finish(SpanStatus.OK)
+```
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- database = TODO("initialize database...")
+```kotlin {tabTitle:SupportSQLiteOpenHelper}
+import io.sentry.Sentry
+import io.sentry.SpanStatus
+import io.sentry.TransactionOptions
- findViewById