diff --git a/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt b/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt index 47d5f23ab4..4c7aa189cb 100644 --- a/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt +++ b/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt @@ -1,7 +1,6 @@ package com.tangem.tap import androidx.hilt.work.HiltWorkerFactory -import com.tangem.TangemSdkLogger import com.tangem.core.abtests.manager.ABTestsManager import com.tangem.core.analytics.filter.OneTimeEventFilter import com.tangem.core.analytics.paramsinterceptor.SendTransactionSignerInfoInterceptor @@ -9,13 +8,12 @@ import com.tangem.core.configtoggle.blockchain.ExcludedBlockchainsManager import com.tangem.core.configtoggle.feature.FeatureTogglesManager import com.tangem.datasource.api.common.config.managers.ApiConfigsManager import com.tangem.datasource.local.config.environment.EnvironmentConfig -import com.tangem.datasource.local.logs.AppLogsStore import com.tangem.domain.apptheme.GetAppThemeModeUseCase import com.tangem.domain.walletconnect.usecase.initialize.WcInitializeUseCase import com.tangem.domain.wallets.repository.WalletsRepository import com.tangem.tap.common.analytics.handlers.BlockchainExceptionHandler import com.tangem.tap.common.analytics.handlers.appsflyer.AppsFlyerClient -import com.tangem.tap.common.log.TangemAppLoggerInitializer +import com.tangem.tap.common.log.TangemLoggingInitializer import dagger.hilt.EntryPoint import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent @@ -36,11 +34,7 @@ interface ApplicationEntryPoint { fun getOneTimeEventFilter(): OneTimeEventFilter - fun getTangemSdkLogger(): TangemSdkLogger - - fun getTangemAppLogger(): TangemAppLoggerInitializer - - fun getAppLogsStore(): AppLogsStore + fun getTangemLoggingInitializer(): TangemLoggingInitializer fun getBlockchainExceptionHandler(): BlockchainExceptionHandler diff --git a/app/src/main/java/com/tangem/tap/TangemApplication.kt b/app/src/main/java/com/tangem/tap/TangemApplication.kt index d66468de37..3684c3af20 100644 --- a/app/src/main/java/com/tangem/tap/TangemApplication.kt +++ b/app/src/main/java/com/tangem/tap/TangemApplication.kt @@ -8,11 +8,7 @@ import androidx.hilt.work.HiltWorkerFactory import androidx.work.Configuration import coil.ImageLoader import coil.ImageLoaderFactory -import com.chuckerteam.chucker.api.ChuckerInterceptor -import com.tangem.Log -import com.tangem.TangemSdkLogger import com.tangem.blockchain.common.ExceptionHandler -import com.tangem.blockchain.network.BlockchainSdkRetrofitBuilder import com.tangem.core.abtests.manager.ABTestsManager import com.tangem.core.analytics.Analytics import com.tangem.core.analytics.filter.AppsFlyerEventFilter @@ -21,15 +17,10 @@ import com.tangem.core.configtoggle.blockchain.ExcludedBlockchainsManager import com.tangem.core.configtoggle.feature.FeatureTogglesManager import com.tangem.datasource.api.common.MoshiConverter import com.tangem.datasource.api.common.config.managers.ApiConfigsManager -import com.tangem.datasource.api.common.createNetworkLoggingInterceptor import com.tangem.datasource.local.config.environment.EnvironmentConfig -import com.tangem.datasource.local.logs.AppLogsStore -import com.tangem.datasource.utils.NetworkLogsSaveInterceptor -import com.tangem.datasource.utils.WireMockRedirectInterceptor import com.tangem.domain.apptheme.GetAppThemeModeUseCase import com.tangem.domain.common.LogConfig import com.tangem.domain.wallets.repository.WalletsRepository -import com.tangem.operations.attestation.api.TangemApiServiceSettings import com.tangem.tap.common.analytics.AnalyticsFactory import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder import com.tangem.tap.common.analytics.handlers.BlockchainExceptionHandler @@ -39,7 +30,7 @@ import com.tangem.tap.common.analytics.handlers.appsflyer.AppsFlyerClient import com.tangem.tap.common.analytics.handlers.customerio.CustomerIoAnalyticsHandler import com.tangem.tap.common.analytics.handlers.firebase.FirebaseAnalyticsHandler import com.tangem.tap.common.images.createCoilImageLoader -import com.tangem.tap.common.log.TangemAppLoggerInitializer +import com.tangem.tap.common.log.TangemLoggingInitializer import com.tangem.utils.logging.TangemLogger import com.tangem.wallet.BuildConfig import dagger.hilt.EntryPoints @@ -72,14 +63,8 @@ open class TangemApplication : Application(), ImageLoaderFactory, Configuration. private val oneTimeEventFilter: OneTimeEventFilter get() = entryPoint.getOneTimeEventFilter() - private val tangemSdkLogger: TangemSdkLogger - get() = entryPoint.getTangemSdkLogger() - - private val tangemAppLoggerInitializer: TangemAppLoggerInitializer - get() = entryPoint.getTangemAppLogger() - - private val appLogsStore: AppLogsStore - get() = entryPoint.getAppLogsStore() + private val tangemLoggingInitializer: TangemLoggingInitializer + get() = entryPoint.getTangemLoggingInitializer() private val blockchainExceptionHandler: BlockchainExceptionHandler get() = entryPoint.getBlockchainExceptionHandler() @@ -142,7 +127,7 @@ open class TangemApplication : Application(), ImageLoaderFactory, Configuration. * Initialize components that need to be initialized before [super.onCreate] is called */ fun preInit() { - tangemAppLoggerInitializer.initialize() + tangemLoggingInitializer.initAppLogging() registerActivityLifecycleCallbacks(foregroundActivityObserver.callbacks) } @@ -157,7 +142,7 @@ open class TangemApplication : Application(), ImageLoaderFactory, Configuration. TangemLogger.i(excludedBlockchainsManager.toString()) } - initWithConfigDependency(environmentConfig = environmentConfig) + initAnalytics(application = this, environmentConfig = environmentConfig) abTestsManager.init() @@ -169,26 +154,7 @@ open class TangemApplication : Application(), ImageLoaderFactory, Configuration. ExceptionHandler.append(blockchainExceptionHandler) - if (LogConfig.network.isBlockchainSdkNetworkLogEnabled) { - BlockchainSdkRetrofitBuilder.interceptors = buildList { - if (BuildConfig.MOCK_DATA_SOURCE) { - add(WireMockRedirectInterceptor()) - } - add(createNetworkLoggingInterceptor()) - add(ChuckerInterceptor(this@TangemApplication)) - } - - TangemApiServiceSettings.addInterceptors( - *buildList { - if (BuildConfig.MOCK_DATA_SOURCE) { - add(WireMockRedirectInterceptor()) - } - add(createNetworkLoggingInterceptor()) - add(ChuckerInterceptor(this@TangemApplication)) - add(NetworkLogsSaveInterceptor(appLogsStore)) - }.toTypedArray(), - ) - } + tangemLoggingInitializer.initSdkLogging(this) wcInitializeUseCase.init( projectId = environmentConfig.walletConnectProjectId, @@ -206,11 +172,6 @@ open class TangemApplication : Application(), ImageLoaderFactory, Configuration. System.loadLibrary("TrustWalletCore") } - private fun initWithConfigDependency(environmentConfig: EnvironmentConfig) { - initAnalytics(this, environmentConfig) - Log.addLogger(logger = tangemSdkLogger) - } - private fun initAnalytics(application: Application, environmentConfig: EnvironmentConfig) { val factory = AnalyticsFactory() factory.addHandlerBuilder(AmplitudeAnalyticsHandler.Builder()) diff --git a/app/src/main/java/com/tangem/tap/common/log/TangemAppLoggerInitializer.kt b/app/src/main/java/com/tangem/tap/common/log/TangemAppLoggerInitializer.kt deleted file mode 100644 index b71a74125c..0000000000 --- a/app/src/main/java/com/tangem/tap/common/log/TangemAppLoggerInitializer.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.tangem.tap.common.log - -import com.tangem.datasource.local.logs.AppLogsStore -import com.tangem.utils.logging.TangemLogger -import com.tangem.wallet.BuildConfig - -/** - * Tangem app logger - * - * @property appLogsStore app logs store - * -[REDACTED_AUTHOR] - */ -class TangemAppLoggerInitializer( - private val appLogsStore: AppLogsStore, -) { - - fun initialize() { - TangemLogger.setLogWriters( - buildList { - if (BuildConfig.LOG_ENABLED) { - add(LogcatLogWriter()) - } - add(FileLogWriter(appLogsStore)) - }, - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/data/TangemBlockchainSDKLogger.kt b/app/src/main/java/com/tangem/tap/common/log/TangemBlockchainSDKLogger.kt similarity index 94% rename from app/src/main/java/com/tangem/tap/data/TangemBlockchainSDKLogger.kt rename to app/src/main/java/com/tangem/tap/common/log/TangemBlockchainSDKLogger.kt index fdfcf8789e..c97dc1f59a 100644 --- a/app/src/main/java/com/tangem/tap/data/TangemBlockchainSDKLogger.kt +++ b/app/src/main/java/com/tangem/tap/common/log/TangemBlockchainSDKLogger.kt @@ -1,4 +1,4 @@ -package com.tangem.tap.data +package com.tangem.tap.common.log import com.tangem.blockchain.common.logging.BlockchainSDKLogger import com.tangem.datasource.local.logs.AppLogsStore diff --git a/app/src/main/java/com/tangem/tap/common/log/TangemCardSDKLogger.kt b/app/src/main/java/com/tangem/tap/common/log/TangemCardSDKLogger.kt index f938ef17cc..38de07528e 100644 --- a/app/src/main/java/com/tangem/tap/common/log/TangemCardSDKLogger.kt +++ b/app/src/main/java/com/tangem/tap/common/log/TangemCardSDKLogger.kt @@ -6,27 +6,40 @@ import com.tangem.TangemSdkLogger import com.tangem.datasource.local.logs.AppLogsStore /** - * CardSDK logger implementation + * CardSDK logger implementation. * - * @property levels logging levels - * @property messageFormatter message formatter - * @property appLogsStore app logs store + * @property appLogsStore app logs store * [REDACTED_AUTHOR] */ -@Suppress("UnusedPrivateMember") internal class TangemCardSDKLogger( - private val levels: List, - private val messageFormatter: LogFormat, private val appLogsStore: AppLogsStore, ) : TangemSdkLogger { + private val messageFormatter: LogFormat = LogFormat.StairsFormatter() + override fun log(message: () -> String, level: Log.Level) { - if (!levels.contains(level)) return + if (!LEVELS.contains(level)) return appLogsStore.saveLogMessage( tag = "CardSDK_${level.name}", message = messageFormatter.format(message = message, level = level), ) } + + private companion object { + val LEVELS = listOf( + Log.Level.ApduCommand, + Log.Level.Apdu, + Log.Level.Tlv, + Log.Level.Nfc, + Log.Level.Command, + Log.Level.Session, + Log.Level.View, + Log.Level.Network, + Log.Level.Error, + Log.Level.Biometric, + Log.Level.Info, + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/log/TangemLoggingInitializer.kt b/app/src/main/java/com/tangem/tap/common/log/TangemLoggingInitializer.kt new file mode 100644 index 0000000000..6e9e000506 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/common/log/TangemLoggingInitializer.kt @@ -0,0 +1,80 @@ +package com.tangem.tap.common.log + +import android.app.Application +import com.chuckerteam.chucker.api.ChuckerInterceptor +import com.tangem.Log +import com.tangem.TangemSdkLogger +import com.tangem.blockchain.network.BlockchainSdkRetrofitBuilder +import com.tangem.datasource.api.common.createNetworkLoggingInterceptor +import com.tangem.datasource.local.logs.AppLogsStore +import com.tangem.datasource.utils.NetworkLogsSaveInterceptor +import com.tangem.datasource.utils.WireMockRedirectInterceptor +import com.tangem.domain.common.LogConfig +import com.tangem.operations.attestation.api.TangemApiServiceSettings +import com.tangem.utils.logging.TangemLogger +import com.tangem.wallet.BuildConfig + +/** + * Owns all app-startup wiring of the logging subsystem in a single place: + * - [initAppLogging] — registers [TangemLogger] writers (Logcat + file). + * - [initSdkLogging] — registers the Card SDK logger with [Log] and installs OkHttp + * interceptors for the Blockchain SDK and the Tangem API. + * + * @property appLogsStore app logs store used by file-based writer and the network logs save + * interceptor + * @property tangemSdkLogger Card SDK logger registered with [Log.addLogger] + * +[REDACTED_AUTHOR] + */ +class TangemLoggingInitializer( + private val appLogsStore: AppLogsStore, + private val tangemSdkLogger: TangemSdkLogger, +) { + + fun initAppLogging() { + TangemLogger.setLogWriters( + buildList { + if (BuildConfig.LOG_ENABLED) { + add(LogcatLogWriter()) + } + add(FileLogWriter(appLogsStore)) + }, + ) + } + + /** + * Configure logging for the underlying SDKs: + * - register [tangemSdkLogger] with the Card SDK static [Log] facade, + * - install OkHttp interceptors for the Blockchain SDK and Tangem API. + * + * Must be called from `TangemApplication.init()` AFTER `entryPoint.getWalletsRepository()` + * has triggered Hilt singletons construction — in particular `DefaultCardSdkProvider`, + * whose init block registers `AddHeadersInterceptor` in [TangemApiServiceSettings]. + * Calling this method earlier would invert the OkHttp interceptor chain order and + * cause logging interceptors to see requests *without* auth headers. + */ + fun initSdkLogging(application: Application) { + Log.addLogger(logger = tangemSdkLogger) + + if (!LogConfig.network.isBlockchainSdkNetworkLogEnabled) return + + BlockchainSdkRetrofitBuilder.interceptors = buildList { + if (BuildConfig.MOCK_DATA_SOURCE) { + add(WireMockRedirectInterceptor()) + } + add(createNetworkLoggingInterceptor()) + add(ChuckerInterceptor(application)) + } + + TangemApiServiceSettings.addInterceptors( + *buildList { + if (BuildConfig.MOCK_DATA_SOURCE) { + add(WireMockRedirectInterceptor()) + } + add(createNetworkLoggingInterceptor()) + add(ChuckerInterceptor(application)) + add(NetworkLogsSaveInterceptor(appLogsStore)) + }.toTypedArray(), + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/di/data/TangemLoggingModule.kt b/app/src/main/java/com/tangem/tap/di/data/TangemLoggingModule.kt index 400f58d8b2..f6dc626675 100644 --- a/app/src/main/java/com/tangem/tap/di/data/TangemLoggingModule.kt +++ b/app/src/main/java/com/tangem/tap/di/data/TangemLoggingModule.kt @@ -1,13 +1,10 @@ package com.tangem.tap.di.data -import com.tangem.Log -import com.tangem.LogFormat -import com.tangem.TangemSdkLogger import com.tangem.blockchain.common.logging.BlockchainSDKLogger import com.tangem.datasource.local.logs.AppLogsStore -import com.tangem.tap.common.log.TangemAppLoggerInitializer +import com.tangem.tap.common.log.TangemBlockchainSDKLogger import com.tangem.tap.common.log.TangemCardSDKLogger -import com.tangem.tap.data.TangemBlockchainSDKLogger +import com.tangem.tap.common.log.TangemLoggingInitializer import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -20,31 +17,10 @@ internal object TangemLoggingModule { @Provides @Singleton - fun provideAppLoggerInitializer(appLogsStore: AppLogsStore): TangemAppLoggerInitializer { - return TangemAppLoggerInitializer(appLogsStore) - } - - @Provides - @Singleton - fun provideCardSDKLogger(appLogsStore: AppLogsStore): TangemSdkLogger { - val logLevels = listOf( - Log.Level.ApduCommand, - Log.Level.Apdu, - Log.Level.Tlv, - Log.Level.Nfc, - Log.Level.Command, - Log.Level.Session, - Log.Level.View, - Log.Level.Network, - Log.Level.Error, - Log.Level.Biometric, - Log.Level.Info, - ) - - return TangemCardSDKLogger( - levels = logLevels, - messageFormatter = LogFormat.StairsFormatter(), + fun provideLoggingInitializer(appLogsStore: AppLogsStore): TangemLoggingInitializer { + return TangemLoggingInitializer( appLogsStore = appLogsStore, + tangemSdkLogger = TangemCardSDKLogger(appLogsStore), ) }