Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 26 additions & 5 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,42 +5,49 @@ androidxNavigation = "2.4.2"
androidxTestCore = "1.7.0"
androidxCompose = "1.6.3"
asyncProfiler = "4.2"
camerax = "1.4.0"
composeCompiler = "1.5.14"
coroutines = "1.6.1"
espresso = "3.7.0"
feign = "11.6"
gummyBears = "0.12.0"
jacoco = "0.8.7"
jackson = "2.18.3"
jetbrainsCompose = "1.6.11"
kotlin = "2.2.0"
kotlinSpring7 = "2.2.0"
kotlin-compatible-version = "1.9"
ksp = "2.2.0-2.0.2"
ktorClient = "3.0.0"
logback = "1.2.9"
log4j2 = "2.20.0"
nopen = "1.0.1"
# see https://www.jetbrains.com/help/kotlin-multiplatform-dev/compose-compatibility-and-versioning.html#kotlin-compatibility
# see https://developer.android.com/jetpack/androidx/releases/compose-kotlin
okhttp = "4.9.2"
openfeature = "1.18.2"
otel = "1.60.1"
otelInstrumentation = "2.26.0"
otelInstrumentationAlpha = "2.26.0-alpha"
# check https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/dependencyManagement/build.gradle.kts#L49 for release version above to find a compatible version
otelSemanticConventions = "1.40.0"
otelSemanticConventionsAlpha = "1.40.0-alpha"
retrofit = "2.9.0"
room2 = "2.8.4"
room3 = "3.0.0-alpha06"
sqlite = "2.6.2"
sqliteAlpha = "2.7.0-alpha06" # Required by Room3 3.0.0-alpha*
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I've included deps that are only relevant to the sample app b/c that matched prior art. Chime in if you want me to break with that practice and move the new sample app deps to its build.gradle file.

slf4j = "1.7.30"
spotless = "8.4.0"
springboot2 = "2.7.18"
springboot3 = "3.5.0"
springboot4 = "4.0.0"
sqldelight = "2.3.2"

# Android
targetSdk = "36"
compileSdk = "36"
minSdk = "21"
spotless = "8.4.0"
gummyBears = "0.12.0"
camerax = "1.4.0"
openfeature = "1.18.2"

[plugins]
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
Expand All @@ -50,6 +57,7 @@ kotlin-jvm-spring7 = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlinSpr
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
buildconfig = { id = "com.github.gmazzo.buildconfig", version = "5.6.5" }
dokka = { id = "org.jetbrains.dokka", version = "2.0.0" }
dokka-javadoc = { id = "org.jetbrains.dokka-javadoc", version = "2.0.0" }
Expand All @@ -64,6 +72,7 @@ vanniktech-maven-publish = { id = "com.vanniktech.maven.publish", version = "0.3
springboot3 = { id = "org.springframework.boot", version.ref = "springboot3" }
springboot4 = { id = "org.springframework.boot", version.ref = "springboot4" }
spring-dependency-management = { id = "io.spring.dependency-management", version = "1.1.7" }
sqldelight = { id = "app.cash.sqldelight", version.ref = "sqldelight" }
gretty = { id = "org.gretty", version = "4.0.0" }
animalsniffer = { id = "ru.vyarus.animalsniffer", version = "2.0.1" }
sentry = { id = "io.sentry.android.gradle", version = "6.6.0"}
Expand Down Expand Up @@ -94,7 +103,14 @@ androidx-lifecycle-common-java8 = { module = "androidx.lifecycle:lifecycle-commo
androidx-lifecycle-process = { module = "androidx.lifecycle:lifecycle-process", version.ref = "androidxLifecycle" }
androidx-navigation-runtime = { module = "androidx.navigation:navigation-runtime", version.ref = "androidxNavigation" }
androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "androidxNavigation" }
androidx-sqlite = { module = "androidx.sqlite:sqlite", version = "2.6.2" }
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room2" }
androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "room2" }
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room2" }
androidx-room3-compiler = { module = "androidx.room3:room3-compiler", version.ref = "room3" }
androidx-room3-runtime = { module = "androidx.room3:room3-runtime", version.ref = "room3" }
androidx-sqlite = { module = "androidx.sqlite:sqlite", version.ref = "sqlite" }
androidx-sqlite-bundled = { module = "androidx.sqlite:sqlite-bundled", version.ref = "sqliteAlpha" }
androidx-sqlite-framework = { module = "androidx.sqlite:sqlite-framework", version.ref = "sqliteAlpha" }
androidx-recyclerview = { module = "androidx.recyclerview:recyclerview", version = "1.2.1" }
androidx-browser = { module = "androidx.browser:browser", version = "1.8.0" }
async-profiler = { module = "tools.profiler:async-profiler", version.ref = "asyncProfiler" }
Expand Down Expand Up @@ -207,6 +223,7 @@ springboot4-starter-jdbc = { module = "org.springframework.boot:spring-boot-star
springboot4-starter-actuator = { module = "org.springframework.boot:spring-boot-starter-actuator", version.ref = "springboot4" }
springboot4-starter-cache = { module = "org.springframework.boot:spring-boot-starter-cache", version.ref = "springboot4" }
springboot4-starter-kafka = { module = "org.springframework.boot:spring-boot-starter-kafka", version.ref = "springboot4" }
sqldelight-android-driver = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" }
timber = { module = "com.jakewharton.timber:timber", version = "4.7.1" }

# Animalsniffer signature
Expand Down Expand Up @@ -249,3 +266,7 @@ msgpack = { module = "org.msgpack:msgpack-core", version = "0.9.8" }
okhttp-mockwebserver = { module = "com.squareup.okhttp3:mockwebserver", version.ref = "okhttp" }
okio = { module = "com.squareup.okio:okio", version = "1.13.0" }
roboelectric = { module = "org.robolectric:robolectric", version = "4.15" }

[bundles]
androidx-room2 = ["androidx-room-runtime", "androidx-room-ktx"]
androidx-sqlite-drivers = ["androidx-sqlite-bundled", "androidx-sqlite-framework"]
27 changes: 27 additions & 0 deletions sentry-samples/sentry-samples-android/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Sentry Sample Android App

Sample application demonstrating how to use the Sentry Android SDK, including core functionality (error reporting, tracing, session replay, profiling) and integrations (Compose, OkHttp, SQLDelight, etc.).

## How to run it?

Install the app on your device or emulator:

```
./gradlew :sentry-samples:sentry-samples-android:installDebug
```

or simply open the project in Android Studio and run the `sentry-samples-android` configuration.

## Viewing events locally

Debug builds enable SDK debug logging, so captured envelopes are printed to logcat (tag `Sentry`):

```
adb logcat -s Sentry
```

## Viewing events on Sentry UI

By default, events appear under the [sentry-sdk test project](https://sentry-sdks.sentry.io/issues/?project=5428559).
To redirect them to your own project, replace the test DSN (i.e., the `io.sentry.dsn` `meta-data` value)
in `src/main/AndroidManifest.xml` with your own.
40 changes: 34 additions & 6 deletions sentry-samples/sentry-samples-android/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ plugins {
id("com.android.application")
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
alias(libs.plugins.ksp)
alias(libs.plugins.sqldelight)
}

android {
Expand All @@ -15,7 +17,8 @@ android {

defaultConfig {
applicationId = "io.sentry.samples.android"
minSdk = libs.versions.minSdk.get().toInt()
// androidx.sqlite 2.6+ require minSdk 23; the Sentry SDK still supports 21.
minSdk = 23
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Note that Room 3 requires us to bump the Android sample app minSDK to 23 and JVM target to 11.

targetSdk = libs.versions.targetSdk.get().toInt()
versionCode = 2
versionName = project.version.toString()
Expand Down Expand Up @@ -90,7 +93,13 @@ android {
}
}

kotlin { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 }
// Java 11 b/c androidx.room3 requires it.
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}

kotlin { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11 }

androidComponents.beforeVariants {
it.enable = !Config.Android.shouldSkipDebugVariant(it.buildType)
Expand All @@ -116,13 +125,25 @@ android {
@Suppress("UnstableApiUsage") packagingOptions { jniLibs { useLegacyPackaging = true } }
}

sqldelight {
databases {
create("SampleSQLDelightDatabase") {
packageName.set("io.sentry.samples.android.sqlite")
// Keep .sq files next to the hand-written Kotlin (src/main/java/.../sqlite) instead of the
// default src/main/sqldelight source root.
srcDirs("src/main/java")
}
}
}

dependencies {
implementation(
kotlin(Config.kotlinStdLib, org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION)
)

implementation(projects.sentryAndroid)
implementation(projects.sentryAndroidFragment)
implementation(projects.sentryAndroidSqlite)
implementation(projects.sentryAndroidTimber)
implementation(projects.sentryCompose)
implementation(projects.sentryKotlinExtensions)
Expand All @@ -148,17 +169,24 @@ dependencies {
implementation(libs.androidx.navigation.compose)
implementation(libs.androidx.recyclerview)
implementation(libs.androidx.browser)
implementation(libs.androidx.room3.runtime)
implementation(libs.bundles.androidx.room2)
implementation(libs.bundles.androidx.sqlite.drivers)
implementation(libs.camerax.camera2)
implementation(libs.camerax.core)
implementation(libs.camerax.lifecycle)
implementation(libs.camerax.view)
implementation(libs.coil.compose)
implementation(libs.kotlinx.coroutines.android)
implementation(libs.lottie.compose)
implementation(libs.retrofit)
implementation(libs.retrofit.gson)
implementation(libs.sentry.native.ndk)
implementation(libs.sqldelight.android.driver)
implementation(libs.timber)
implementation(libs.camerax.core)
implementation(libs.camerax.camera2)
implementation(libs.camerax.lifecycle)
implementation(libs.camerax.view)

ksp(libs.androidx.room.compiler)
ksp(libs.androidx.room3.compiler)

debugImplementation(projects.sentryAndroidDistribution)
debugImplementation(libs.leakcanary)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,14 @@
android:name=".TriggerHttpRequestActivity"
android:exported="false" />

<activity
android:name=".sqlite.SQLiteActivity"
android:exported="false" />

<activity
android:name=".sqlite.UiLoadActivity"
android:exported="false" />

<!-- NOTE: Replace the test DSN below with YOUR OWN DSN to see the events from this app in your Sentry project/dashboard-->
<meta-data
android:name="io.sentry.dsn"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,20 @@ fun TracingScreen() {
}
}
}
item {
SentryTraced("open_sqlite") {
OutlinedButton(
onClick = {
activity.startActivity(
Intent(activity, io.sentry.samples.android.sqlite.SQLiteActivity::class.java)
)
},
modifier = Modifier,
) {
Text("Open SQLite Activity", maxLines = 2, overflow = TextOverflow.Ellipsis)
}
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import android.app.Application;
import android.os.StrictMode;
import io.sentry.Sentry;
import io.sentry.samples.android.sqlite.SampleDatabases;

/** Apps. main Application. */
public class MyApplication extends Application {
Expand All @@ -13,6 +14,8 @@ public void onCreate() {
strictMode();
super.onCreate();

SampleDatabases.INSTANCE.warmUp(this);

// Example how to initialize the SDK manually which allows access to SentryOptions callbacks.
// Make sure you disable the auto init via manifest meta-data: io.sentry.auto-init=false
// SentryAndroid.init(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package io.sentry.samples.android.sqlite
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

From here on I've flagged what few items I think are of interest. Your time is probably better spent spinning up the sample app from a local branch and seeing whether you have any feedback.


/**
* Display text for each "SQL run" summary shown in the [SQLiteActivity] screen UI. Documentation
* only / never executed. The real statements live in [SqlStatements].
*/
internal data class DisplayInfo(val sql: String, val sqlHeavy: String = sql)

internal val DRIVER_DIRECT =
DisplayInfo(
sql =
"""
CREATE TABLE IF NOT EXISTS song(…)
INSERT INTO song(title, artist) VALUES (?, ?)
SELECT count(*) FROM song
"""
.trimIndent(),
sqlHeavy =
"""
CREATE TABLE IF NOT EXISTS song(…)
INSERT INTO song(title, artist) VALUES (?, ?)
INSERT INTO song(title, artist) VALUES (?, ?), (?, ?), … (?, ?)
SELECT id, title, artist FROM song
SELECT count(*) FROM song
-- then, per row: appWork() = 500x SHA-256, in the app (not in any span)
"""
.trimIndent(),
)

internal val DRIVER_ROOM2 =
DisplayInfo(
sql =
"""
INSERT OR ABORT INTO `song` (…) VALUES (nullif(?, 0), ?, ?)
SELECT count(*) FROM song
"""
.trimIndent(),
sqlHeavy =
"""
INSERT OR ABORT INTO `song` (…) VALUES (nullif(?, 0), ?, ?)
SELECT * FROM song
SELECT count(*) FROM song
-- then, per row: appWork() = 500x SHA-256, outside the step()-timed spans
"""
.trimIndent(),
)

// Room 3 issues the same statements as Room 2 (see SqlStatements.driverWithRoom3).
internal val DRIVER_ROOM3 = DRIVER_ROOM2

internal val OPENHELPER_DIRECT =
DisplayInfo(
sql =
"""
CREATE TABLE IF NOT EXISTS song(…)
INSERT INTO song(title, artist) VALUES (?, ?)
SELECT count(*) FROM song
"""
.trimIndent(),
sqlHeavy =
"""
CREATE TABLE IF NOT EXISTS song(…)
INSERT INTO song(title, artist) VALUES (?, ?)
INSERT INTO song(title, artist) VALUES (?, ?), (?, ?), … (?, ?)
SELECT id, title, artist FROM song
SELECT count(*) FROM song
-- then, per row: appWork() = 500x SHA-256, in the app
"""
.trimIndent(),
)

internal val OPENHELPER_ROOM =
DisplayInfo(
sql =
"""
INSERT OR ABORT INTO `song` (…) VALUES (nullif(?, 0), ?, ?)
SELECT count(*) FROM song
"""
.trimIndent(),
sqlHeavy =
"""
INSERT OR ABORT INTO `song` (…) VALUES (nullif(?, 0), ?, ?)
SELECT * FROM song
SELECT count(*) FROM song
-- then, per row: appWork() = 500x SHA-256, in the app
"""
.trimIndent(),
)

internal val OPENHELPER_SQLDELIGHT =
DisplayInfo(
sql =
"""
INSERT INTO song(title, artist) VALUES (?, ?)
SELECT count(*) FROM song
"""
.trimIndent(),
sqlHeavy =
"""
INSERT INTO song(title, artist) VALUES (?, ?)
SELECT * FROM song
SELECT count(*) FROM song
-- then, per row: appWork() = 500x SHA-256, in the app
"""
.trimIndent(),
)
Loading
Loading