Skip to content

Fix DAO auto-instrumentation for Room 2.7+ and 3.0+ #1304

Description

@0xadam-brown

Background

The Sentry Android Gradle Plugin auto-instruments Room DAO methods starting from Room 1.0. That auto-instrumentation silently stopped working on Room 2.7+ and Room 3.0+ due to Room API changes.

Cause

AndroidXRoomDao (plugin-build/.../instrumentation/androidx/room/) detects DAO _Impl classes and rewrites their public methods to emit a span around the body:

  1. Match classes by _Impl suffix (AndroidXRoomDao.kt:67)
  2. Confirm the non-_Impl parent has the @androidx.room.Dao annotation (AndroidXRoomDao.kt:34)
  3. Scan method bytecode (InstrumentableMethodsCollectingVisitor.kt:90-94) for direct calls to:
    • androidx/room/RoomDatabase.beginTransaction
    • androidx/room/util/DBUtil.query
  4. Classify the method (TRANSACTION, QUERY, or QUERY_WITH_TRANSACTION) and wrap it accordingly

Two independent things break on recent Room versions:

  • Room 3.0+ package rename. The runtime moved to androidx.room3 (cf. AndroidXSQLiteDriver.kt:70, which already handles both androidx.room.RoomDatabase$Builder and androidx.room3.RoomDatabase$Builder). The hard-coded androidx/room/... owner strings in InstrumentableMethodsCollectingVisitor simply can't match Room 3 bytecode.
  • Room 2.7+ driver-based execution path. Room 2.7 introduced RoomDatabase.Builder.setDriver(SQLiteDriver). Our current hypothesis is that generated _Impl methods now route through the driver instead of calling RoomDatabase.beginTransaction() / DBUtil.query() directly, so the bytecode scan finds nothing to wrap. But we've yet to inspect what Room 2.7's _Impl codegen actually emits to confirm the precise shape. That confirmation is part of the work.

Acceptance criteria

  • DAO-method db.sql.room spans are produced for @Dao-annotated methods on Room 2.7.x and Room 3.0.x (kotlin and java sources; suspend and blocking DAOs).
  • The // no longer work on Room 2.7+ or Room 3.0+ comment in SpanAddingClassVisitorFactory.kt and the version disclaimer in InstrumentationFeature.DATABASE Kdoc are removed.
  • Existing instrumentation for Room < 2.7 keeps working (or is replaced by a unified approach that covers all supported versions).
  • Coexists cleanly with the driver-level wrap from feat(plugin): Auto-instrument SQLiteDriver for Room users (GRADLE-107) #1285 (no duplicate spans, no double-counting).

Possible approaches (to be evaluated, not committed to)

  1. Update the bytecode scan to match the new generated shape. Inspect what Room 2.7+ _Impl classes emit (likely calls into RoomDatabase.useConnection / performBlocking / performSuspending or similar driver-mediated entrypoints) and add those (owner, name) pairs to the lookup. Add androidx.room3 package variants alongside androidx.room.
  2. Move DAO-method tracing out of bytecode entirely. The SentrySQLiteDriver wrapper in sentry-android-sqlite has visibility into the connection/statement layer; consider whether a span representing "the work done under one DAO call" can be reconstructed from driver-level events plus a thread-local stack pushed/popped by a thinner DAO visitor (only entry/exit, no internal scanning).
  3. Hybrid: keep a minimal DAO _Impl visitor that only wraps method entry/exit (no internal pattern matching), so the span exists regardless of what Room's codegen does internally. Loses the TRANSACTION / QUERY / QUERY_WITH_TRANSACTION classification unless we recover it from the driver layer.
  4. Something else entirely.

Investigation notes

  • The driver-wrap workaround lives at plugin-build/src/main/kotlin/io/sentry/android/gradle/instrumentation/androidx/sqlite/driver/AndroidXSQLiteDriver.kt and targets both Room 2 and Room 3 builder classes.
  • Generated _Impl bytecode for a Room 2.7.x project should be inspected as the first concrete step, as it determines whether option 1 is viable and what owner/name pairs to look for.

Metadata

Metadata

Assignees

No one assigned

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions