Merge pull request #193 from zcash/feature/integrate-bugsnag
Feature/integrate bugsnag
This commit is contained in:
commit
a6cf504972
|
@ -5,7 +5,6 @@ apply plugin: 'kotlin-android'
|
|||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
apply plugin: 'com.google.gms.google-services'
|
||||
apply plugin: 'com.google.firebase.crashlytics'
|
||||
//apply plugin: 'com.github.ben-manes.versions'
|
||||
|
||||
archivesBaseName = 'zcash-android-wallet'
|
||||
|
@ -27,6 +26,7 @@ android {
|
|||
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
||||
testInstrumentationRunnerArguments clearPackageData: 'true'
|
||||
multiDexEnabled true
|
||||
resValue 'string', 'bugsnag_api_key', "${(project.findProperty('BUGSNAG_API_KEY') ?: System.getenv('BUGSNAG_API_KEY')) ?: ''}"
|
||||
}
|
||||
flavorDimensions 'network'
|
||||
productFlavors {
|
||||
|
@ -145,8 +145,8 @@ dependencies {
|
|||
implementation Deps.JavaX.JAVA_ANNOTATION
|
||||
|
||||
// Analytics (for dogfooding/crash-reporting/feedback only on internal team builds)
|
||||
implementation Deps.Analytics.CRASHLYTICS
|
||||
implementation Deps.Analytics.MIXPANEL
|
||||
implementation Deps.Analytics.BUGSNAG
|
||||
|
||||
// Misc.
|
||||
implementation Deps.Misc.LOTTIE
|
||||
|
|
|
@ -33,8 +33,6 @@
|
|||
|
||||
<!-- Firebase options -->
|
||||
<meta-data android:name="com.google.firebase.ml.vision.DEPENDENCIES" android:value="barcode" />
|
||||
<!-- All reporting is opt-in, only -->
|
||||
<meta-data android:name="firebase_crashlytics_collection_enabled" android:value="false" />
|
||||
|
||||
<!-- Mixpanel options -->
|
||||
<meta-data android:name="com.mixpanel.android.MPConfig.AutoShowMixpanelUpdates" android:value="false" />
|
||||
|
|
|
@ -9,7 +9,6 @@ import cash.z.ecc.android.feedback.*
|
|||
import cash.z.ecc.android.sdk.ext.SilentTwig
|
||||
import cash.z.ecc.android.sdk.ext.TroubleshootingTwig
|
||||
import cash.z.ecc.android.sdk.ext.Twig
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.multibindings.IntoSet
|
||||
|
@ -50,7 +49,6 @@ class AppModule {
|
|||
): FeedbackCoordinator {
|
||||
return preferences.getBoolean(FeedbackCoordinator.ENABLED, false).let { isEnabled ->
|
||||
// observe nothing unless feedback is enabled
|
||||
FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(isEnabled)
|
||||
Twig.plant(if (isEnabled) TroubleshootingTwig() else SilentTwig())
|
||||
FeedbackCoordinator(feedback, if (isEnabled) defaultObservers else setOf())
|
||||
}
|
||||
|
@ -79,5 +77,5 @@ class AppModule {
|
|||
@Provides
|
||||
@Singleton
|
||||
@IntoSet
|
||||
fun provideFeedbackCrashlytics(): FeedbackCoordinator.FeedbackObserver = FeedbackCrashlytics()
|
||||
fun provideFeedbackBugsnag(): FeedbackCoordinator.FeedbackObserver = FeedbackBugsnag()
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import dagger.Reusable
|
|||
|
||||
@Module
|
||||
class InitializerModule {
|
||||
private val host = "lightwalletd.z.cash"
|
||||
private val host = "lightwalletd.electriccoin.co"
|
||||
private val port = 9067
|
||||
|
||||
@Provides
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
package cash.z.ecc.android.feedback
|
||||
|
||||
import cash.z.ecc.android.R
|
||||
import cash.z.ecc.android.ZcashWalletApp
|
||||
import cash.z.ecc.android.sdk.ext.twig
|
||||
import com.bugsnag.android.Bugsnag
|
||||
import com.bugsnag.android.Configuration
|
||||
|
||||
class FeedbackBugsnag : FeedbackCoordinator.FeedbackObserver {
|
||||
|
||||
var isInitialized = false
|
||||
|
||||
override fun initialize(): FeedbackCoordinator.FeedbackObserver = apply {
|
||||
ZcashWalletApp.instance.let { appContext ->
|
||||
appContext.getString(R.string.bugsnag_api_key)
|
||||
.takeUnless { it.isNullOrEmpty() }?.let { apiKey ->
|
||||
twig("starting bugsnag")
|
||||
val config = Configuration(apiKey)
|
||||
Bugsnag.start(appContext, config)
|
||||
isInitialized = true
|
||||
} ?: onInitError()
|
||||
}
|
||||
}
|
||||
|
||||
private fun onInitError() {
|
||||
twig("Warning: Failed to load bugsnag because the API key was missing!")
|
||||
}
|
||||
|
||||
/**
|
||||
* Report non-fatal crashes because fatal ones already get reported by default.
|
||||
*/
|
||||
override fun onAction(action: Feedback.Action) {
|
||||
if (!isInitialized) return
|
||||
|
||||
when (action) {
|
||||
is Feedback.Crash -> action.exception
|
||||
is Feedback.NonFatal -> action.exception
|
||||
is Report.Error.NonFatal.Reorg -> ReorgException(
|
||||
action.errorHeight,
|
||||
action.rewindHeight,
|
||||
action.toString()
|
||||
)
|
||||
else -> null
|
||||
}?.let { exception ->
|
||||
val details = kotlin.runCatching { action.toMap() }.getOrElse { mapOf() }
|
||||
Bugsnag.notify(exception) { event ->
|
||||
if (details.isNotEmpty()) event.addMetadata("errorDetails", details)
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ReorgException(errorHeight: Int, rewindHeight: Int, reorgMesssage: String) :
|
||||
Throwable(reorgMesssage)
|
||||
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package cash.z.ecc.android.feedback
|
||||
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
|
||||
class FeedbackCrashlytics : FeedbackCoordinator.FeedbackObserver {
|
||||
/**
|
||||
* Report non-fatal crashes because fatal ones already get reported by default.
|
||||
*/
|
||||
override fun onAction(action: Feedback.Action) {
|
||||
var exception: Throwable? = null
|
||||
exception = when (action) {
|
||||
is Feedback.Crash -> action.exception
|
||||
is Feedback.NonFatal -> action.exception
|
||||
is Report.Error.NonFatal.Reorg -> ReorgException(
|
||||
action.errorHeight,
|
||||
action.rewindHeight,
|
||||
action.toString()
|
||||
)
|
||||
else -> null
|
||||
}
|
||||
exception?.let { FirebaseCrashlytics.getInstance().recordException(it) }
|
||||
}
|
||||
|
||||
private class ReorgException(errorHeight: Int, rewindHeight: Int, reorgMesssage: String) :
|
||||
Throwable(reorgMesssage)
|
||||
}
|
|
@ -11,8 +11,10 @@ class FeedbackFile(fileName: String = "user_log.txt") :
|
|||
val file = File("${ZcashWalletApp.instance.filesDir}/logs", fileName)
|
||||
private val format = SimpleDateFormat("MM-dd HH:mm:ss.SSS")
|
||||
|
||||
init {
|
||||
if (!file.parentFile.exists()) file.parentFile.mkdirs()
|
||||
override fun initialize(): FeedbackCoordinator.FeedbackObserver = apply {
|
||||
file.parentFile?.apply {
|
||||
if (!exists()) mkdirs()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onMetric(metric: Feedback.Metric) {
|
||||
|
|
|
@ -7,8 +7,12 @@ import com.mixpanel.android.mpmetrics.MixpanelAPI
|
|||
|
||||
class FeedbackMixpanel : FeedbackCoordinator.FeedbackObserver {
|
||||
|
||||
private val mixpanel =
|
||||
MixpanelAPI.getInstance(ZcashWalletApp.instance, R.string.mixpanel_project.toAppString())
|
||||
private lateinit var mixpanel: MixpanelAPI
|
||||
|
||||
override fun initialize(): FeedbackCoordinator.FeedbackObserver = apply {
|
||||
mixpanel =
|
||||
MixpanelAPI.getInstance(ZcashWalletApp.instance, R.string.mixpanel_project.toAppString())
|
||||
}
|
||||
|
||||
override fun onMetric(metric: Feedback.Metric) {
|
||||
track(metric.key, metric.toMap())
|
||||
|
|
|
@ -442,7 +442,7 @@ class MainActivity : AppCompatActivity() {
|
|||
}
|
||||
}
|
||||
}
|
||||
twig("MainActivity has received an error${if (notified) " and notified the user" else ""} and reported it to crashlytics and mixpanel.")
|
||||
twig("MainActivity has received an error${if (notified) " and notified the user" else ""} and reported it to bugsnag and mixpanel.")
|
||||
feedback.report(error)
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ import cash.z.ecc.android.sdk.ext.twig
|
|||
import cash.z.ecc.android.ui.base.BaseFragment
|
||||
import cash.z.ecc.android.ui.send.SendViewModel
|
||||
import com.google.common.util.concurrent.ListenableFuture
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.concurrent.ExecutorService
|
||||
import java.util.concurrent.Executors
|
||||
|
|
|
@ -13,7 +13,7 @@ buildscript {
|
|||
classpath 'com.google.gms:google-services:4.3.3'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${Deps.kotlinVersion}"
|
||||
classpath 'io.fabric.tools:gradle:1.31.2'
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.1.1'
|
||||
classpath 'com.bugsnag:bugsnag-android-gradle-plugin:4.7.5'
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ object Deps {
|
|||
val STUB = "io.grpc:grpc-stub:$version"
|
||||
}
|
||||
object Analytics { // for dogfooding/crash-reporting/feedback only on internal team builds
|
||||
val CRASHLYTICS = "com.google.firebase:firebase-crashlytics:17.0.1"
|
||||
val BUGSNAG = "com.bugsnag:bugsnag-android:5.0.1"
|
||||
val MIXPANEL = "com.mixpanel.android:mixpanel-android:5.6.3"
|
||||
}
|
||||
object JavaX {
|
||||
|
@ -80,7 +80,7 @@ object Deps {
|
|||
object Zcash {
|
||||
const val ANDROID_WALLET_PLUGINS = "cash.z.ecc.android:zcash-android-wallet-plugins:1.0.0"
|
||||
const val KOTLIN_BIP39 = "cash.z.ecc.android:kotlin-bip39:1.0.0-beta09"
|
||||
object Sdk : Version("1.1.0-beta03") {
|
||||
object Sdk : Version("1.1.0-beta04") {
|
||||
val MAINNET = "cash.z.ecc.android:sdk-mainnet:$version"
|
||||
val TESTNET = "cash.z.ecc.android:sdk-testnet:$version"
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ class FeedbackCoordinator(val feedback: Feedback, defaultObservers: Set<Feedback
|
|||
private val jobs = CompositeJob()
|
||||
val observers = mutableSetOf<FeedbackObserver>()
|
||||
|
||||
|
||||
/**
|
||||
* Wait for any in-flight listeners to complete.
|
||||
*/
|
||||
|
@ -83,7 +84,7 @@ class FeedbackCoordinator(val feedback: Feedback, defaultObservers: Set<Feedback
|
|||
*/
|
||||
fun addObserver(observer: FeedbackObserver) {
|
||||
feedback.onStart {
|
||||
observers += observer
|
||||
observers += observer.initialize()
|
||||
observeMetrics(observer::onMetric)
|
||||
observeActions(observer::onAction)
|
||||
}
|
||||
|
@ -119,6 +120,7 @@ class FeedbackCoordinator(val feedback: Feedback, defaultObservers: Set<Feedback
|
|||
}
|
||||
|
||||
interface FeedbackObserver {
|
||||
fun initialize(): FeedbackObserver { return this }
|
||||
fun onMetric(metric: Feedback.Metric) {}
|
||||
fun onAction(action: Feedback.Action) {}
|
||||
fun flush() {}
|
||||
|
|
Loading…
Reference in New Issue