Commit a7887fe0 authored by Daniel Wolf's avatar Daniel Wolf
Browse files

Add a Sentry config server which can be used to dynamically provide a Sentry DSN

parent a58f51b6
...@@ -18,7 +18,8 @@ android { ...@@ -18,7 +18,8 @@ android {
buildConfigField("Boolean", "FROM_CI", String.valueOf(getSystemVariableOrDefault("CI_COMMIT_SHORT_SHA", "") != "")) buildConfigField("Boolean", "FROM_CI", String.valueOf(getSystemVariableOrDefault("CI_COMMIT_SHORT_SHA", "") != ""))
buildConfigField("String", "COMMIT_HASH", '"' + getGitCommitHash() + '"') buildConfigField("String", "COMMIT_HASH", '"' + getGitCommitHash() + '"')
buildConfigField("String", "SENTRY_DSN", '""') buildConfigField("String", "SENTRY_DSN", '"dummy"') // A valid Sentry DSN, or "dummy"
buildConfigField("String", "SENTRY_DSN_CONFIGSERVER", '"dummy"') // A host which returns a valid Sentry DSN on GET, or "dummy". If both are dummy Sentry is disabled.
buildConfigField("Boolean", "SHOW_DOQ", 'false') buildConfigField("Boolean", "SHOW_DOQ", 'false')
buildConfigField("Boolean", "SHOW_INTRO", 'false') buildConfigField("Boolean", "SHOW_INTRO", 'false')
buildConfigField("Boolean", "IN_APP_UPDATES", "false") buildConfigField("Boolean", "IN_APP_UPDATES", "false")
......
...@@ -24,15 +24,13 @@ import io.sentry.Sentry ...@@ -24,15 +24,13 @@ import io.sentry.Sentry
import io.sentry.SentryOptions import io.sentry.SentryOptions
import io.sentry.android.core.* import io.sentry.android.core.*
import io.sentry.protocol.User import io.sentry.protocol.User
import kotlinx.coroutines.Dispatchers import okhttp3.*
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.minidns.dnsmessage.DnsMessage import org.minidns.dnsmessage.DnsMessage
import org.minidns.dnsmessage.Question import org.minidns.dnsmessage.Question
import org.minidns.record.A import org.minidns.record.A
import org.minidns.record.AAAA import org.minidns.record.AAAA
import org.minidns.record.Record import org.minidns.record.Record
import java.net.InetAddress import java.io.IOException
import java.util.* import java.util.*
import kotlin.system.exitProcess import kotlin.system.exitProcess
...@@ -172,75 +170,121 @@ class SmokeScreen : Application() { ...@@ -172,75 +170,121 @@ class SmokeScreen : Application() {
} }
fun initSentry(forceStatus: Status = Status.NONE) { fun initSentry(forceStatus: Status = Status.NONE) {
if (!BuildConfig.DEBUG && BuildConfig.SENTRY_DSN != "dummy") { val enabledType = getPreferences().crashreportingType
log("Sentry will be initialized.") if (forceStatus == Status.NONE &&
GlobalScope.launch(Dispatchers.IO) { enabledType == Crashreporting.OFF) return
log("Initializing Sentry.") log("Maybe initializing Sentry")
sentryReady = false getSentryDSN { resolvedDSN ->
try { log("Initializing Sentry.")
val hostName = InetAddress.getLocalHost().hostName sentryReady = false
if(!hostName.startsWith("mars-sandbox", true)) { try {
val enabledType = getPreferences().crashreportingType if (sentryReady) {
if (forceStatus != Status.DATASAVING && (enabledType == Crashreporting.FULL || forceStatus == Status.ENABLED)) { log("Reinitializing Sentry with new DSN")
// Enable Sentry in full mode SentryAndroid.init(this@SmokeScreen) {
// This passes some device-related data, but nothing which allows user actions to be tracked across the app it.dsn = resolvedDSN
// Info: Some data is attached by the AndroidEventBuilderHelper class, which is present by default }
} else {
if (forceStatus != Status.DATASAVING && (enabledType == Crashreporting.FULL || forceStatus == Status.ENABLED)) {
// Enable Sentry in full mode
// This passes some device-related data, but nothing which allows user actions to be tracked across the app
// Info: Some data is attached by the AndroidEventBuilderHelper class, which is present by default
SentryAndroid.init(this@SmokeScreen) { SentryAndroid.init(this@SmokeScreen) {
it.dsn = BuildConfig.SENTRY_DSN it.dsn = resolvedDSN
} }
Sentry.setUser(User().apply { Sentry.setUser(User().apply {
this.username = getPreferences().crashReportingUUID this.username = getPreferences().crashReportingUUID
}) })
Sentry.setTag("user.language", Locale.getDefault().displayLanguage) Sentry.setTag("user.language", Locale.getDefault().displayLanguage)
Sentry.setTag( Sentry.setTag(
"app.database_version", "app.database_version",
AppDatabase.currentVersion.toString() AppDatabase.currentVersion.toString()
) )
Sentry.setTag( Sentry.setTag(
"app.dns_server_name", "app.dns_server_name",
getPreferences().dnsServerConfig.name getPreferences().dnsServerConfig.name
) )
Sentry.setTag( Sentry.setTag(
"app.dns_server_primary", "app.dns_server_primary",
getPreferences().dnsServerConfig.servers[0].address.formatToString() getPreferences().dnsServerConfig.servers[0].address.formatToString()
) )
Sentry.setTag( Sentry.setTag(
"app.dns_server_secondary", "app.dns_server_secondary",
getPreferences().dnsServerConfig.servers.getOrNull(1)?.address?.formatToString() getPreferences().dnsServerConfig.servers.getOrNull(1)?.address?.formatToString()
?: "" ?: ""
) )
Sentry.setTag( Sentry.setTag(
"app.installer_package", "app.installer_package",
packageManager.getInstallerPackageName(packageName) ?: "" packageManager.getInstallerPackageName(packageName) ?: ""
) )
Sentry.setTag("richdata", "true") Sentry.setTag("richdata", "true")
Sentry.setTag("app.fromCi", BuildConfig.FROM_CI.toString()) Sentry.setTag("app.fromCi", BuildConfig.FROM_CI.toString())
Sentry.setTag("app.commit", BuildConfig.COMMIT_HASH) Sentry.setTag("app.commit", BuildConfig.COMMIT_HASH)
sentryReady = true sentryReady = true
} else if (enabledType == Crashreporting.MINIMAL || forceStatus == Status.DATASAVING) { } else if (enabledType == Crashreporting.MINIMAL || forceStatus == Status.DATASAVING) {
// Inits Sentry in datasaving mode // Inits Sentry in datasaving mode
// Only data absolutely necessary is transmitted (Android version, app version). // Only data absolutely necessary is transmitted (Android version, app version).
// Only crashes will be reported, no regular events. // Only crashes will be reported, no regular events.
SentryAndroid.init(this@SmokeScreen) { SentryAndroid.init(this@SmokeScreen) {
it.dsn = BuildConfig.SENTRY_DSN it.dsn = resolvedDSN
setupSentryForDatasaving(it) setupSentryForDatasaving(it)
}
Sentry.setUser(User().apply {
this.username = "anon-" + BuildConfig.VERSION_CODE
})
Sentry.setTag("richdata", "false")
Sentry.setTag("dist", BuildConfig.VERSION_CODE.toString())
Sentry.setTag("app.commit", BuildConfig.COMMIT_HASH)
Sentry.setTag("app.fromCi", BuildConfig.FROM_CI.toString())
sentryReady = true
} }
Sentry.setUser(User().apply {
this.username = "anon-" + BuildConfig.VERSION_CODE
})
Sentry.setTag("richdata", "false")
Sentry.setTag("dist", BuildConfig.VERSION_CODE.toString())
Sentry.setTag("app.commit", BuildConfig.COMMIT_HASH)
Sentry.setTag("app.fromCi", BuildConfig.FROM_CI.toString())
sentryReady = true
} }
} catch(ex:Throwable) {
ex.printStackTrace()
} }
log("Sentry ready.") log("Sentry ready.")
} catch (ex: Throwable) {
log("Creating Sentry errored")
log(ex)
}
}
}
private fun getSentryDSN(then:(dsn:String) -> Unit) {
try {
val primaryDSN = BuildConfig.SENTRY_DSN
val configServer = BuildConfig.SENTRY_DSN_CONFIGSERVER
if(primaryDSN.contains("@")) then(primaryDSN)
else log("Primary Sentry DSN not set, maybe retrieving from server")
if(configServer.isNotBlank() && configServer.startsWith("http") && !configServer.contains("@")) {
log("Dynamically retrieving Sentry DSN from $configServer")
val request = Request.Builder().url(configServer).build()
OkHttpClient.Builder().build().newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
log("Sentry DSN retrieval failed with error: ${e.message}")
}
override fun onResponse(call: Call, response: Response) {
println("RESPONSE")
if (!response.isSuccessful) {
log("Sentry DSN retrieval failed with status ${response.code}")
}
val retrievedDSN = response.body?.string()?.trim()
if (retrievedDSN.isNullOrBlank() || !retrievedDSN.contains("@") || !retrievedDSN.startsWith(
"http"
)
) {
log("Sentry DSN retrieval returned invalid DSN '$retrievedDSN'.")
} else {
if (true || retrievedDSN != primaryDSN) {
log("Sentry DSN successfuly resolved to '$retrievedDSN'")
then(retrievedDSN)
} else log("Retrieved Sentry DSN is the same as configured DSN, not re-configuring")
}
}
})
} }
} catch (ex:Throwable) {
log("Getting Sentry DSN errorerd")
log(ex)
} }
} }
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment