Updated on 2026-08-14

This commit is contained in:
Tangem 2026-03-20 21:54:46 +04:00
parent 8b75e37e30
commit a9bca131c3
386 changed files with 1369 additions and 1347 deletions

View file

@ -1,12 +1,12 @@
package com.tangem.datasource.api.common.response
import com.tangem.core.analytics.api.AnalyticsErrorHandler
import com.tangem.utils.logging.TangemLogger
import okhttp3.Request
import okio.Timeout
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import timber.log.Timber
internal class ApiResponseCallDelegate<T : Any>(
private val wrappedCall: Call<T>,
@ -41,10 +41,10 @@ internal class ApiResponseCallDelegate<T : Any>(
val error = try {
t.toApiError()
} catch (e: ApiResponseError) {
Timber.e(e, "error map toApiError")
TangemLogger.e("error map toApiError", e)
e
} catch (e: Exception) {
Timber.e(e, "onFailure UnknownException")
TangemLogger.e("onFailure UnknownException", e)
ApiResponseError.UnknownException(e)
}

View file

@ -2,9 +2,9 @@ package com.tangem.datasource.api.common.response
import com.tangem.core.analytics.api.AnalyticsErrorHandler
import com.tangem.datasource.api.common.response.analytics.ApiErrorEvent
import com.tangem.utils.logging.TangemLogger
import kotlinx.coroutines.TimeoutCancellationException
import retrofit2.Response
import timber.log.Timber
import java.net.ConnectException
import java.net.SocketTimeoutException
import java.net.UnknownHostException
@ -31,7 +31,7 @@ internal fun <T : Any> Response<T>.toSafeApiResponse(analyticsErrorHandler: Anal
ApiResponseError.HttpException(code, message(), errorBody)
}
} catch (e: Exception) {
Timber.e(e, "UnknownException occured")
TangemLogger.e("UnknownException occured", e)
ApiResponseError.UnknownException(e)
}

View file

@ -9,8 +9,8 @@ import com.tangem.datasource.asset.reader.AssetReader
import com.tangem.datasource.di.NetworkMoshi
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.coroutines.runCatching
import com.tangem.utils.logging.TangemLogger
import kotlinx.coroutines.withContext
import timber.log.Timber
import javax.inject.Inject
import javax.inject.Singleton
@ -49,7 +49,10 @@ class AssetLoader @Inject constructor(
json = json,
)
Timber.e(IllegalStateException("Parsed config [$fileName] is null"))
TangemLogger.e(
"Error",
IllegalStateException("Parsed config [$fileName] is null"),
)
}
parsedConfig
@ -61,51 +64,65 @@ class AssetLoader @Inject constructor(
json = json,
)
Timber.e(throwable, "Failed to load config [$fileName] from assets")
TangemLogger.e("Failed to load config [$fileName] from assets", throwable)
null
},
)
}
/** Load list [V] values of asset file [fileName] */
suspend inline fun <reified V> loadList(fileName: String): List<V> = runCatching(dispatchers.io) {
val json = assetReader.read(fullFileName = "$fileName.json")
suspend inline fun <reified V> loadList(fileName: String): List<V> {
val result = runCatching(dispatchers.io) {
val json = assetReader.read(fullFileName = "$fileName.json")
val type = Types.newParameterizedType(List::class.java, V::class.java)
val adapter = moshi.adapter<List<V>>(type)
val type = Types.newParameterizedType(List::class.java, V::class.java)
val adapter = moshi.adapter<List<V>>(type)
adapter.fromJson(json)
}
.fold(
adapter.fromJson(json)
}
return result.fold(
onSuccess = { parsedConfig ->
if (parsedConfig == null) Timber.e(IllegalStateException("Parsed config [$fileName] is null"))
if (parsedConfig == null) {
TangemLogger.e(
"Error",
IllegalStateException("Parsed config [$fileName] is null"),
)
}
parsedConfig.orEmpty()
},
onFailure = { throwable ->
Timber.e(throwable, "Failed to load config [$fileName] from assets")
TangemLogger.e("Failed to load config [$fileName] from assets", throwable)
emptyList()
},
)
}
/** Load map [String] keys and [V] values of asset file [fileName] */
suspend inline fun <reified V> loadMap(fileName: String): Map<String, V> = runCatching(dispatchers.io) {
val json = assetReader.read(fullFileName = "$fileName.json")
suspend inline fun <reified V> loadMap(fileName: String): Map<String, V> {
val result = runCatching(dispatchers.io) {
val json = assetReader.read(fullFileName = "$fileName.json")
val type = Types.newParameterizedType(Map::class.java, String::class.java, V::class.java)
val adapter = moshi.adapter<Map<String, V>>(type)
val type = Types.newParameterizedType(Map::class.java, String::class.java, V::class.java)
val adapter = moshi.adapter<Map<String, V>>(type)
adapter.fromJson(json)
}
.fold(
adapter.fromJson(json)
}
return result.fold(
onSuccess = { parsedConfig ->
if (parsedConfig == null) Timber.e(IllegalStateException("Parsed config [$fileName] is null"))
if (parsedConfig == null) {
TangemLogger.e(
"Error",
IllegalStateException("Parsed config [$fileName] is null"),
)
}
parsedConfig.orEmpty()
},
onFailure = { throwable ->
Timber.e(throwable, "Failed to load config [$fileName] from assets")
TangemLogger.e("Failed to load config [$fileName] from assets", throwable)
emptyMap()
},
)
}
fun sendException(fileName: String, isParsingSuccess: Boolean, json: String?) {
analyticsExceptionHandler.sendException(

View file

@ -1,10 +1,10 @@
package com.tangem.datasource.di
import com.tangem.utils.logging.TangemLogger
import okhttp3.Interceptor
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.Response
import okhttp3.ResponseBody.Companion.toResponseBody
import timber.log.Timber
class StatusCodeInterceptor : Interceptor {
@ -12,7 +12,7 @@ class StatusCodeInterceptor : Interceptor {
val originalResponse = chain.proceed(chain.request())
if (shouldInterceptResponse(originalResponse)) {
Timber.e("StatusCodeInterceptor INTERCEPTED%s", originalResponse.request.url.toString())
TangemLogger.e("StatusCodeInterceptor INTERCEPTED${originalResponse.request.url}")
val body = getBody().toResponseBody("application/json".toMediaTypeOrNull())
val code = getCode()

View file

@ -8,7 +8,7 @@ import com.tangem.datasource.local.preferences.utils.getObjectSyncOrNull
import com.tangem.datasource.local.preferences.utils.getSyncOrNull
import com.tangem.datasource.local.preferences.utils.storeObject
import com.tangem.domain.wallets.models.AppsFlyerConversionData
import timber.log.Timber
import com.tangem.utils.logging.TangemLogger
internal class DefaultAppsFlyerStore(
private val appPreferencesStore: AppPreferencesStore,
@ -18,14 +18,14 @@ internal class DefaultAppsFlyerStore(
val dto = appPreferencesStore.getObjectSyncOrNull<ConversionDataDTO>(CONVERSION_DATA_KEY) ?: return null
return ConversionDataConverter.convertBack(value = dto).also {
Timber.i("Getting conversion data from store: $it")
TangemLogger.i("Getting conversion data from store: $it")
}
}
override suspend fun getUID(): String? = appPreferencesStore.getSyncOrNull(UID_KEY)
override suspend fun store(value: AppsFlyerConversionData) {
Timber.i("Storing conversion data to store: $value")
TangemLogger.i("Storing conversion data to store: $value")
val dto = ConversionDataConverter.convert(value)
@ -33,24 +33,24 @@ internal class DefaultAppsFlyerStore(
}
override suspend fun storeIfAbsent(value: AppsFlyerConversionData) {
Timber.i("Storing conversion data to store if absent: $value")
TangemLogger.i("Storing conversion data to store if absent: $value")
appPreferencesStore.editData { preferences ->
val saved = preferences[CONVERSION_DATA_KEY]
if (saved == null) {
Timber.i("Conversion data is absent, storing $value")
TangemLogger.i("Conversion data is absent, storing $value")
preferences.setObject(CONVERSION_DATA_KEY, ConversionDataConverter.convert(value))
}
}
}
override suspend fun storeUIDIfAbsent(value: String) {
Timber.i("Storing UID to store if absent: $value")
TangemLogger.i("Storing UID to store if absent: $value")
appPreferencesStore.editData { preferences ->
val saved = preferences[UID_KEY]
if (saved == null) {
Timber.i("UID is absent, storing $value")
TangemLogger.i("UID is absent, storing $value")
preferences[UID_KEY] = value
}
}

View file

@ -3,13 +3,14 @@ package com.tangem.datasource.local.logs
import android.content.Context
import com.tangem.utils.coroutines.AppCoroutineScope
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.logging.TangemLogger
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.*
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import org.joda.time.DateTime
import org.joda.time.format.DateTimeFormatterBuilder
import timber.log.Timber
import java.io.*
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
@ -121,7 +122,7 @@ class AppLogsStore @Inject constructor(
private fun createFileIfNotExist() {
if (!logFile.exists()) {
runCatching { logFile.createNewFile() }
.onFailure(Timber::e)
.onFailure { TangemLogger.e("Error", it) }
}
}
@ -129,7 +130,7 @@ class AppLogsStore @Inject constructor(
scope.launch {
mutex.withLock {
runCatching { callback() }
.onFailure(Timber::e)
.onFailure { TangemLogger.e("Error", it) }
}
}
}

View file

@ -17,7 +17,7 @@ import com.tangem.datasource.local.preferences.PreferencesKeys.SHOULD_SHOW_RING_
import com.tangem.datasource.local.preferences.utils.CleanupKeyMigration
import com.tangem.datasource.local.preferences.utils.SharedPreferencesKeyMigration
import com.tangem.utils.coroutines.AppCoroutineScope
import timber.log.Timber
import com.tangem.utils.logging.TangemLogger
/**
* Application preferences data store 'DataStore<Preferences>'.
@ -49,7 +49,7 @@ internal object PreferencesDataStore {
private fun createCorruptionHandler(): ReplaceFileCorruptionHandler<Preferences> {
return ReplaceFileCorruptionHandler(
produceNewData = { corruptionException ->
Timber.w(corruptionException)
TangemLogger.w("Error", corruptionException)
emptyPreferences()
},
)

View file

@ -1,8 +1,8 @@
package com.tangem.datasource.utils
import com.tangem.utils.logging.TangemLogger
import okhttp3.Interceptor
import okhttp3.Response
import timber.log.Timber
/**
* OkHttp interceptor that redirects requests from wiremock.tests-d.com to a local WireMock instance.
@ -17,7 +17,7 @@ class WireMockRedirectInterceptor : Interceptor {
if (url.contains(WIREMOCK_REMOTE_URL)) {
val newUrl = url.replace(WIREMOCK_REMOTE_URL, override.trimEnd('/'))
Timber.d("WireMockRedirect: $url -> $newUrl")
TangemLogger.d("WireMockRedirect: $url -> $newUrl")
val newRequest = request.newBuilder()
.url(newUrl)
.build()

View file

@ -4,13 +4,13 @@ import com.google.common.truth.Truth
import com.tangem.datasource.api.common.AuthProvider
import com.tangem.datasource.local.config.environment.EnvironmentConfig
import com.tangem.utils.ProviderSuspend
import com.tangem.utils.logging.TangemLogger
import io.mockk.clearMocks
import io.mockk.every
import io.mockk.mockk
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
import timber.log.Timber
/**
[REDACTED_AUTHOR]
@ -38,7 +38,7 @@ class ApiConfigTest {
// Actual
val actual = allBaseUrls.all { it.endsWith("/") }
Timber.e(allBaseUrls.joinToString(separator = "\n"))
TangemLogger.e(allBaseUrls.joinToString(separator = "\n"))
// Assert
Truth.assertThat(actual).isTrue()