-
-
Notifications
You must be signed in to change notification settings - Fork 467
Expand file tree
/
Copy pathSentrySQLiteDriver.kt
More file actions
90 lines (82 loc) · 2.7 KB
/
SentrySQLiteDriver.kt
File metadata and controls
90 lines (82 loc) · 2.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package io.sentry.android.sqlite
import androidx.sqlite.SQLiteConnection
import androidx.sqlite.SQLiteDriver
import androidx.sqlite.SQLiteStatement
import io.sentry.android.sqlite.SQLiteSpanManager
import io.sentry.IScopes
import io.sentry.ScopesAdapter
/**
* Automatically adds a Sentry span to the current scope for each database query executed.
*
* Usage - wrap this around your current [SQLiteDriver]:
* ```
* val driver = SentrySQLiteDriver.create(AndroidSQLiteDriver())
* ```
*
* If you use Room you can wrap the default [AndroidSQLiteDriver]:
* ```
* val database = Room.databaseBuilder(context, MyDatabase::class.java, "dbName")
* .setDriver(SentrySQLiteDriver.create(AndroidSQLiteDriver()))
* ...
* .build()
* ```
*/
public class SentrySQLiteDriver internal constructor(
private val delegate: SQLiteDriver,
private val scopes: IScopes = ScopesAdapter.getInstance(),
) : SQLiteDriver {
override fun open(fileName: String): SQLiteConnection {
val sqliteSpanManager = SQLiteSpanManager(
scopes,
// SQLiteDriver.open docs say:
// >> To open an in-memory database use the special name :memory: as the fileName.
// SQLiteSpanManager expects null for an in-memory databaseName, so replace ":memory:" with null.
databaseName = fileName.takeIf { it != ":memory:" }
)
val connection = delegate.open(fileName)
return SentrySQLiteConnection(connection, sqliteSpanManager)
}
public companion object {
/**
* @param delegate The [SQLiteDriver] instance to delegate calls to.
*/
@JvmStatic
public fun create(delegate: SQLiteDriver): SQLiteDriver {
if (delegate is SentrySQLiteDriver) {
return delegate
} else {
return SentrySQLiteDriver(delegate)
}
}
}
}
internal class SentrySQLiteConnection(
private val delegate: SQLiteConnection,
private val sqliteSpanManager: SQLiteSpanManager,
) : SQLiteConnection by delegate {
override fun prepare(sql: String): SQLiteStatement {
val statement = delegate.prepare(sql)
return SentrySQLiteStatement(statement, sqliteSpanManager, sql)
}
}
internal class SentrySQLiteStatement(
private val delegate: SQLiteStatement,
private val sqliteSpanManager: SQLiteSpanManager,
private val sql: String,
) : SQLiteStatement by delegate {
// We have to start the span only the first time, regardless of how many times its methods get
// called.
private var isSpanStarted = false
override fun step(): Boolean {
if (isSpanStarted) {
return delegate.step()
} else {
isSpanStarted = true
return sqliteSpanManager.performSql(sql) { delegate.step() }
}
}
override fun reset() {
isSpanStarted = false
delegate.reset()
}
}