Skip to content

Commit

Permalink
feat(Android): sentry integration (#569)
Browse files Browse the repository at this point in the history
* feat(Android): sentry integration

* fix: cleanup logs

* fix: account for no .envrc file in CI

* fix: restore the missing defaultConfig closing paren

* fix: restore mapbox logging warn msg

* Update README.md

Co-authored-by: Melody Horn <mhorn@mbta.com>

* wip: try native symbols only

* fix: actually pass through SENTRY_AUTH_TOKEN

* cleanup: remove test log

---------

Co-authored-by: Melody Horn <mhorn@mbta.com>
  • Loading branch information
KaylaBrady and boringcactus authored Dec 9, 2024
1 parent 387e5dc commit 4f46c4a
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 4 deletions.
3 changes: 2 additions & 1 deletion .envrc.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ export GOOGLE_APP_ID=

# Sentry - needed only to record sentry events from local development
# Find DSN under the Client Keys settings of the mobile_app_ios project in Sentry
export SENTRY_DSN=
export SENTRY_DSN_IOS=
export SENTRY_DSN_ANDROID=
export SENTRY_ENVIRONMENT=debug
1 change: 1 addition & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ jobs:
KEY_PASSWORD: ${{ env.MOBILE_APP_ANDROID_UPLOAD_KEY_PASSPHRASE }}
MAPBOX_SECRET_TOKEN: ${{ secrets.MAPBOX_SECRET_TOKEN }}
MAPBOX_PUBLIC_TOKEN: ${{ secrets.MAPBOX_PUBLIC_TOKEN }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
run: |
bundle exec fastlane android build flavor:Staging
- uses: actions/upload-artifact@v4
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ ios app:

To switch between the staging and prod app flavors, go to Build > Select Build Variant and then set the `:androidApp` Active Build Variant.

Populate any configuration needed in your the .envrc file. These will be read by a gradle build task
set as BuildConfig values so that they can be read by the application.


## Running Tests

### Unit Tests
Expand Down
48 changes: 48 additions & 0 deletions androidApp/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
import com.mbta.tid.mbta_app.gradle.ConvertIosMapIconsTask
import java.io.BufferedReader
import java.io.StringReader
import java.util.Properties

plugins {
alias(libs.plugins.androidApplication)
alias(libs.plugins.compose)
alias(libs.plugins.cycloneDx)
alias(libs.plugins.kotlinAndroid)
alias(libs.plugins.sentryGradle)
alias(libs.plugins.serialization)
id("check-mapbox-bridge")
}

sentry {
// Generates a JVM (Java, Kotlin, etc.) source bundle and uploads your source code to Sentry.
// This enables source context, allowing you to see your source
// code as part of your stack traces in Sentry.
includeSourceContext = true

org = "mbtace"
projectName = "mobile_app_android"
authToken = System.getenv("SENTRY_AUTH_TOKEN")
}

android {
namespace = "com.mbta.tid.mbta_app.android"
compileSdk = 34
Expand Down Expand Up @@ -104,6 +119,39 @@ task("accessToken") {
}
}

task("envVars") {
val envFile = File(".envrc")
val props = Properties()

if (envFile.exists()) {
val bufferedReader: BufferedReader = envFile.bufferedReader()
bufferedReader.use {
it.readLines()
.filter { line -> line.contains("export") }
.map { line ->
val cleanLine = line.replace("export", "")
props.load(StringReader(cleanLine))
}
}
} else {
println(".envrc file not configured, reading from system env instead")
}

android.defaultConfig.buildConfigField(
"String",
"SENTRY_DSN",
"\"${props.getProperty("SENTRY_DSN_ANDROID")
?: System.getenv("SENTRY_DSN_ANDROID") ?: ""}\""
)

android.defaultConfig.buildConfigField(
"String",
"SENTRY_ENVIRONMENT",
"\"${props.getProperty("SENTRY_ENVIRONMENT")
?: System.getenv("SENTRY_ENVIRONMENT") ?: ""}\""
)
}

gradle.projectsEvaluated {
tasks.getByPath("preBuild").dependsOn("accessToken", "convertIosIconsToAssets")
tasks.getByPath("check").dependsOn("checkMapboxBridge")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.mbta.tid.mbta_app.android

import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
Expand All @@ -12,12 +13,14 @@ import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationServices
import com.mbta.tid.mbta_app.android.util.LocalActivity
import com.mbta.tid.mbta_app.android.util.LocalLocationClient
import com.mbta.tid.mbta_app.initializeSentry

class MainActivity : ComponentActivity() {
private lateinit var fusedLocationClient: FusedLocationProviderClient

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
initSentry()
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
setContent {
MyApplicationTheme {
Expand All @@ -35,4 +38,16 @@ class MainActivity : ComponentActivity() {
}
}
}

private fun initSentry() {
val dsn = BuildConfig.SENTRY_DSN
val env = BuildConfig.SENTRY_ENVIRONMENT

if (dsn != null && env != null && !BuildConfig.DEBUG) {
initializeSentry(dsn, env)
Log.i("MainActivity", "Sentry initialized")
} else {
Log.w("MainActivity", "skipping sentry initialization")
}
}
}
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ okhttp = "4.12.0"
okio = "3.9.1"
playServicesLocation = "21.3.0"
sentry = "0.9.0"
sentryGradle = "4.14.1"
skie = "0.9.3"
spatialk = "0.3.0"
turbine = "1.2.0"
Expand Down Expand Up @@ -84,5 +85,6 @@ kotlinCocoapods = { id = "org.jetbrains.kotlin.native.cocoapods", version.ref =
kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
mokkery = { id = "dev.mokkery", version.ref = "mokkery" }
sentry = { id = "io.sentry.kotlin.multiplatform.gradle", version.ref = "sentry" }
sentryGradle = {id = "io.sentry.android.gradle", version.ref = "sentryGradle"}
serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
skie = { id = "co.touchlab.skie", version.ref = "skie" }
2 changes: 1 addition & 1 deletion iosApp/ci_scripts/ci_post_clone.sh
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ fi
echo "Adding build environment variables"
cd ${CI_PRIMARY_REPOSITORY_PATH}
touch .envrc
echo "export SENTRY_DSN=${SENTRY_DSN}" >> .envrc
echo "export SENTRY_DSN_IOS=${SENTRY_DSN}" >> .envrc
echo "export SENTRY_ENVIRONMENT=${SENTRY_ENVIRONMENT}" >> .envrc
echo "export FIREBASE_KEY=${FIREBASE_KEY}" >> .envrc
echo "export GOOGLE_APP_ID=${GOOGLE_APP_ID}" >> .envrc
4 changes: 2 additions & 2 deletions iosApp/iosApp/ProductionAppView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,11 @@ struct ProductionAppView: View {
}

private static func initSentry() {
if let sentryDsn = Bundle.main.object(forInfoDictionaryKey: "SENTRY_DSN") as? String {
if let sentryDsn = Bundle.main.object(forInfoDictionaryKey: "SENTRY_DSN_IOS") as? String {
let sentryEnv = Bundle.main.object(forInfoDictionaryKey: "SENTRY_ENVIRONMENT") as? String ?? "debug"
AppSetupKt.initializeSentry(dsn: sentryDsn, environment: sentryEnv)
} else {
Logger().warning("skipping sentry initialization - SENTRY_DSN not configured")
Logger().warning("skipping sentry initialization - SENTRY_DSN_IOS not configured")
}
}
}

0 comments on commit 4f46c4a

Please sign in to comment.