Updated on 2026-08-14
This commit is contained in:
parent
7794446857
commit
5d448b9500
87 changed files with 223 additions and 121 deletions
|
|
@ -1,93 +0,0 @@
|
|||
package com.tangem.tap.common.analytics
|
||||
|
||||
import com.tangem.domain.common.FeatureCoroutineExceptionHandler
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsEventFilter
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsFilterHolder
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandler
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandlerHolder
|
||||
import com.tangem.tap.common.analytics.api.ParamsInterceptor
|
||||
import com.tangem.tap.common.analytics.api.ParamsInterceptorHolder
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsEvent
|
||||
import kotlinx.coroutines.CoroutineName
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.asCoroutineDispatcher
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface GlobalAnalyticsEventHandler : AnalyticsEventHandler,
|
||||
AnalyticsHandlerHolder,
|
||||
AnalyticsFilterHolder,
|
||||
ParamsInterceptorHolder
|
||||
|
||||
object Analytics : GlobalAnalyticsEventHandler {
|
||||
|
||||
private val analyticsScope: CoroutineScope by lazy { createScope() }
|
||||
|
||||
private val handlers = mutableMapOf<String, AnalyticsHandler>()
|
||||
private val paramsInterceptors = mutableMapOf<String, ParamsInterceptor>()
|
||||
private val analyticsFilters = mutableSetOf<AnalyticsEventFilter>()
|
||||
|
||||
private val analyticsHandlers: List<AnalyticsHandler>
|
||||
get() = handlers.values.toList()
|
||||
|
||||
override fun addHandler(name: String, handler: AnalyticsHandler) {
|
||||
handlers[name] = handler
|
||||
}
|
||||
|
||||
override fun removeHandler(name: String): AnalyticsHandler? {
|
||||
return handlers.remove(name)
|
||||
}
|
||||
|
||||
override fun addFilter(filter: AnalyticsEventFilter) {
|
||||
analyticsFilters.add(filter)
|
||||
}
|
||||
|
||||
override fun removeFilter(filter: AnalyticsEventFilter): Boolean {
|
||||
return analyticsFilters.remove(filter)
|
||||
}
|
||||
|
||||
override fun addParamsInterceptor(interceptor: ParamsInterceptor) {
|
||||
paramsInterceptors[interceptor.id()] = interceptor
|
||||
}
|
||||
|
||||
override fun removeParamsInterceptor(interceptor: ParamsInterceptor): ParamsInterceptor? {
|
||||
return paramsInterceptors.remove(interceptor.id())
|
||||
}
|
||||
|
||||
override fun send(event: AnalyticsEvent) {
|
||||
analyticsScope.launch {
|
||||
event.params = applyParamsInterceptors(event)
|
||||
val eventFilter = analyticsFilters.firstOrNull { it.canBeAppliedTo(event) }
|
||||
|
||||
when {
|
||||
eventFilter == null -> analyticsHandlers.forEach { handler -> handler.send(event) }
|
||||
eventFilter.canBeSent(event) -> {
|
||||
analyticsHandlers
|
||||
.filter { handler -> eventFilter.canBeConsumedByHandler(handler, event) }
|
||||
.forEach { handler -> handler.send(event) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun applyParamsInterceptors(event: AnalyticsEvent): MutableMap<String, String> {
|
||||
val interceptedParams = event.params.toMutableMap()
|
||||
paramsInterceptors.values
|
||||
.filter { it.canBeAppliedTo(event) }
|
||||
.forEach { it.intercept(interceptedParams) }
|
||||
|
||||
return interceptedParams
|
||||
}
|
||||
|
||||
private fun createScope(): CoroutineScope {
|
||||
val name = "Analytics"
|
||||
val dispatcher = Executors.newFixedThreadPool(1).asCoroutineDispatcher()
|
||||
val exHandler = FeatureCoroutineExceptionHandler.create(name)
|
||||
return CoroutineScope(SupervisorJob() + dispatcher + CoroutineName(name) + exHandler)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
package com.tangem.tap.common.analytics
|
||||
|
||||
import com.tangem.common.json.MoshiJsonConverter
|
||||
import com.tangem.tap.common.analytics.api.ErrorEventLogger
|
||||
import com.tangem.tap.common.analytics.api.EventLogger
|
||||
import com.tangem.analytics.api.ErrorEventLogger
|
||||
import com.tangem.analytics.api.EventLogger
|
||||
import timber.log.Timber
|
||||
|
||||
class AnalyticsEventsLogger(
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
package com.tangem.tap.common.analytics
|
||||
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsEventFilter
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.core.analytics.api.AnalyticsEventFilter
|
||||
import com.tangem.core.analytics.api.ParamsInterceptor
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder
|
||||
import com.tangem.tap.common.analytics.api.ParamsInterceptor
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
package com.tangem.tap.common.analytics.api
|
||||
|
||||
import android.app.Application
|
||||
import com.tangem.common.json.MoshiJsonConverter
|
||||
import com.tangem.core.analytics.api.AnalyticsHandler
|
||||
import com.tangem.domain.common.AnalyticsHandlersLogConfig
|
||||
import com.tangem.tap.domain.configurable.config.Config
|
||||
|
||||
interface AnalyticsHandlerBuilder {
|
||||
fun build(data: Data): AnalyticsHandler?
|
||||
|
||||
data class Data(
|
||||
val application: Application,
|
||||
val config: Config,
|
||||
val isDebug: Boolean,
|
||||
val logConfig: AnalyticsHandlersLogConfig,
|
||||
val jsonConverter: MoshiJsonConverter,
|
||||
)
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
package com.tangem.tap.common.analytics.api
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface EventLogger {
|
||||
fun logEvent(
|
||||
event: String,
|
||||
params: Map<String, String> = emptyMap(),
|
||||
)
|
||||
}
|
||||
|
||||
interface ErrorEventLogger {
|
||||
fun logErrorEvent(
|
||||
error: Throwable,
|
||||
params: Map<String, String> = emptyMap(),
|
||||
)
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
package com.tangem.tap.common.analytics.api
|
||||
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsEvent
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
* The filter is used to separate events to send and determine which handler it can be processed with.
|
||||
*/
|
||||
interface AnalyticsEventFilter {
|
||||
/**
|
||||
* Recognizes the event and checks if the given filter can be applied to the event.
|
||||
*/
|
||||
fun canBeAppliedTo(event: AnalyticsEvent): Boolean
|
||||
|
||||
/**
|
||||
* An internal filter check that, on external or internal conditions, recognizes the possibility of
|
||||
* sending an event.
|
||||
*/
|
||||
fun canBeSent(event: AnalyticsEvent): Boolean
|
||||
|
||||
/**
|
||||
* Performs a check to see if the event can be dispatched by a specific handler
|
||||
*/
|
||||
fun canBeConsumedByHandler(handler: AnalyticsHandler, event: AnalyticsEvent): Boolean
|
||||
}
|
||||
|
||||
interface AnalyticsFilterHolder {
|
||||
fun addFilter(filter: AnalyticsEventFilter)
|
||||
fun removeFilter(filter: AnalyticsEventFilter): Boolean
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
package com.tangem.tap.common.analytics.api
|
||||
|
||||
import android.app.Application
|
||||
import com.tangem.common.json.MoshiJsonConverter
|
||||
import com.tangem.domain.common.AnalyticsHandlersLogConfig
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsEvent
|
||||
import com.tangem.tap.domain.configurable.config.Config
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface AnalyticsEventHandler {
|
||||
fun send(event: AnalyticsEvent)
|
||||
}
|
||||
|
||||
interface AnalyticsHandler : AnalyticsEventHandler {
|
||||
fun id(): String
|
||||
|
||||
fun send(event: String, params: Map<String, String> = emptyMap())
|
||||
|
||||
override fun send(event: AnalyticsEvent) {
|
||||
send(prepareEventString(event), event.params)
|
||||
}
|
||||
|
||||
fun prepareEventString(event: AnalyticsEvent): String = "[${event.category}] ${event.event}"
|
||||
}
|
||||
|
||||
interface ErrorEventHandler {
|
||||
fun send(
|
||||
error: Throwable,
|
||||
params: Map<String, String> = emptyMap(),
|
||||
)
|
||||
}
|
||||
|
||||
interface AnalyticsHandlerHolder {
|
||||
fun addHandler(name: String, handler: AnalyticsHandler)
|
||||
fun removeHandler(name: String): AnalyticsHandler?
|
||||
}
|
||||
|
||||
interface AnalyticsHandlerBuilder {
|
||||
fun build(data: Data): AnalyticsHandler?
|
||||
|
||||
data class Data(
|
||||
val application: Application,
|
||||
val config: Config,
|
||||
val isDebug: Boolean,
|
||||
val logConfig: AnalyticsHandlersLogConfig,
|
||||
val jsonConverter: MoshiJsonConverter,
|
||||
)
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
package com.tangem.tap.common.analytics.api
|
||||
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsEvent
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface ParamsInterceptor {
|
||||
fun id(): String
|
||||
fun canBeAppliedTo(event: AnalyticsEvent): Boolean
|
||||
fun intercept(params: MutableMap<String, String>)
|
||||
}
|
||||
|
||||
interface ParamsInterceptorHolder {
|
||||
fun addParamsInterceptor(interceptor: ParamsInterceptor)
|
||||
fun removeParamsInterceptor(interceptor: ParamsInterceptor): ParamsInterceptor?
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
sealed class AnalyticsEvent(
|
||||
val category: String,
|
||||
val event: String,
|
||||
var params: Map<String, String> = mapOf(),
|
||||
val error: Throwable? = null,
|
||||
var filterData: Any? = null,
|
||||
)
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
import com.tangem.domain.common.extensions.toNetworkId
|
||||
import com.tangem.domain.features.addCustomToken.CustomCurrency
|
||||
import com.tangem.tap.common.extensions.filterNotNull
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
|
||||
sealed class MyWallets(
|
||||
event: String,
|
||||
params: Map<String, String> = mapOf(),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
import com.tangem.tap.features.details.ui.details.SocialNetwork
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
import com.tangem.tap.common.extensions.filterNotNull
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam.CurrencyType
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
package com.tangem.tap.common.analytics.filters
|
||||
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsEventFilter
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandler
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsEvent
|
||||
import com.tangem.core.analytics.api.AnalyticsEventFilter
|
||||
import com.tangem.core.analytics.api.AnalyticsHandler
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
import com.tangem.tap.common.analytics.events.Basic
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
package com.tangem.tap.common.analytics.filters
|
||||
|
||||
import com.tangem.common.extensions.guard
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsEventFilter
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandler
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsEvent
|
||||
import com.tangem.core.analytics.api.AnalyticsEventFilter
|
||||
import com.tangem.core.analytics.api.AnalyticsHandler
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Basic
|
||||
import com.tangem.tap.persistence.ToppedUpWalletStorage
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
package com.tangem.tap.common.analytics.filters
|
||||
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsEventFilter
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandler
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsEvent
|
||||
import com.tangem.core.analytics.api.AnalyticsEventFilter
|
||||
import com.tangem.core.analytics.api.AnalyticsHandler
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
import com.tangem.tap.common.analytics.events.Shop
|
||||
import com.tangem.tap.common.analytics.handlers.appsFlyer.AppsFlyerAnalyticsHandler
|
||||
import com.tangem.tap.common.analytics.handlers.firebase.FirebaseAnalyticsHandler
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.tap.common.analytics.handlers.amplitude
|
||||
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandler
|
||||
import com.tangem.core.analytics.api.AnalyticsHandler
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder
|
||||
|
||||
class AmplitudeAnalyticsHandler(
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import android.app.Application
|
|||
import com.amplitude.api.Amplitude
|
||||
import com.amplitude.api.AmplitudeClient
|
||||
import com.tangem.common.Converter
|
||||
import com.tangem.tap.common.analytics.api.EventLogger
|
||||
import com.tangem.analytics.api.EventLogger
|
||||
import org.json.JSONObject
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.tap.common.analytics.handlers.appsFlyer
|
||||
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandler
|
||||
import com.tangem.core.analytics.api.AnalyticsHandler
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder
|
||||
|
||||
class AppsFlyerAnalyticsHandler(
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package com.tangem.tap.common.analytics.handlers.appsFlyer
|
|||
|
||||
import android.content.Context
|
||||
import com.appsflyer.AppsFlyerLib
|
||||
import com.tangem.tap.common.analytics.api.EventLogger
|
||||
import com.tangem.analytics.api.EventLogger
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
package com.tangem.tap.common.analytics.handlers.firebase
|
||||
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandler
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
import com.tangem.core.analytics.api.AnalyticsHandler
|
||||
import com.tangem.core.analytics.api.ErrorEventHandler
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder
|
||||
import com.tangem.tap.common.analytics.api.ErrorEventHandler
|
||||
import com.tangem.tap.common.analytics.converters.AnalyticsErrorConverter
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsEvent
|
||||
|
||||
class FirebaseAnalyticsHandler(
|
||||
private val client: FirebaseAnalyticsClient,
|
||||
|
|
@ -17,18 +17,18 @@ class FirebaseAnalyticsHandler(
|
|||
}
|
||||
|
||||
override fun send(event: AnalyticsEvent) {
|
||||
when (event.error) {
|
||||
null -> super.send(event)
|
||||
else -> {
|
||||
val errorConverter = AnalyticsErrorConverter()
|
||||
if (!errorConverter.canBeHandled(event.error)) return
|
||||
val error = event.error
|
||||
if (error == null) {
|
||||
super.send(event)
|
||||
} else {
|
||||
val errorConverter = AnalyticsErrorConverter()
|
||||
if (!errorConverter.canBeHandled(error)) return
|
||||
|
||||
val errorParams = errorConverter.convert(event.error).toMutableMap()
|
||||
errorParams["Category"] = event.category
|
||||
errorParams["Event"] = event.event
|
||||
errorParams.putAll(event.params)
|
||||
send(event.error, errorParams)
|
||||
}
|
||||
val errorParams = errorConverter.convert(error).toMutableMap()
|
||||
errorParams["Category"] = event.category
|
||||
errorParams["Event"] = event.event
|
||||
errorParams.putAll(event.params)
|
||||
send(error, errorParams)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ import com.google.firebase.analytics.FirebaseAnalytics
|
|||
import com.google.firebase.analytics.ktx.analytics
|
||||
import com.google.firebase.crashlytics.ktx.crashlytics
|
||||
import com.google.firebase.ktx.Firebase
|
||||
import com.tangem.tap.common.analytics.api.ErrorEventLogger
|
||||
import com.tangem.tap.common.analytics.api.EventLogger
|
||||
import com.tangem.analytics.api.ErrorEventLogger
|
||||
import com.tangem.analytics.api.EventLogger
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package com.tangem.tap.common.analytics.paramsInterceptor
|
||||
|
||||
import com.tangem.tap.common.analytics.api.ParamsInterceptor
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsEvent
|
||||
import com.tangem.core.analytics.api.ParamsInterceptor
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import android.app.Application
|
|||
import android.content.Intent
|
||||
import com.google.android.gms.wallet.PaymentData
|
||||
import com.shopify.buy3.Storefront
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.converters.ShopOrderToEventConverter
|
||||
import com.tangem.tap.common.extensions.filterNotNull
|
||||
import com.tangem.tap.common.shop.data.ProductType
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue