Skip to content

feat(plugin): Auto-instrument SQLiteDriver for Room users (GRADLE-107)#1285

Merged
0xadam-brown merged 13 commits into
mainfrom
feat/wrap-sqlite-driver
Jun 25, 2026
Merged

feat(plugin): Auto-instrument SQLiteDriver for Room users (GRADLE-107)#1285
0xadam-brown merged 13 commits into
mainfrom
feat/wrap-sqlite-driver

Conversation

@0xadam-brown

@0xadam-brown 0xadam-brown commented Jun 9, 2026

Copy link
Copy Markdown
Member

📜 Description

Adds a new bytecode method visitor that lets us auto-wrap all occurrences of SQLiteDriver with SentrySQLiteDriver whenever the driver is passed to Room.DatabaseBuilder.setDriver(SQLiteDriver) (Room's sole driver access point – see the "Coverage" section from #1281 for why we don't need to worry about anything else).

In other words, this:

val database = Room.databaseBuilder(context, MyDatabase::class.java, "dbName")
     .setDriver(AndroidSQLiteDriver())
     .build()

becomes:

val database = Room.databaseBuilder(context, MyDatabase::class.java, "dbName")
     .setDriver(SentrySQLiteDriver.create(AndroidSQLiteDriver()))
     .build()

The wrapping policy is naive in that every SQLiteDriver passed to Room.DatabaseBuilder.setDriver() is wrapped. That's deliberate because SentrySQLiteDriver protects against double-wrapping internally, which lets us keep our visitor implementation simple.

💡 Motivation and Context

Room 2.7 introduced RoomDatabase.Builder.setDriver(SQLiteDriver) as the new way to configure an underlying SQLite implementation (link), with the intention of eventually replacing SupportSQLiteOpenHelper. (Room 3.0+ does just that.)

The Sentry Android Gradle Plugin currently auto-instruments only the open helper path. Apps that adopt the driver-based API will lose automatic SQL performance instrumentation unless they manually wrap their driver with SentrySQLiteDriver.create(...) at every setDriver(...) call site.

This PR provides auto-wrapping for the driver path too.

Addresses GRADLE-107 / #1281

Preconditions

  1. sentry-android-sqlite version in the SAGP build must include SentrySQLiteDriver
  2. InstrumentationFeature.DATABASE must be enabled (⚠️ in other words, we piggyback on the existing DATABASE toggle used to auto-instrument the SupportSQLiteOpenHelper + Room DAO spans)

Coverage

  • Auto-wraps SQLiteDriver for all Room users.
  • SQLDelight users don't need driver auto-wrapping (they still use SupportSQLiteOpenHelper, which we already auto-instrument).
  • The few developers who use SQLiteDriver directly will need to wrap it manually.

Impact on build times

Near zero. The new instrumentation gates on a two-entry allowlist (androidx.room.RoomDatabase$Builder / androidx.room3.RoomDatabase$Builder), which means 0-1 classes will be visited per build in virtually all scenarios. The rest of the per-class cost is a single Set.contains check.

Interactions with other db instrumentation

SupportSQLiteOpenHelper

Driver instrumentation operates alongside our existing instrumentation of SupportSQLiteOpenHelper. (It's fine to use both drivers and open helpers in the same project, so long as a given db file is associated with exactly one of them. Room's APIs help enforce that restriction.)

The Sentry Android SDK – and not the SAGP – is responsible for protecting against double-wrapping and duplicate spans. In general that's easy (just check the type being passed to the wrapper). In the case of the SupportSQLiteDriver used with Room [2.7, 3.0) things get a bit trickier, as it's both a driver and consumes an open helper. But the SDK has that covered as well (see #5514).

Room DAO methods

Driver instrumentation also operates in tandem with our existing Room DAO spans – in theory, at least. Unfortunately DAO instrumentation broke under API changes in Room 2.7, which is the same version that introduced SQLiteDriver. So for now the two are never active at the same time. Fixing that is a task for another day...

💚 How did you test it?

[1] Added unit tests + integration tests in this PR

[2] Verified that all the (for now) @Ignored integration tests pass against a local sentry-java SDK artifact containing SentrySQLiteDriver.

[3] Built out a local version of the Sentry Android sample app that let me manually test SAGP + sentry-java compatibility end-to-end. Verified that auto-instrumentation of SQLiteDriver works as expected.

📝 Checklist

  • I reviewed the submitted code
  • I added tests to verify the changes
  • I updated the docs if needed
  • No breaking changes

🔮 Next steps

  • Merge updates to sentry-docs (#18489)
  • Consider a CI cron job that checks Room's latest API for changes that would impact our implementation here and in the Sentry Android SDK.

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor
Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against 41fba8c

@0xadam-brown 0xadam-brown linked an issue Jun 9, 2026 that may be closed by this pull request
Comment thread CHANGELOG.md Outdated
Comment thread plugin-build/src/main/kotlin/io/sentry/android/gradle/util/Versions.kt Outdated
@0xadam-brown 0xadam-brown force-pushed the feat/wrap-sqlite-driver branch 2 times, most recently from f64ad3f to 1c821b7 Compare June 10, 2026 14:41
… users (GRADLE-107)

Adds a new ASM bytecode method visitor that lets us auto-wrap all occurrences of SQLiteDriver with SentrySQLiteDriver whenever the driver is passed to Room.DatabaseBuilder.setDriver(...).

For instance:

val database = Room.databaseBuilder(context, MyDatabase::class.java, "dbName")
     .setDriver(AndroidSQLiteDriver())
     .build()

becomes:

val database = Room.databaseBuilder(context, MyDatabase::class.java, "dbName")
     .setDriver(SentrySQLiteDriver.create(AndroidSQLiteDriver()))
     .build()

The wrapping policy is naive in that every SQLiteDriver passed to setDriver() is wrapped. That's deliberate because SentrySQLiteDriver protects against double-wrapping internally, which lets us keep our visitor implementation simple.

Preconditions:

1. InstrumentationFeature.DATABASE is enabled
2. The owning app is using a version of sentry-android-sqlite that includes SentrySQLiteDriver

Coverage:

- Auto-wraps SQLiteDriver for all Room users (sole Room access point is via its Room.DatabaseBuilder.setDriver() method).
- SQLDelight users don't need driver auto-wrapping (they still use SupportSQLiteOpenHelper, which we already auto-wrap).
- The few developers who use SQLiteDriver directly will need to wrap it manually.
@0xadam-brown 0xadam-brown force-pushed the feat/wrap-sqlite-driver branch from 1c821b7 to 1548c9c Compare June 10, 2026 15:27
@0xadam-brown 0xadam-brown marked this pull request as ready for review June 10, 2026 15:31
@0xadam-brown 0xadam-brown changed the title feat(plugin): Auto-wrap SQLiteDriver with SentrySQLiteDriver for Room users feat(plugin): Auto-instrument SQLiteDriver for Room users Jun 10, 2026
@0xadam-brown 0xadam-brown changed the title feat(plugin): Auto-instrument SQLiteDriver for Room users feat(plugin): Auto-instrument SQLiteDriver for Room users (GRADLE-107) Jun 10, 2026
@linear-code

linear-code Bot commented Jun 10, 2026

Copy link
Copy Markdown

GRADLE-107

@runningcode runningcode left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks this looks good! I just don't think I'm enough of an expert in how we instrument classes to approve this.
I left some questions for my better understanding of the patterns we are using.

Comment thread gradle/libs.versions.toml
Comment thread CHANGELOG.md Outdated
Comment thread plugin-build/build.gradle.kts Outdated
Comment thread plugin-build/src/test/kotlin/io/sentry/sqlite/SentrySQLiteDriver.kt Outdated
Comment thread CHANGELOG.md Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 2ee2ad8. Configure here.

Comment thread gradle/libs.versions.toml Outdated
Comment thread plugin-build/src/main/kotlin/io/sentry/android/gradle/util/Versions.kt Outdated
Comment thread CHANGELOG.md Outdated

@romtsn romtsn left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nicely done, hats off!

@0xadam-brown 0xadam-brown merged commit 1a4369e into main Jun 25, 2026
23 checks passed
@0xadam-brown 0xadam-brown deleted the feat/wrap-sqlite-driver branch June 25, 2026 05:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Auto-instrument SQLiteDriver for Room users

3 participants