diff --git a/README.md b/README.md index 73eca44..ce24cc3 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Analytics-Kotlin Bugsnag +# Analytics-Kotlin BugSnag Add Bugsnag support to your applications via this plugin for [Analytics-Kotlin](https://github.com/segmentio/analytics-kotlin) @@ -8,13 +8,30 @@ To install the Segment-bugsnag integration, simply add this line to your gradle ``` implementation 'com.segment.analytics.kotlin.destinations:bugsnag:' ``` - Or the following for Kotlin DSL - ``` implementation("com.segment.analytics.kotlin.destinations:bugsnag:") ``` +Also add the BugSnag Gradle plugin dependency to your Project project level build.gradle. +``` +buildscript { + dependencies { + // ... + classpath "com.bugsnag:bugsnag-android-gradle-plugin:7.4.1" + } +} +``` +Or the following for Kotlin DSL +``` +buildscript { + dependencies { + // ... + classpath("com.bugsnag:bugsnag-android-gradle-plugin:7.4.1") + } +} +``` + ## Using the Plugin in your App Open the file where you setup and configure the Analytics-Kotlin library. Add this plugin to the list of imports. diff --git a/build.gradle.kts b/build.gradle.kts index 292ac0f..0e15838 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -25,6 +25,7 @@ buildscript { classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0") classpath("org.jetbrains.kotlin:kotlin-serialization:1.6.0") classpath("com.android.tools.build:gradle:7.0.4") + classpath("com.bugsnag:bugsnag-android-gradle-plugin:7.4.1") } } diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index 08b32d9..e7eafd5 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -52,7 +52,7 @@ dependencies { // Partner Dependencies dependencies { - // TODO add your partner deps here + implementation("com.bugsnag:bugsnag-android:5.28.4") } // Test Dependencies diff --git a/lib/src/main/java/com/segment/analytics/kotlin/destinations/bugsnag/BugsnagDestination.kt b/lib/src/main/java/com/segment/analytics/kotlin/destinations/bugsnag/BugsnagDestination.kt index d8b6f9a..429a944 100644 --- a/lib/src/main/java/com/segment/analytics/kotlin/destinations/bugsnag/BugsnagDestination.kt +++ b/lib/src/main/java/com/segment/analytics/kotlin/destinations/bugsnag/BugsnagDestination.kt @@ -1,4 +1,100 @@ package com.segment.analytics.kotlin.destinations.bugsnag -class BugsnagDestination { +import android.app.Activity +import android.content.Context +import android.os.Bundle +import com.bugsnag.android.Client +import com.segment.analytics.kotlin.android.plugins.AndroidLifecycle +import com.segment.analytics.kotlin.core.* +import com.segment.analytics.kotlin.core.platform.DestinationPlugin +import com.segment.analytics.kotlin.core.platform.Plugin +import com.segment.analytics.kotlin.core.platform.plugins.logger.log +import com.segment.analytics.kotlin.core.utilities.toContent +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonObject + +class BugsnagDestination : DestinationPlugin(), AndroidLifecycle { + companion object { + private const val BUGSNAG_FULL_KEY = "Bugsnag" + private const val VIEWED_EVENT_FORMAT = "Viewed %s Screen" + } + internal var bugsnagSettings: BugsnagSettings? = null + + override val key: String = BUGSNAG_FULL_KEY + internal var client: Client? = null + + override fun update(settings: Settings, type: Plugin.UpdateType) { + super.update(settings, type) + if (settings.hasIntegrationSettings(this)) { + this.bugsnagSettings = + settings.destinationSettings(key, BugsnagSettings.serializer()) + if (type == Plugin.UpdateType.Initial) { + if(bugsnagSettings!=null) { + analytics.log("Client(context, ${bugsnagSettings?.apiKey})") + initializeBugsnagClient() + } + } + } + } + + override fun identify(payload: IdentifyEvent): BaseEvent { + val traitsMap = payload.traits.asStringMap() + val email: String = traitsMap["email"] ?: "" + val name: String = traitsMap["name"]?: "" + client?.setUser(payload.userId, email, name) + val userKey = "User" + for((key, value) in traitsMap) { + client?.addMetadata(userKey, key, value) + analytics.log("client!!.addMetadata($userKey, $key, $value)") + } + return payload + } + + override fun screen(payload: ScreenEvent): BaseEvent { + leaveBreadcrumb(String.format(VIEWED_EVENT_FORMAT, payload.name)) + return payload + } + + override fun track(payload: TrackEvent): BaseEvent { + leaveBreadcrumb(payload.event) + return payload + } + + override fun onActivityCreated(activity: Activity?, savedInstanceState: Bundle?) { + super.onActivityCreated(activity, savedInstanceState) + analytics.log("client.context = ${activity?.localClassName}") + client?.context = activity?.localClassName + + } + + private fun initializeBugsnagClient():Client { + if(client == null) { + client = Client(analytics.configuration.application as Context, bugsnagSettings!!.apiKey) + client!!.context = (analytics.configuration.application as Context).packageName + } + return client!! + } + private fun leaveBreadcrumb(event: String) { + client?.leaveBreadcrumb(event) + analytics.log(" client?.leaveBreadcrumb($event)") + } + + fun getUnderlyingInstance(): Client? { + return client + } +} +/** + * Bugsnag Settings data class. + */ +@Serializable +data class BugsnagSettings( +// Bugsnag API key + var apiKey: String, +// Distinguish errors that happen in different stages of app's release process e.g 'production', 'development', etc. + var releaseStage: String, +// Use SSL When Sending Data to Bugsnag, by default enabled in Segment dashboard + var useSSL: Boolean +) +private fun JsonObject.asStringMap(): Map = this.mapValues { (_, value) -> + value.toContent().toString() } \ No newline at end of file