From de93d0f3503a9fd2c3dc6ed1f755a1ffeba07693 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 8 Nov 2022 18:26:18 +0500 Subject: [PATCH] Updated on 2026-08-14 --- app/src/main/assets/tangem-app-config | 2 +- .../tangem/tap/common/analytics/Analytics.kt | 67 +++++++++++++------ .../analytics/GlobalAnalyticsEventHandler.kt | 21 ------ .../analytics/api/ErrorEventHandlerApi.kt | 37 ++++++++++ .../common/analytics/api/EventFilterApi.kt | 7 +- .../common/analytics/api/EventHandlerApi.kt | 41 +----------- .../analytics/api/ParamsInterceptorApi.kt | 17 +++++ .../common/analytics/events/AnalyticsParam.kt | 4 +- .../tap/common/analytics/events/Basic.kt | 2 +- .../analytics/filters/BasicSignInFilter.kt | 2 +- .../analytics/filters/BasicTopUpFilter.kt | 2 +- .../filters/ShopPurchasedEventFilter.kt | 2 +- .../BatchIdParamsInterceptor.kt | 21 ++++++ .../tap/features/home/redux/HomeMiddleware.kt | 4 +- 14 files changed, 140 insertions(+), 89 deletions(-) delete mode 100644 app/src/main/java/com/tangem/tap/common/analytics/GlobalAnalyticsEventHandler.kt create mode 100644 app/src/main/java/com/tangem/tap/common/analytics/api/ErrorEventHandlerApi.kt create mode 100644 app/src/main/java/com/tangem/tap/common/analytics/api/ParamsInterceptorApi.kt create mode 100644 app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/BatchIdParamsInterceptor.kt diff --git a/app/src/main/assets/tangem-app-config b/app/src/main/assets/tangem-app-config index cf6ea50867..a1658496e7 160000 --- a/app/src/main/assets/tangem-app-config +++ b/app/src/main/assets/tangem-app-config @@ -1 +1 @@ -Subproject commit cf6ea50867477f97655da9da47ff94987e8f3354 +Subproject commit a1658496e777b611fc990ef2bc1a1a1fd48bc1e6 diff --git a/app/src/main/java/com/tangem/tap/common/analytics/Analytics.kt b/app/src/main/java/com/tangem/tap/common/analytics/Analytics.kt index 6e773bceab..3950438219 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/Analytics.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/Analytics.kt @@ -6,9 +6,15 @@ import com.tangem.common.core.TangemSdkError 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.AnalyticsHandlerHolder import com.tangem.tap.common.analytics.api.BlockchainSdkErrorEventHandler import com.tangem.tap.common.analytics.api.CardSdkErrorEventHandler +import com.tangem.tap.common.analytics.api.ErrorEventHandler import com.tangem.tap.common.analytics.api.ErrorEventLogger +import com.tangem.tap.common.analytics.api.ParamsInterceptor +import com.tangem.tap.common.analytics.api.ParamsInterceptorHolder +import com.tangem.tap.common.analytics.api.SdkErrorEventHandler import com.tangem.tap.common.analytics.events.AnalyticsEvent import com.tangem.tap.common.extensions.filterNotNull import kotlinx.coroutines.CoroutineName @@ -21,18 +27,27 @@ import java.util.concurrent.Executors /** [REDACTED_AUTHOR] */ +interface GlobalAnalyticsEventHandler : AnalyticsEventHandler, + ErrorEventHandler, + SdkErrorEventHandler, + AnalyticsHandlerHolder, + AnalyticsFilterHolder, + ParamsInterceptorHolder { + + fun send(event: AnalyticsEvent, card: Card? = null, blockchain: String? = null) +} + object Analytics : GlobalAnalyticsEventHandler { - internal val analyticsScope: CoroutineScope by lazy { createScope() } + private val analyticsScope: CoroutineScope by lazy { createScope() } - private val eventFilters = mutableListOf() private val handlers = mutableMapOf() + private val analyticsFilters = mutableSetOf() + private val paramsInterceptors = mutableMapOf() private val analyticsHandlers: List get() = handlers.values.toList() - private val attachToAllEventsParams: MutableMap = mutableMapOf() - override fun id(): String = analyticsHandlers.joinToString(", ") { it.id() } override fun addHandler(name: String, handler: AnalyticsEventHandler) { @@ -44,33 +59,39 @@ object Analytics : GlobalAnalyticsEventHandler { } override fun addFilter(filter: AnalyticsEventFilter) { - eventFilters.add(filter) + analyticsFilters.add(filter) } - override fun removeFilter(filter: AnalyticsEventFilter) { - eventFilters.remove(filter) + override fun removeFilter(filter: AnalyticsEventFilter): Boolean { + return analyticsFilters.remove(filter) } - override fun attachToAllEvents(key: String, value: String) { - attachToAllEventsParams[key] = value + override fun addParamsInterceptor(interceptor: ParamsInterceptor) { + paramsInterceptors[interceptor.id()] = interceptor + } + + override fun removeParamsInterceptor(interceptor: ParamsInterceptor): ParamsInterceptor? { + return paramsInterceptors.remove(interceptor.id()) } override fun send(event: String, params: Map) { analyticsScope.launch { - analyticsHandlers.forEach { it.send(event, params) } + analyticsHandlers.forEach { it.send(event, params.interceptParams()) } } } override fun send(event: AnalyticsEvent, card: Card?, blockchain: String?) { analyticsScope.launch { - val eventFilter = eventFilters.firstOrNull { it.canBeAppliedTo(event) } + val eventString = prepareEventString(event.category, event.event) + val eventParams = prepareParams(card, blockchain, event.interceptParams()) + val eventFilter = analyticsFilters.firstOrNull { it.canBeAppliedTo(event) } when { - eventFilter == null -> analyticsHandlers.forEach { it.send(event, card, blockchain) } + eventFilter == null -> analyticsHandlers.forEach { it.send(eventString, eventParams) } eventFilter.canBeSent(event) -> { analyticsHandlers - .filter { eventFilter.canBeConsumedBy(it, event) } - .forEach { it.send(event) } + .filter { handler -> eventFilter.canBeConsumedByHandler(handler, event) } + .forEach { it.send(eventString, eventParams) } } } } @@ -84,7 +105,7 @@ object Analytics : GlobalAnalyticsEventHandler { ) { analyticsScope.launch { analyticsHandlers.forEach { - it.handleAnalyticsEvent(event, params, card, blockchain) + it.handleAnalyticsEvent(event, params.interceptParams(), card, blockchain) } } } @@ -123,17 +144,21 @@ object Analytics : GlobalAnalyticsEventHandler { } } - override fun prepareParams(card: Card?, blockchain: String?, params: Map): Map { - return super.prepareParams(card, blockchain, params).toMutableMap().apply { - putAll(attachToAllEventsParams) - } + private fun AnalyticsEvent.interceptParams(): Map = params.interceptParams() + + private fun Map.interceptParams(): Map { + return this.toMutableMap().apply { interceptParams() } + } + + private fun MutableMap.interceptParams() { + paramsInterceptors.values.forEach { it.intercept(this) } } private fun createScope(): CoroutineScope { val name = "Analytics" val dispatcher = Executors.newFixedThreadPool(1).asCoroutineDispatcher() - val exceptionHandler = FeatureCoroutineExceptionHandler.create(name) - return CoroutineScope(Job() + dispatcher + CoroutineName(name) + exceptionHandler) + val exHandler = FeatureCoroutineExceptionHandler.create(name) + return CoroutineScope(Job() + dispatcher + CoroutineName(name) + exHandler) } } diff --git a/app/src/main/java/com/tangem/tap/common/analytics/GlobalAnalyticsEventHandler.kt b/app/src/main/java/com/tangem/tap/common/analytics/GlobalAnalyticsEventHandler.kt deleted file mode 100644 index 287f991527..0000000000 --- a/app/src/main/java/com/tangem/tap/common/analytics/GlobalAnalyticsEventHandler.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.tangem.tap.common.analytics - -import com.tangem.tap.common.analytics.api.AnalyticsEventFilter -import com.tangem.tap.common.analytics.api.AnalyticsEventHandler -import com.tangem.tap.common.analytics.api.ErrorEventHandler -import com.tangem.tap.common.analytics.api.SdkErrorEventHandler - -interface GlobalAnalyticsEventHandler : AnalyticsEventHandler, - ErrorEventHandler, - SdkErrorEventHandler { - - fun addHandler(name: String, handler: AnalyticsEventHandler) - - fun removeHandler(name: String): AnalyticsEventHandler? - - fun addFilter(filter: AnalyticsEventFilter) - - fun removeFilter(filter: AnalyticsEventFilter) - - fun attachToAllEvents(key: String, value: String) -} diff --git a/app/src/main/java/com/tangem/tap/common/analytics/api/ErrorEventHandlerApi.kt b/app/src/main/java/com/tangem/tap/common/analytics/api/ErrorEventHandlerApi.kt new file mode 100644 index 0000000000..3279075ea4 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/common/analytics/api/ErrorEventHandlerApi.kt @@ -0,0 +1,37 @@ +package com.tangem.tap.common.analytics.api + +import com.tangem.blockchain.common.BlockchainError +import com.tangem.common.card.Card +import com.tangem.common.core.TangemSdkError +import com.tangem.tap.common.analytics.AnalyticsAnOld +import com.tangem.tap.common.analytics.AnalyticsParamAnOld + +/** +[REDACTED_AUTHOR] + */ +interface ErrorEventHandler { + fun send( + error: Throwable, + params: Map = emptyMap(), + ) +} + +interface SdkErrorEventHandler : CardSdkErrorEventHandler, BlockchainSdkErrorEventHandler + +interface CardSdkErrorEventHandler { + fun send( + error: TangemSdkError, + action: AnalyticsAnOld.ActionToLog, + params: Map = emptyMap(), + card: Card? = null, + ) +} + +interface BlockchainSdkErrorEventHandler { + fun send( + error: BlockchainError, + action: AnalyticsAnOld.ActionToLog, + params: Map = mapOf(), + card: Card? = null, + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/analytics/api/EventFilterApi.kt b/app/src/main/java/com/tangem/tap/common/analytics/api/EventFilterApi.kt index a4e93fa75b..c86313164b 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/api/EventFilterApi.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/api/EventFilterApi.kt @@ -8,5 +8,10 @@ import com.tangem.tap.common.analytics.events.AnalyticsEvent interface AnalyticsEventFilter { fun canBeAppliedTo(event: AnalyticsEvent): Boolean fun canBeSent(event: AnalyticsEvent): Boolean - fun canBeConsumedBy(handler: AnalyticsEventHandler, event: AnalyticsEvent): Boolean + fun canBeConsumedByHandler(handler: AnalyticsEventHandler, event: AnalyticsEvent): Boolean +} + +interface AnalyticsFilterHolder { + fun addFilter(filter: AnalyticsEventFilter) + fun removeFilter(filter: AnalyticsEventFilter): Boolean } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/analytics/api/EventHandlerApi.kt b/app/src/main/java/com/tangem/tap/common/analytics/api/EventHandlerApi.kt index 494747287e..5095d83dfa 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/api/EventHandlerApi.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/api/EventHandlerApi.kt @@ -1,15 +1,10 @@ package com.tangem.tap.common.analytics.api import android.app.Application -import com.tangem.blockchain.common.BlockchainError import com.tangem.common.card.Card -import com.tangem.common.core.TangemSdkError import com.tangem.common.json.MoshiJsonConverter import com.tangem.domain.common.AnalyticsHandlersLogConfig -import com.tangem.tap.common.analytics.AnalyticsAnOld import com.tangem.tap.common.analytics.AnalyticsEventAnOld -import com.tangem.tap.common.analytics.AnalyticsParamAnOld -import com.tangem.tap.common.analytics.events.AnalyticsEvent import com.tangem.tap.common.analytics.events.AnalyticsParam import com.tangem.tap.common.extensions.filterNotNull import com.tangem.tap.domain.configurable.config.Config @@ -22,13 +17,6 @@ interface AnalyticsEventHandler { fun send(event: String, params: Map = emptyMap()) - fun send(event: AnalyticsEvent, card: Card? = null, blockchain: String? = null) { - send( - event = prepareEventString(event.category, event.event), - params = prepareParams(card, blockchain, event.params), - ) - } - @Deprecated("Migrate to AnalyticsEvent") fun handleAnalyticsEvent( event: AnalyticsEventAnOld, @@ -45,7 +33,6 @@ interface AnalyticsEventHandler { params: Map = emptyMap(), ): Map = mapOf( AnalyticsParam.Firmware to card?.firmwareVersion?.stringValue, - AnalyticsParam.BatchId to card?.batchId, AnalyticsParam.Blockchain to blockchain, ).filterNotNull() + params @@ -54,31 +41,9 @@ interface AnalyticsEventHandler { } } -interface ErrorEventHandler { - fun send( - error: Throwable, - params: Map = emptyMap(), - ) -} - -interface SdkErrorEventHandler : CardSdkErrorEventHandler, BlockchainSdkErrorEventHandler - -interface CardSdkErrorEventHandler { - fun send( - error: TangemSdkError, - action: AnalyticsAnOld.ActionToLog, - params: Map = emptyMap(), - card: Card? = null, - ) -} - -interface BlockchainSdkErrorEventHandler { - fun send( - error: BlockchainError, - action: AnalyticsAnOld.ActionToLog, - params: Map = mapOf(), - card: Card? = null, - ) +interface AnalyticsHandlerHolder { + fun addHandler(name: String, handler: AnalyticsEventHandler) + fun removeHandler(name: String): AnalyticsEventHandler? } interface AnalyticsHandlerBuilder { diff --git a/app/src/main/java/com/tangem/tap/common/analytics/api/ParamsInterceptorApi.kt b/app/src/main/java/com/tangem/tap/common/analytics/api/ParamsInterceptorApi.kt new file mode 100644 index 0000000000..245ef32da5 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/common/analytics/api/ParamsInterceptorApi.kt @@ -0,0 +1,17 @@ +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) +} + +interface ParamsInterceptorHolder { + fun addParamsInterceptor(interceptor: ParamsInterceptor) + fun removeParamsInterceptor(interceptor: ParamsInterceptor): ParamsInterceptor? +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/AnalyticsParam.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/AnalyticsParam.kt index 71e6eb6c09..0d76d1dd08 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/events/AnalyticsParam.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/events/AnalyticsParam.kt @@ -55,8 +55,10 @@ sealed class AnalyticsParam { } companion object Key { + const val BatchId = "Batch" + + // old keys const val Blockchain = "blockchain" - const val BatchId = "batch_id" const val Firmware = "firmware" } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/Basic.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/Basic.kt index f1e3927530..229093235d 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/events/Basic.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/events/Basic.kt @@ -17,7 +17,7 @@ sealed class Basic( params = mapOf( "State" to state.value, "Currency" to currency.value, - "Batch" to batch, + AnalyticsParam.BatchId to batch, ), ) diff --git a/app/src/main/java/com/tangem/tap/common/analytics/filters/BasicSignInFilter.kt b/app/src/main/java/com/tangem/tap/common/analytics/filters/BasicSignInFilter.kt index c885cf7ae6..372f2787a3 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/filters/BasicSignInFilter.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/filters/BasicSignInFilter.kt @@ -23,5 +23,5 @@ class BasicSignInFilter : AnalyticsEventFilter { return canBeSent } - override fun canBeConsumedBy(handler: AnalyticsEventHandler, event: AnalyticsEvent): Boolean = true + override fun canBeConsumedByHandler(handler: AnalyticsEventHandler, event: AnalyticsEvent): Boolean = true } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/analytics/filters/BasicTopUpFilter.kt b/app/src/main/java/com/tangem/tap/common/analytics/filters/BasicTopUpFilter.kt index 5b0638231e..fea71037d9 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/filters/BasicTopUpFilter.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/filters/BasicTopUpFilter.kt @@ -39,7 +39,7 @@ class BasicTopUpFilter( } } - override fun canBeConsumedBy(handler: AnalyticsEventHandler, event: AnalyticsEvent): Boolean = true + override fun canBeConsumedByHandler(handler: AnalyticsEventHandler, event: AnalyticsEvent): Boolean = true data class Data( val walletId: String, diff --git a/app/src/main/java/com/tangem/tap/common/analytics/filters/ShopPurchasedEventFilter.kt b/app/src/main/java/com/tangem/tap/common/analytics/filters/ShopPurchasedEventFilter.kt index 5267782ddc..945dbefab4 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/filters/ShopPurchasedEventFilter.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/filters/ShopPurchasedEventFilter.kt @@ -16,7 +16,7 @@ class ShopPurchasedEventFilter : AnalyticsEventFilter { override fun canBeSent(event: AnalyticsEvent): Boolean = true - override fun canBeConsumedBy(handler: AnalyticsEventHandler, event: AnalyticsEvent): Boolean { + override fun canBeConsumedByHandler(handler: AnalyticsEventHandler, event: AnalyticsEvent): Boolean { return when (handler) { is AppsFlyerAnalyticsHandler, is FirebaseAnalyticsHandler -> true else -> false diff --git a/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/BatchIdParamsInterceptor.kt b/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/BatchIdParamsInterceptor.kt new file mode 100644 index 0000000000..ffe48cf198 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/BatchIdParamsInterceptor.kt @@ -0,0 +1,21 @@ +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.tap.common.analytics.events.AnalyticsParam + +/** +[REDACTED_AUTHOR] + */ +class BatchIdParamsInterceptor( + val batchId: String, +) : ParamsInterceptor { + + override fun id(): String = this::class.java.simpleName + + override fun canBeAppliedTo(event: AnalyticsEvent): Boolean = true + + override fun intercept(params: MutableMap) { + params[AnalyticsParam.BatchId] = batchId + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt b/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt index 0148a2cbf7..16d6ee9efd 100644 --- a/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt @@ -13,8 +13,8 @@ import com.tangem.tap.common.analytics.Analytics import com.tangem.tap.common.analytics.AnalyticsEventAnOld import com.tangem.tap.common.analytics.AnalyticsParamAnOld import com.tangem.tap.common.analytics.GetCardSourceParamsAnOld -import com.tangem.tap.common.analytics.events.AnalyticsParam import com.tangem.tap.common.analytics.events.IntroductionProcess +import com.tangem.tap.common.analytics.paramsInterceptor.BatchIdParamsInterceptor import com.tangem.tap.common.entities.IndeterminateProgressButton import com.tangem.tap.common.extensions.dispatchDialogShow import com.tangem.tap.common.extensions.dispatchOpenUrl @@ -165,7 +165,7 @@ private fun onScanSuccess(scanResponse: ScanResponse) { val tapWalletManager = globalState.tapWalletManager tapWalletManager.updateConfigManager(scanResponse) - Analytics.attachToAllEvents(AnalyticsParam.BatchId, scanResponse.card.batchId) + Analytics.addParamsInterceptor(BatchIdParamsInterceptor(scanResponse.card.batchId)) store.dispatch(TwinCardsAction.IfTwinsPrepareState(scanResponse))