diff --git a/build.gradle.kts b/build.gradle.kts index 8d1583187..ec448c1d4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,9 +10,11 @@ buildscript { classpath("org.jetbrains.kotlin:kotlin-serialization:${Versions.kotlin}") classpath("com.squareup.sqldelight:gradle-plugin:${Versions.sqlDelight}") - // Plugins for the legacy android app - // Argument classes generation plugin for the androidx navigation component - classpath("androidx.navigation:navigation-safe-args-gradle-plugin:${Versions.AndroidLegacy.safeArgs}") + if (System.getProperty("includeAndroid")?.toBoolean() == true) { + // Plugins for the legacy android app + // Argument classes generation plugin for the androidx navigation component + classpath("androidx.navigation:navigation-safe-args-gradle-plugin:${Versions.AndroidLegacy.safeArgs}") + } // Firebase cloud messaging plugin classpath("com.google.gms:google-services:${Versions.fcmPlugin}") } diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/AppView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/AppView.kt index d6b257fd6..1cf8fe488 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/AppView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/AppView.kt @@ -95,7 +95,6 @@ import fr.acinq.phoenix.data.WalletPaymentId import fr.acinq.phoenix.data.walletPaymentId import fr.acinq.phoenix.legacy.utils.LegacyAppStatus import fr.acinq.phoenix.legacy.utils.LegacyPrefsDatastore -import fr.acinq.phoenix.utils.extensions.id import io.ktor.http.decodeURLPart import io.ktor.http.encodeURLParameter import kotlinx.coroutines.flow.filterNotNull @@ -120,7 +119,7 @@ fun AppView( navController: NavHostController, ) { val log = logger("Navigation") - log.debug { "init app view composition" } + log.debug("init app view composition") val context = LocalContext.current val isAmountInFiat = UserPrefs.getIsAmountInFiat(context).collectAsState(false) @@ -190,10 +189,10 @@ fun AppView( onBusinessStarted = { val next = nextScreenLink?.takeUnless { it.isBlank() }?.let { Uri.parse(it) } if (next == null || !navController.graph.hasDeepLink(next)) { - log.debug { "redirecting from startup to home" } + log.debug("redirecting from startup to home") popToHome(navController) } else { - log.debug { "redirecting from startup to $next" } + log.debug("redirecting from startup to $next") navController.navigate(next, navOptions = navOptions { popUpTo(navController.graph.id) { inclusive = true } }) @@ -291,7 +290,7 @@ fun AppView( val paymentId = if (id != null && direction != null) WalletPaymentId.create(direction, id) else null if (paymentId != null) { RequireStarted(walletState, nextUri = "phoenix:payments/${direction}/${id}") { - log.debug { "navigating to payment-details id=$id" } + log.debug("navigating to payment-details id=$id") PaymentDetailsView( paymentId = paymentId, onBackClick = { @@ -450,7 +449,7 @@ fun AppView( val isDataMigrationExpected by LegacyPrefsDatastore.getDataMigrationExpected(context).collectAsState(initial = null) val lastCompletedPayment by business.paymentsManager.lastCompletedPayment.collectAsState() lastCompletedPayment?.let { - log.debug { "completed payment=${lastCompletedPayment?.id()} with data-migration=$isDataMigrationExpected" } +// log.debug { "completed payment=${lastCompletedPayment?.id()} with data-migration=$isDataMigrationExpected" } LaunchedEffect(key1 = it.walletPaymentId()) { if (isDataMigrationExpected == false) { navigateToPaymentDetails(navController, id = it.walletPaymentId(), isFromEvent = true) @@ -545,7 +544,6 @@ private fun RequireStarted( nextUri: String? = null, children: @Composable () -> Unit ) { - val log = logger("Navigation") if (serviceState == null) { // do nothing } else if (serviceState !is NodeServiceState.Running) { diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/Navigation.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/Navigation.kt index 2094776b5..521d05bd4 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/Navigation.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/Navigation.kt @@ -18,8 +18,7 @@ package fr.acinq.phoenix.android import androidx.navigation.NavController import androidx.navigation.NavOptionsBuilder -import org.kodein.log.LoggerFactory -import org.kodein.log.newLogger +import org.slf4j.LoggerFactory sealed class Screen(val route: String) { @@ -68,17 +67,17 @@ sealed class Screen(val route: String) { } fun NavController.navigate(screen: Screen, arg: List = emptyList(), builder: NavOptionsBuilder.() -> Unit = {}) { - val log = newLogger(LoggerFactory.default) + val log = LoggerFactory.getLogger("NavController") val path = arg.joinToString{ "/$it" } val route = "${screen.route}$path" - log.debug { "navigating from ${currentDestination?.route} to $route" } + log.debug("navigating from ${currentDestination?.route} to $route") try { if (route == currentDestination?.route) { - log.warning { "cannot navigate to same route" } + log.warn("cannot navigate to same route") } else { navigate(route, builder) } } catch (e: Exception) { - log.error(e) { "failed to navigate to $route" } + log.error("failed to navigate to $route: " , e) } } diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/components/AmountInput.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/components/AmountInput.kt index 28de3d788..e8d1eaaa2 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/components/AmountInput.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/components/AmountInput.kt @@ -81,7 +81,6 @@ import fr.acinq.phoenix.android.utils.Converter.toMilliSatoshi import fr.acinq.phoenix.android.utils.Converter.toPlainString import fr.acinq.phoenix.android.utils.Converter.toPrettyString import fr.acinq.phoenix.android.utils.Converter.toUnit -import fr.acinq.phoenix.android.utils.logger import fr.acinq.phoenix.android.utils.negativeColor import fr.acinq.phoenix.android.utils.outlinedTextFieldColors import fr.acinq.phoenix.data.BitcoinUnit @@ -390,7 +389,6 @@ fun AmountHeroInput( inputTextSize: TextUnit = 16.sp, enabled: Boolean = true, ) { - val log = logger("AmountHeroInput") val context = LocalContext.current val prefBitcoinUnit = LocalBitcoinUnit.current val prefFiat = LocalFiatCurrency.current diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/home/HomeView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/home/HomeView.kt index bc8dc24b5..9687d79cb 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/home/HomeView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/home/HomeView.kt @@ -57,7 +57,6 @@ import fr.acinq.phoenix.android.utils.annotatedStringResource import fr.acinq.phoenix.android.utils.datastore.HomeAmountDisplayMode import fr.acinq.phoenix.android.utils.datastore.UserPrefs import fr.acinq.phoenix.android.utils.findActivity -import fr.acinq.phoenix.android.utils.logger import fr.acinq.phoenix.data.WalletPaymentId import fr.acinq.phoenix.legacy.utils.LegacyPrefsDatastore import kotlinx.coroutines.flow.combine @@ -79,7 +78,6 @@ fun HomeView( onShowNotifications: () -> Unit, onRequestLiquidityClick: () -> Unit, ) { - val log = logger("HomeView") val context = LocalContext.current val torEnabledState = UserPrefs.getIsTorEnabled(context).collectAsState(initial = null) val connections by business.connectionsManager.connections.collectAsState() diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/init/CreateWalletView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/init/CreateWalletView.kt index f7e1df369..f5260bea4 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/init/CreateWalletView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/init/CreateWalletView.kt @@ -71,7 +71,7 @@ fun CreateWalletView( is Initialization.Model.Ready -> { val entropy = remember { Lightning.randomBytes(16) } LaunchedEffect(key1 = entropy) { - log.debug { "generating new wallet..." } + log.debug("generating new wallet...") postIntent(Initialization.Intent.GenerateWallet(entropy)) } } diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/init/RestoreWalletView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/init/RestoreWalletView.kt index 8ad0c0e27..07019b77a 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/init/RestoreWalletView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/init/RestoreWalletView.kt @@ -66,7 +66,6 @@ sealed class RestoreWalletViewState { fun RestoreWalletView( onSeedWritten: () -> Unit ) { - val log = logger("RestoreWalletView") val nc = navController val context = LocalContext.current val vm: InitViewModel = viewModel(factory = InitViewModel.Factory(controllerFactory, CF::initialization)) diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/LnurlAuthView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/LnurlAuthView.kt index 09a3ea7a9..9195f09b8 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/LnurlAuthView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/LnurlAuthView.kt @@ -32,7 +32,6 @@ import androidx.compose.ui.unit.sp import fr.acinq.phoenix.android.R import fr.acinq.phoenix.android.components.* import fr.acinq.phoenix.android.utils.datastore.UserPrefs -import fr.acinq.phoenix.android.utils.logger import fr.acinq.phoenix.controllers.payments.Scan import fr.acinq.phoenix.data.lnurl.LnurlAuth @@ -43,8 +42,6 @@ fun LnurlAuthView( onLoginClick: (Scan.Intent.LnurlAuthFlow) -> Unit, onAuthSchemeInfoClick: () -> Unit ) { - val log = logger("LnurlAuthView") - val context = LocalContext.current var showHowItWorks by remember { mutableStateOf(false) } val prefAuthScheme by UserPrefs.getLnurlAuthScheme(context).collectAsState(initial = null) diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/LnurlPayView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/LnurlPayView.kt index ab824d5ff..e32becfcf 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/LnurlPayView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/LnurlPayView.kt @@ -46,7 +46,6 @@ import fr.acinq.phoenix.android.preferredAmountUnit import fr.acinq.phoenix.android.utils.BitmapHelper import fr.acinq.phoenix.android.utils.Converter.toPrettyStringWithFallback import fr.acinq.phoenix.android.utils.annotatedStringResource -import fr.acinq.phoenix.android.utils.logger import fr.acinq.phoenix.android.utils.safeLet import fr.acinq.phoenix.controllers.payments.Scan import fr.acinq.phoenix.data.lnurl.LnurlError @@ -58,9 +57,6 @@ fun LnurlPayView( onBackClick: () -> Unit, onSendLnurlPayClick: (Scan.Intent.LnurlPayFlow) -> Unit ) { - val log = logger("LnurlPayView") - log.debug { "init lnurl-pay view with url=${model.paymentIntent}" } - val context = LocalContext.current val balance = business.balanceManager.balance.collectAsState(null).value val prefUnit = preferredAmountUnit diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/LnurlWithdrawView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/LnurlWithdrawView.kt index 274d73829..274938f9e 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/LnurlWithdrawView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/LnurlWithdrawView.kt @@ -36,7 +36,6 @@ import fr.acinq.phoenix.android.fiatRate import fr.acinq.phoenix.android.preferredAmountUnit import fr.acinq.phoenix.android.utils.Converter.toPrettyStringWithFallback import fr.acinq.phoenix.android.utils.annotatedStringResource -import fr.acinq.phoenix.android.utils.logger import fr.acinq.phoenix.controllers.payments.Scan import fr.acinq.phoenix.data.lnurl.LnurlError @@ -46,9 +45,6 @@ fun LnurlWithdrawView( onBackClick: () -> Unit, onWithdrawClick: (Scan.Intent.LnurlWithdrawFlow) -> Unit ) { - val log = logger("LnurlWithdrawView") - log.debug { "init lnurl-withdraw view with url=${model.lnurlWithdraw}" } - val context = LocalContext.current val prefUnit = preferredAmountUnit val rate = fiatRate diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/ScanDataView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/ScanDataView.kt index aa6261058..cd1847cf0 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/ScanDataView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/ScanDataView.kt @@ -84,7 +84,6 @@ fun ScanDataView( onBackClick: () -> Unit, onAuthSchemeInfoClick: () -> Unit, ) { - val log = logger("ScanDataView") var initialInput = remember { input } val peer by business.peerManager.peerState.collectAsState() val trampolineFees = peer?.walletParams?.trampolineFees?.firstOrNull() @@ -174,7 +173,6 @@ fun ReadDataView( onBackClick: () -> Unit, onScannedText: (String) -> Unit, ) { - val log = logger("ReadDataView") val context = LocalContext.current.applicationContext var showManualInputDialog by remember { mutableStateOf(false) } @@ -248,7 +246,6 @@ fun BoxScope.ScannerView( onScanViewBinding: (DecoratedBarcodeView) -> Unit, onScannedText: (String) -> Unit ) { - val log = logger("ScannerView") // scanner view using a legacy binding AndroidViewBinding( modifier = Modifier.fillMaxWidth(), @@ -264,7 +261,6 @@ fun BoxScope.ScannerView( override fun barcodeResult(result: BarcodeResult?) { result?.text?.trim()?.takeIf { it.isNotBlank() }?.let { scanView.pause() - log.debug { "scanned text=$it" } onScannedText(it) } } diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/SendLightningView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/SendLightningView.kt index bb22cc013..3e0c350c4 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/SendLightningView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/SendLightningView.kt @@ -37,7 +37,6 @@ import fr.acinq.phoenix.android.R import fr.acinq.phoenix.android.business import fr.acinq.phoenix.android.components.* import fr.acinq.phoenix.android.utils.Converter.toPrettyString -import fr.acinq.phoenix.android.utils.logger import fr.acinq.phoenix.android.utils.safeLet import fr.acinq.phoenix.controllers.payments.Scan import fr.acinq.phoenix.utils.extensions.isAmountlessTrampoline @@ -49,9 +48,6 @@ fun SendLightningPaymentView( onBackClick: () -> Unit, onPayClick: (Scan.Intent.InvoiceFlow.SendInvoicePayment) -> Unit ) { - val log = logger("SendLightningPaymentView") - log.debug { "init sendview amount=${paymentRequest.amount} desc=${paymentRequest.description}" } - val context = LocalContext.current val balance = business.balanceManager.balance.collectAsState(null).value val prefBitcoinUnit = LocalBitcoinUnit.current diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/cpfp/CpfpView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/cpfp/CpfpView.kt index b638c120c..58feafd43 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/cpfp/CpfpView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/cpfp/CpfpView.kt @@ -53,7 +53,6 @@ import fr.acinq.phoenix.android.components.feedback.ErrorMessage import fr.acinq.phoenix.android.payments.spliceout.spliceFailureDetails import fr.acinq.phoenix.android.utils.Converter.toPrettyString import fr.acinq.phoenix.android.utils.annotatedStringResource -import fr.acinq.phoenix.android.utils.logger import fr.acinq.phoenix.android.utils.positiveColor import fr.acinq.phoenix.data.BitcoinUnit @@ -63,8 +62,6 @@ fun CpfpView( channelId: ByteVector32, onSuccess: () -> Unit, ) { - val logger = logger("CpfpView") - val peerManager = business.peerManager val vm = viewModel(factory = CpfpViewModel.Factory(peerManager)) val mempoolFeerate by business.appConfigurationManager.mempoolFeerate.collectAsState() diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/details/PaymentDetailsSplashView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/details/PaymentDetailsSplashView.kt index 9a4a16807..eb63d5db7 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/details/PaymentDetailsSplashView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/details/PaymentDetailsSplashView.kt @@ -649,7 +649,6 @@ private fun ConfirmationView( onCpfpSuccess: () -> Unit, minDepth: Int? = null, // sometimes we know how many confirmations are needed ) { - val log = logger("PaymentDetailsSplashView") val txUrl = txUrl(txId = txId) val context = LocalContext.current val electrumClient = business.electrumClient @@ -670,9 +669,9 @@ private fun ConfirmationView( suspend fun getConfirmations(): Int { val confirmations = electrumClient.getConfirmations(txId) - log.debug { "retrieved confirmations=$confirmations from electrum for tx=$txId" } +// log.debug { "retrieved confirmations=$confirmations from electrum for tx=$txId" } return confirmations ?: run { - log.debug { "retrying getConfirmations from electrum in 5 sec" } +// log.debug { "retrying getConfirmations from electrum in 5 sec" } delay(5_000) getConfirmations() } diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/history/CsvExportView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/history/CsvExportView.kt index 365c74876..ac3136d98 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/history/CsvExportView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/history/CsvExportView.kt @@ -33,7 +33,6 @@ import fr.acinq.phoenix.android.components.* import fr.acinq.phoenix.android.components.feedback.ErrorMessage import fr.acinq.phoenix.android.utils.Converter.toBasicAbsoluteDateString import fr.acinq.phoenix.android.utils.copyToClipboard -import fr.acinq.phoenix.android.utils.logger import fr.acinq.phoenix.android.utils.positiveColor import fr.acinq.phoenix.android.utils.shareFile @@ -42,7 +41,6 @@ import fr.acinq.phoenix.android.utils.shareFile fun CsvExportView( onBackClick: () -> Unit, ) { - val log = logger("CsvExportView") val context = LocalContext.current val vm: CsvExportViewModel = viewModel( factory = CsvExportViewModel.Factory( diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/history/PaymentsHistoryView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/history/PaymentsHistoryView.kt index 948d2c5ee..78c7de1b1 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/history/PaymentsHistoryView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/history/PaymentsHistoryView.kt @@ -47,7 +47,6 @@ import fr.acinq.phoenix.android.components.DefaultScreenLayout import fr.acinq.phoenix.android.components.ItemCard import fr.acinq.phoenix.android.payments.details.PaymentLine import fr.acinq.phoenix.android.payments.details.PaymentLineLoading -import fr.acinq.phoenix.android.utils.logger import fr.acinq.phoenix.data.WalletPaymentId import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter @@ -103,7 +102,6 @@ fun PaymentsHistoryView( onPaymentClick: (WalletPaymentId) -> Unit, onCsvExportClick: () -> Unit, ) { - val log = logger("PaymentsHistory") val listState = rememberLazyListState() val allPaymentsCount by business.paymentsManager.paymentsCount.collectAsState() val payments by paymentsViewModel.paymentsFlow.collectAsState() diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/spliceout/SpliceOutView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/spliceout/SpliceOutView.kt index e6a5cbc83..c010f2c92 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/spliceout/SpliceOutView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/spliceout/SpliceOutView.kt @@ -44,7 +44,6 @@ import fr.acinq.phoenix.android.components.* import fr.acinq.phoenix.android.components.feedback.ErrorMessage import fr.acinq.phoenix.android.utils.Converter.toPrettyString import fr.acinq.phoenix.android.utils.annotatedStringResource -import fr.acinq.phoenix.android.utils.logger import fr.acinq.phoenix.data.BitcoinUnit import fr.acinq.phoenix.data.MempoolFeerate @@ -57,9 +56,6 @@ fun SendSpliceOutView( onBackClick: () -> Unit, onSpliceOutSuccess: () -> Unit, ) { - val log = logger("SendSpliceOut") - log.debug { "init splice-out with amount=$requestedAmount address=$address" } - val context = LocalContext.current val prefBtcUnit = LocalBitcoinUnit.current val keyboardManager = LocalSoftwareKeyboardController.current diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/security/SeedManager.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/security/SeedManager.kt index 7d9e97187..c30bd38ca 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/security/SeedManager.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/security/SeedManager.kt @@ -17,8 +17,7 @@ package fr.acinq.phoenix.android.security import android.content.Context -import org.kodein.log.LoggerFactory -import org.kodein.log.newLogger +import org.slf4j.LoggerFactory import java.io.File sealed class SeedFileState { @@ -36,7 +35,7 @@ sealed class SeedFileState { object SeedManager { private val BASE_DATADIR = "node-data" private const val SEED_FILE = "seed.dat" - private val log = newLogger(LoggerFactory.default) + private val log = LoggerFactory.getLogger(this::class.java) // newLogger(LoggerFactory.default) fun getDatadir(context: Context): File { return File(context.filesDir, BASE_DATADIR) @@ -52,7 +51,7 @@ object SeedManager { else -> SeedFileState.Error.UnhandledSeedType } } catch (e: Exception) { - log.error(e) { "failed to read seed: " } + log.error("failed to read seed: ", e) SeedFileState.Error.Unreadable(e.localizedMessage) } @@ -91,7 +90,7 @@ object SeedManager { // 3 - decrypt temp file and check validity; if correct, move temp file to final file val checkSeed = loadSeedFromDir(dir, temp.name) as EncryptedSeed.V2 if (!checkSeed.ciphertext.contentEquals(seed.ciphertext)) { - log.warning { "seed check do not match!" } + log.warn("seed check do not match!") // throw WriteErrorCheckDontMatch } temp.copyTo(File(dir, SEED_FILE), overwrite) diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/AboutView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/AboutView.kt index f9cfee644..9d2adebc7 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/AboutView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/AboutView.kt @@ -32,12 +32,10 @@ import fr.acinq.phoenix.android.R import fr.acinq.phoenix.android.components.* import fr.acinq.phoenix.android.navController import fr.acinq.phoenix.android.utils.annotatedStringResource -import fr.acinq.phoenix.android.utils.logger @Composable fun AboutView() { - val log = logger("AboutView") val nc = navController val context = LocalContext.current diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/AppLockView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/AppLockView.kt index ebd70a3cc..85720b716 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/AppLockView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/AppLockView.kt @@ -38,7 +38,6 @@ import kotlinx.coroutines.launch fun AppLockView( onBackClick: () -> Unit, ) { - val log = logger("AppLockView") val context = LocalContext.current val authStatus = BiometricsHelper.authStatus(context) val isScreenLockActive by UserPrefs.getIsScreenLockActive(context).collectAsState(null) diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/ElectrumView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/ElectrumView.kt index 88394eee9..f79abef63 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/ElectrumView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/ElectrumView.kt @@ -56,7 +56,6 @@ import java.text.NumberFormat @Composable fun ElectrumView() { - val log = logger("ElectrumView") val nc = navController val context = LocalContext.current val scope = rememberCoroutineScope() diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/ForceCloseView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/ForceCloseView.kt index 3e3b9d5fa..96fdadf53 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/ForceCloseView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/ForceCloseView.kt @@ -33,7 +33,6 @@ import fr.acinq.phoenix.android.R import fr.acinq.phoenix.android.components.* import fr.acinq.phoenix.android.components.mvi.MVIView import fr.acinq.phoenix.android.utils.annotatedStringResource -import fr.acinq.phoenix.android.utils.logger import fr.acinq.phoenix.android.utils.monoTypo import fr.acinq.phoenix.android.utils.negativeColor import fr.acinq.phoenix.controllers.config.CloseChannelsConfiguration @@ -42,7 +41,6 @@ import fr.acinq.phoenix.controllers.config.CloseChannelsConfiguration fun ForceCloseView( onBackClick: () -> Unit ) { - val log = logger("ForceCloseView") var showConfirmationDialog by remember { mutableStateOf(false) } MVIView(CF::forceCloseChannelsConfiguration) { model, postIntent -> diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/LogsView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/LogsView.kt index 903e434c6..0ee1a0bf7 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/LogsView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/LogsView.kt @@ -35,7 +35,6 @@ import fr.acinq.phoenix.android.components.DefaultScreenLayout import fr.acinq.phoenix.android.components.SettingButton import fr.acinq.phoenix.android.navController import fr.acinq.phoenix.android.utils.Logging -import fr.acinq.phoenix.android.utils.logger import fr.acinq.phoenix.android.utils.shareFile private sealed class LogsExportState { @@ -45,7 +44,6 @@ private sealed class LogsExportState { } @Composable fun LogsView() { - val log = logger("LogsView") val nc = navController val context = LocalContext.current val authority = remember { "${BuildConfig.APPLICATION_ID}.provider" } diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/MutualCloseView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/MutualCloseView.kt index f5bb0f2ed..332bffcc9 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/MutualCloseView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/MutualCloseView.kt @@ -42,11 +42,9 @@ import fr.acinq.phoenix.android.payments.CameraPermissionsView import fr.acinq.phoenix.android.payments.ScannerView import fr.acinq.phoenix.android.utils.Converter.toPrettyString import fr.acinq.phoenix.android.utils.annotatedStringResource -import fr.acinq.phoenix.android.utils.logger import fr.acinq.phoenix.android.utils.monoTypo import fr.acinq.phoenix.android.utils.mutedBgColor import fr.acinq.phoenix.controllers.config.CloseChannelsConfiguration -import fr.acinq.phoenix.controllers.payments.Scan import fr.acinq.phoenix.data.BitcoinAddressError import fr.acinq.phoenix.utils.Parser @@ -55,7 +53,6 @@ import fr.acinq.phoenix.utils.Parser fun MutualCloseView( onBackClick: () -> Unit, ) { - val log = logger("MutualCloseView") val context = LocalContext.current val balance by business.balanceManager.balance.collectAsState(0.msat) diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/NotificationsView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/NotificationsView.kt index 88a195261..2281254ab 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/NotificationsView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/NotificationsView.kt @@ -50,7 +50,6 @@ import fr.acinq.phoenix.android.utils.Converter.toAbsoluteDateTimeString import fr.acinq.phoenix.android.utils.Converter.toPrettyString import fr.acinq.phoenix.android.utils.Converter.toRelativeDateString import fr.acinq.phoenix.android.utils.datastore.UserPrefs -import fr.acinq.phoenix.android.utils.logger import fr.acinq.phoenix.android.utils.safeLet import fr.acinq.phoenix.data.Notification import fr.acinq.phoenix.data.WatchTowerOutcome @@ -63,7 +62,6 @@ fun NotificationsView( noticesViewModel: NoticesViewModel, onBackClick: () -> Unit, ) { - val log = logger("NotificationsView") val notificationsManager = business.notificationsManager // TODO: filter rejected payments where the fee policy was X, but the fee policy is now Y val notices = noticesViewModel.notices.sortedBy { it.priority } diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/PaymentSettingsView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/PaymentSettingsView.kt index 6223bfa8b..8ecd48a96 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/PaymentSettingsView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/PaymentSettingsView.kt @@ -42,7 +42,6 @@ import fr.acinq.phoenix.android.R import fr.acinq.phoenix.android.components.* import fr.acinq.phoenix.android.navController import fr.acinq.phoenix.android.utils.datastore.UserPrefs -import fr.acinq.phoenix.android.utils.logger import fr.acinq.phoenix.data.lnurl.LnurlAuth import kotlinx.coroutines.launch import java.text.NumberFormat @@ -51,7 +50,6 @@ import java.text.NumberFormat fun PaymentSettingsView( initialShowLnurlAuthSchemeDialog: Boolean = false, ) { - val log = logger("PaymentSettingsView") val nc = navController val scope = rememberCoroutineScope() val context = LocalContext.current diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/TorConfigView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/TorConfigView.kt index 17ceb3eec..c50de7d1a 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/TorConfigView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/TorConfigView.kt @@ -34,17 +34,13 @@ import fr.acinq.phoenix.android.business import fr.acinq.phoenix.android.components.* import fr.acinq.phoenix.android.navController import fr.acinq.phoenix.android.utils.datastore.UserPrefs -import fr.acinq.phoenix.android.utils.logger import fr.acinq.phoenix.android.utils.negativeColor import fr.acinq.phoenix.android.utils.orange import fr.acinq.phoenix.android.utils.positiveColor import kotlinx.coroutines.launch @Composable -fun TorConfigView( - -) { - val log = logger("TorSettingView") +fun TorConfigView() { val context = LocalContext.current val scope = rememberCoroutineScope() val business = business diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/channels/ChannelDetailsView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/channels/ChannelDetailsView.kt index 621756444..7e77c1d91 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/channels/ChannelDetailsView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/channels/ChannelDetailsView.kt @@ -77,7 +77,6 @@ import fr.acinq.phoenix.android.navigateToPaymentDetails import fr.acinq.phoenix.android.utils.Converter.toPrettyString import fr.acinq.phoenix.android.utils.MSatDisplayPolicy import fr.acinq.phoenix.android.utils.copyToClipboard -import fr.acinq.phoenix.android.utils.logger import fr.acinq.phoenix.android.utils.monoTypo import fr.acinq.phoenix.android.utils.mutedBgColor import fr.acinq.phoenix.android.utils.share @@ -90,7 +89,6 @@ fun ChannelDetailsView( onBackClick: () -> Unit, channelId: String?, ) { - val log = logger("ChannelDetailsView") val channelsState = business.peerManager.channelsFlow.collectAsState() DefaultScreenLayout(isScrollable = false) { diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/channels/ChannelsView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/channels/ChannelsView.kt index 754d483df..fc9207aea 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/channels/ChannelsView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/channels/ChannelsView.kt @@ -52,7 +52,6 @@ import fr.acinq.phoenix.android.R import fr.acinq.phoenix.android.business import fr.acinq.phoenix.android.components.* import fr.acinq.phoenix.android.utils.annotatedStringResource -import fr.acinq.phoenix.android.utils.logger import fr.acinq.phoenix.android.utils.mutedTextColor import fr.acinq.phoenix.android.utils.negativeColor import fr.acinq.phoenix.android.utils.positiveColor @@ -65,8 +64,6 @@ fun ChannelsView( onChannelClick: (String) -> Unit, onImportChannelsDataClick: () -> Unit, ) { - val log = logger("ChannelsView") - val channelsState by business.peerManager.channelsFlow.collectAsState() val balance by business.balanceManager.balance.collectAsState() val inboundLiquidity = channelsState?.values?.mapNotNull { it.availableForReceive }?.sum() diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/displayseed/DisplaySeedView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/displayseed/DisplaySeedView.kt index 2f9347c0f..229fbc974 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/displayseed/DisplaySeedView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/displayseed/DisplaySeedView.kt @@ -42,7 +42,6 @@ import fr.acinq.phoenix.android.components.feedback.WarningMessage import fr.acinq.phoenix.android.navController import fr.acinq.phoenix.android.security.SeedManager import fr.acinq.phoenix.android.utils.annotatedStringResource -import fr.acinq.phoenix.android.utils.logger import fr.acinq.phoenix.android.utils.mutedTextColor import fr.acinq.phoenix.android.utils.safeLet import kotlinx.coroutines.launch @@ -50,7 +49,6 @@ import kotlinx.coroutines.launch @Composable fun DisplaySeedView() { - val log = logger("DisplaySeedView") val nc = navController val context = LocalContext.current val internalData = application.internalDataRepository diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/fees/LiquidityPolicyView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/fees/LiquidityPolicyView.kt index 617538f40..64571b2af 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/fees/LiquidityPolicyView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/fees/LiquidityPolicyView.kt @@ -46,7 +46,6 @@ import fr.acinq.phoenix.android.fiatRate import fr.acinq.phoenix.android.utils.Converter.toPrettyString import fr.acinq.phoenix.android.utils.annotatedStringResource import fr.acinq.phoenix.android.utils.datastore.UserPrefs -import fr.acinq.phoenix.android.utils.logger import fr.acinq.phoenix.android.utils.negativeColor import fr.acinq.phoenix.data.BitcoinUnit import fr.acinq.phoenix.data.MempoolFeerate @@ -60,7 +59,6 @@ fun LiquidityPolicyView( onAdvancedClick: () -> Unit, onRequestLiquidityClick: () -> Unit, ) { - val log = logger("LiquidityPolicyView") val context = LocalContext.current val scope = rememberCoroutineScope() diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/startup/LegacySwitcherView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/startup/LegacySwitcherView.kt index 10cdf947b..32fdd6b6e 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/startup/LegacySwitcherView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/startup/LegacySwitcherView.kt @@ -50,7 +50,7 @@ fun LegacySwitcherView( val business = business val connectionsDaemon = business.appConnectionsDaemon val legacyAppStatus by LegacyPrefsDatastore.getLegacyAppStatus(context).collectAsState(initial = null) - log.debug { "legacy switcher with legacyAppStatus=${legacyAppStatus}" } + log.debug("legacy switcher with legacyAppStatus=${legacyAppStatus}") Column( modifier = Modifier @@ -77,7 +77,7 @@ fun LegacySwitcherView( scope.launch { if (legacyAppStatus == LegacyAppStatus.Required.InitStart) { LegacyPrefsDatastore.saveStartLegacyApp(context, LegacyAppStatus.Required.Running) - log.info { "switching to legacy app" } + log.info("switching to legacy app") context.startActivity(Intent(context, MainActivity::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP) }) diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/startup/StartupView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/startup/StartupView.kt index e82c3cfcf..2d49a790d 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/startup/StartupView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/startup/StartupView.kt @@ -92,7 +92,6 @@ fun StartupView( onKeyAbsent: () -> Unit, onBusinessStarted: () -> Unit, ) { - val log = logger("StartupView") val context = LocalContext.current val serviceState by appVM.serviceState.observeAsState() val showIntro by application.internalDataRepository.getShowIntro.collectAsState(initial = null) @@ -126,7 +125,7 @@ fun StartupView( activity = context.findActivity(), onSuccess = { appVM.saveIsScreenLocked(false) }, onFailure = { appVM.saveIsScreenLocked(true) }, - onCancel = { log.debug { "cancelled auth prompt" } } + onCancel = { } ).authenticate(promptInfo) } LaunchedEffect(key1 = true) { @@ -188,7 +187,7 @@ private fun DecryptSeedAndStartBusiness( is SeedFileState.Error.Unreadable -> Text(stringResource(id = R.string.startup_error_generic, seedFileState.message ?: "")) is SeedFileState.Error.UnhandledSeedType -> Text(stringResource(id = R.string.startup_error_generic, "Unhandled seed type")) is SeedFileState.Present -> { - log.debug { "wallet ready to start with legacyAppStatus=${legacyAppStatus?.name()}" } + log.debug("wallet ready to start with legacyAppStatus=${legacyAppStatus?.name()}") val decryptionState by vm.decryptionState when (val state = decryptionState) { is StartupDecryptionState.Init -> { @@ -201,7 +200,7 @@ private fun DecryptSeedAndStartBusiness( LegacyAppStatus.Unknown -> { if (Wallet.getEclairDBFile(context).exists()) { Text(stringResource(id = R.string.startup_wait_legacy_check)) - log.debug { "found legacy database file while in unknown legacy status; switching to legacy app" } + log.debug("found legacy database file while in unknown legacy status; switching to legacy app") LaunchedEffect(true) { LegacyPrefsDatastore.saveStartLegacyApp(context, LegacyAppStatus.Required.Expected) } diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/utils/Logging.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/utils/Logging.kt index 360ce3cab..47e6db817 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/utils/Logging.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/utils/Logging.kt @@ -18,9 +18,7 @@ package fr.acinq.phoenix.android.utils import android.content.Context import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.remember -import androidx.compose.ui.platform.LocalContext import ch.qos.logback.classic.Level import ch.qos.logback.classic.Logger import ch.qos.logback.classic.LoggerContext @@ -33,28 +31,15 @@ import ch.qos.logback.core.rolling.RollingFileAppender import ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy import ch.qos.logback.core.util.FileSize import fr.acinq.phoenix.android.BuildConfig -import fr.acinq.phoenix.android.PhoenixApplication -import org.kodein.log.frontend.slf4jFrontend import org.slf4j.LoggerFactory import java.io.File import java.io.FileInputStream import java.io.FileOutputStream + @Composable -fun logger(name: String? = null): org.kodein.log.Logger { - val context = LocalContext.current - val application = context.applicationContext - val tag = name?.let { org.kodein.log.Logger.Tag(BuildConfig.APPLICATION_ID, it) } ?: org.kodein.log.Logger.Tag(context::class) - - return if (application !is PhoenixApplication) { // Preview mode - remember(tag) { org.kodein.log.LoggerFactory(slf4jFrontend).newLogger(tag) } - } else { - val businessState = application.business.collectAsState() - when (val business = businessState.value) { - null -> remember(tag) { org.kodein.log.LoggerFactory(slf4jFrontend).newLogger(tag) } - else -> remember(tag) { business.loggerFactory.newLogger(tag) } - } - } +fun logger(name: String? = null): org.slf4j.Logger { + return remember(name) { LoggerFactory.getLogger(name) } } object Logging { diff --git a/phoenix-ios/phoenix-ios.xcodeproj/project.pbxproj b/phoenix-ios/phoenix-ios.xcodeproj/project.pbxproj index 42ff55f5a..2a07f19c5 100644 --- a/phoenix-ios/phoenix-ios.xcodeproj/project.pbxproj +++ b/phoenix-ios/phoenix-ios.xcodeproj/project.pbxproj @@ -64,6 +64,7 @@ DC1B325029FC3D5900F7F45F /* OnChainDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC1B324F29FC3D5900F7F45F /* OnChainDetails.swift */; }; DC1D2B4B2593EB860036AD38 /* Currency.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC1D2B4A2593EB850036AD38 /* Currency.swift */; }; DC1D2B502594CE900036AD38 /* FormattedAmount.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC1D2B4F2594CE900036AD38 /* FormattedAmount.swift */; }; + DC1E75722B73DD500026F36E /* LogFileParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC1E75712B73DD500026F36E /* LogFileParser.swift */; }; DC26D0BB2A93BD0F006763B3 /* EffectsLibrary in Frameworks */ = {isa = PBXBuildFile; productRef = DC26D0BA2A93BD0F006763B3 /* EffectsLibrary */; }; DC27E4C42791C58C00C777CC /* PaymentsBackupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC27E4C32791C58C00C777CC /* PaymentsBackupView.swift */; }; DC27E4CB2791D17A00C777CC /* RecoveryPhraseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC27E4C92791D17A00C777CC /* RecoveryPhraseView.swift */; }; @@ -165,6 +166,7 @@ DC74174B270F332700F7E3E3 /* KotlinTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC74174A270F332700F7E3E3 /* KotlinTypes.swift */; }; DC74174D270F455D00F7E3E3 /* AES256.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC74174C270F455D00F7E3E3 /* AES256.swift */; }; DC784A112B31EA180018DC4A /* LiquidityAdsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC784A102B31EA180018DC4A /* LiquidityAdsView.swift */; }; + DC7DA9F62AD84DF200F86B99 /* String+Substring.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC7DA9F52AD84DF200F86B99 /* String+Substring.swift */; }; DC81B79F25BF2AA200F5A52C /* MVI.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC81B79E25BF2AA200F5A52C /* MVI.swift */; }; DC82EED629789853007A5853 /* TxHistoryExporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC82EED529789853007A5853 /* TxHistoryExporter.swift */; }; DC89857F25914747007B253F /* UIApplicationState+Phoenix.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC89857E25914747007B253F /* UIApplicationState+Phoenix.swift */; }; @@ -239,6 +241,24 @@ DCCD045F27EE0301007D57A5 /* SummaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCCD045E27EE0301007D57A5 /* SummaryView.swift */; }; DCCD046127EE045C007D57A5 /* DetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCCD046027EE045C007D57A5 /* DetailsView.swift */; }; DCCD046327EE04E1007D57A5 /* WalletPaymentExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCCD046227EE04E1007D57A5 /* WalletPaymentExtensions.swift */; }; + DCCFE6A42B63021E002FFF11 /* KotlinLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCCFE6A32B63021E002FFF11 /* KotlinLogger.swift */; }; + DCCFE6A62B63028A002FFF11 /* UnfairLock.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCCFE6A52B63028A002FFF11 /* UnfairLock.swift */; }; + DCCFE6A72B630836002FFF11 /* KotlinLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCCFE6A32B63021E002FFF11 /* KotlinLogger.swift */; }; + DCCFE6A82B63083F002FFF11 /* UnfairLock.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCCFE6A52B63028A002FFF11 /* UnfairLock.swift */; }; + DCCFE6AB2B6430AB002FFF11 /* Logging in Frameworks */ = {isa = PBXBuildFile; productRef = DCCFE6AA2B6430AB002FFF11 /* Logging */; }; + DCCFE6AE2B64310E002FFF11 /* LoggerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCCFE6AD2B64310E002FFF11 /* LoggerFactory.swift */; }; + DCCFE6B02B64326F002FFF11 /* OSLogHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCCFE6AF2B64326F002FFF11 /* OSLogHandler.swift */; }; + DCCFE6B22B6445F3002FFF11 /* LogFileHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCCFE6B12B6445F3002FFF11 /* LogFileHandler.swift */; }; + DCCFE6B32B680DF5002FFF11 /* LoggerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCCFE6AD2B64310E002FFF11 /* LoggerFactory.swift */; }; + DCCFE6B42B680DF9002FFF11 /* OSLogHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCCFE6AF2B64326F002FFF11 /* OSLogHandler.swift */; }; + DCCFE6B72B682E22002FFF11 /* Logging in Frameworks */ = {isa = PBXBuildFile; productRef = DCCFE6B62B682E22002FFF11 /* Logging */; }; + DCCFE6B92B69A4FA002FFF11 /* LogFileInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCCFE6B82B69A4FA002FFF11 /* LogFileInfo.swift */; }; + DCCFE6BD2B69A610002FFF11 /* LogFileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCCFE6BC2B69A610002FFF11 /* LogFileManager.swift */; }; + DCCFE6BE2B713FB8002FFF11 /* LogFileInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCCFE6B82B69A4FA002FFF11 /* LogFileInfo.swift */; }; + DCCFE6BF2B713FBB002FFF11 /* LogFileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCCFE6BC2B69A610002FFF11 /* LogFileManager.swift */; }; + DCCFE6C02B713FBE002FFF11 /* LogFileHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCCFE6B12B6445F3002FFF11 /* LogFileHandler.swift */; }; + DCCFE6C22B7140FA002FFF11 /* LoggerFactory+Foreground.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCCFE6C12B7140FA002FFF11 /* LoggerFactory+Foreground.swift */; }; + DCCFE6C52B714226002FFF11 /* LoggerFactory+Background.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCCFE6C32B714171002FFF11 /* LoggerFactory+Background.swift */; }; DCD1208728663F4A00EB39C5 /* TransactionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCD1208628663F4A00EB39C5 /* TransactionsView.swift */; }; DCD5FF4326A0D34B009CC666 /* EqualSizes.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCD5FF4226A0D34B009CC666 /* EqualSizes.swift */; }; DCD777D226DE9FE800979A12 /* DelayedSave.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCD777D126DE9FE800979A12 /* DelayedSave.swift */; }; @@ -416,6 +436,7 @@ DC1B324F29FC3D5900F7F45F /* OnChainDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnChainDetails.swift; sourceTree = ""; }; DC1D2B4A2593EB850036AD38 /* Currency.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Currency.swift; sourceTree = ""; }; DC1D2B4F2594CE900036AD38 /* FormattedAmount.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormattedAmount.swift; sourceTree = ""; }; + DC1E75712B73DD500026F36E /* LogFileParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogFileParser.swift; sourceTree = ""; }; DC27E4C32791C58C00C777CC /* PaymentsBackupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaymentsBackupView.swift; sourceTree = ""; }; DC27E4C92791D17A00C777CC /* RecoveryPhraseView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecoveryPhraseView.swift; sourceTree = ""; }; DC27E4CA2791D17A00C777CC /* CloudBackupView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CloudBackupView.swift; sourceTree = ""; }; @@ -502,6 +523,7 @@ DC74174A270F332700F7E3E3 /* KotlinTypes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KotlinTypes.swift; sourceTree = ""; }; DC74174C270F455D00F7E3E3 /* AES256.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AES256.swift; sourceTree = ""; }; DC784A102B31EA180018DC4A /* LiquidityAdsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiquidityAdsView.swift; sourceTree = ""; }; + DC7DA9F52AD84DF200F86B99 /* String+Substring.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Substring.swift"; sourceTree = ""; }; DC81B79E25BF2AA200F5A52C /* MVI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MVI.swift; sourceTree = ""; }; DC82EED529789853007A5853 /* TxHistoryExporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TxHistoryExporter.swift; sourceTree = ""; }; DC89857E25914747007B253F /* UIApplicationState+Phoenix.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIApplicationState+Phoenix.swift"; sourceTree = ""; }; @@ -567,6 +589,15 @@ DCCD045E27EE0301007D57A5 /* SummaryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SummaryView.swift; sourceTree = ""; }; DCCD046027EE045C007D57A5 /* DetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailsView.swift; sourceTree = ""; }; DCCD046227EE04E1007D57A5 /* WalletPaymentExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletPaymentExtensions.swift; sourceTree = ""; }; + DCCFE6A32B63021E002FFF11 /* KotlinLogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KotlinLogger.swift; sourceTree = ""; }; + DCCFE6A52B63028A002FFF11 /* UnfairLock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnfairLock.swift; sourceTree = ""; }; + DCCFE6AD2B64310E002FFF11 /* LoggerFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggerFactory.swift; sourceTree = ""; }; + DCCFE6AF2B64326F002FFF11 /* OSLogHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OSLogHandler.swift; sourceTree = ""; }; + DCCFE6B12B6445F3002FFF11 /* LogFileHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogFileHandler.swift; sourceTree = ""; }; + DCCFE6B82B69A4FA002FFF11 /* LogFileInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogFileInfo.swift; sourceTree = ""; }; + DCCFE6BC2B69A610002FFF11 /* LogFileManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogFileManager.swift; sourceTree = ""; }; + DCCFE6C12B7140FA002FFF11 /* LoggerFactory+Foreground.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LoggerFactory+Foreground.swift"; sourceTree = ""; }; + DCCFE6C32B714171002FFF11 /* LoggerFactory+Background.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LoggerFactory+Background.swift"; sourceTree = ""; }; DCD1208628663F4A00EB39C5 /* TransactionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionsView.swift; sourceTree = ""; }; DCD5FF4226A0D34B009CC666 /* EqualSizes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EqualSizes.swift; sourceTree = ""; }; DCD777D126DE9FE800979A12 /* DelayedSave.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DelayedSave.swift; sourceTree = ""; }; @@ -620,6 +651,7 @@ DCC9D99C267BEB3D00EA36DD /* CloudKit.framework in Frameworks */, DC39D4E5286B4A7E0030F18D /* Popovers in Frameworks */, DCC46F1625C3521C005D32D9 /* FirebaseMessaging in Frameworks */, + DCCFE6AB2B6430AB002FFF11 /* Logging in Frameworks */, DCB0DB8A255AE42F005B29C8 /* PhoenixShared.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -642,6 +674,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + DCCFE6B72B682E22002FFF11 /* Logging in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -699,6 +732,7 @@ DCAEF8F627628BEB00015993 /* Either.swift */, DCDD9ECD28637474001800A3 /* Orientation.swift */, DC355E222A45FAF2008E8A8E /* NestedObservableObject.swift */, + DCCFE6A52B63028A002FFF11 /* UnfairLock.swift */, ); path = utils; sourceTree = ""; @@ -787,6 +821,7 @@ DCACF6EE2566D0A60009B01E /* extensions */, DCA6DEC42829BD060073C658 /* xpc */, DCE3C7A92A6AD39E00F4D385 /* mempool */, + DCCFE6AC2B6430BD002FFF11 /* logging */, ); path = "phoenix-ios"; sourceTree = ""; @@ -911,6 +946,7 @@ DC46BAEF26CACCF700E760A6 /* KotlinPublishers+Phoenix.swift */, DCB62F462A5DF19D00912A71 /* KotlinPublishers+Lightning.swift */, DC74174A270F332700F7E3E3 /* KotlinTypes.swift */, + DCCFE6A32B63021E002FFF11 /* KotlinLogger.swift */, ); path = kotlin; sourceTree = ""; @@ -1139,6 +1175,7 @@ DC422F3429392B0500E72253 /* Int+ToDate.swift */, DCB493CA269F3B05001B0F09 /* Result+Deugly.swift */, DC59377027516296003B4B53 /* Sequence+Sum.swift */, + DC7DA9F52AD84DF200F86B99 /* String+Substring.swift */, DC09085725B5E43900A46136 /* String+VersionComparison.swift */, DC384D82265C32F100131772 /* TextField+Verbatim.swift */, DC89857E25914747007B253F /* UIApplicationState+Phoenix.swift */, @@ -1234,6 +1271,29 @@ path = inspect; sourceTree = ""; }; + DCCFE6AC2B6430BD002FFF11 /* logging */ = { + isa = PBXGroup; + children = ( + DCCFE6AD2B64310E002FFF11 /* LoggerFactory.swift */, + DCCFE6C12B7140FA002FFF11 /* LoggerFactory+Foreground.swift */, + DCCFE6C32B714171002FFF11 /* LoggerFactory+Background.swift */, + DCCFE6AF2B64326F002FFF11 /* OSLogHandler.swift */, + DCCFE6BA2B69A502002FFF11 /* fileLogging */, + ); + path = logging; + sourceTree = ""; + }; + DCCFE6BA2B69A502002FFF11 /* fileLogging */ = { + isa = PBXGroup; + children = ( + DCCFE6B82B69A4FA002FFF11 /* LogFileInfo.swift */, + DCCFE6BC2B69A610002FFF11 /* LogFileManager.swift */, + DCCFE6B12B6445F3002FFF11 /* LogFileHandler.swift */, + DC1E75712B73DD500026F36E /* LogFileParser.swift */, + ); + path = fileLogging; + sourceTree = ""; + }; DCD1208528663F2D00EB39C5 /* transactions */ = { isa = PBXGroup; children = ( @@ -1339,6 +1399,7 @@ DC39D4E4286B4A7E0030F18D /* Popovers */, DCA5391929F1DDE7001BD3D5 /* SegmentedPicker */, DC26D0BA2A93BD0F006763B3 /* EffectsLibrary */, + DCCFE6AA2B6430AB002FFF11 /* Logging */, ); productName = "phoenix-ios"; productReference = 7555FF7B242A565900829871 /* Phoenix.app */; @@ -1414,6 +1475,9 @@ DC641C692820786600862DCD /* PBXTargetDependency */, ); name = "phoenix-notifySrvExt"; + packageProductDependencies = ( + DCCFE6B62B682E22002FFF11 /* Logging */, + ); productName = "phoenix-notifySrvExt"; productReference = DCB511C7281AED58001BC525 /* phoenix-notifySrvExt.appex */; productType = "com.apple.product-type.app-extension"; @@ -1466,6 +1530,7 @@ DC39D4E3286B4A7E0030F18D /* XCRemoteSwiftPackageReference "Popovers" */, DCA5391729F1DAA3001BD3D5 /* XCRemoteSwiftPackageReference "SwiftySegmentedPicker" */, DC26D0B82A93BA8C006763B3 /* XCRemoteSwiftPackageReference "effects-library" */, + DCCFE6A92B6430AB002FFF11 /* XCRemoteSwiftPackageReference "swift-log" */, ); productRefGroup = 7555FF7C242A565900829871 /* Products */; projectDirPath = ""; @@ -1571,8 +1636,10 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + DCCFE6BD2B69A610002FFF11 /* LogFileManager.swift in Sources */, DC09085825B5E43900A46136 /* String+VersionComparison.swift in Sources */, DC355E212A44D838008E8A8E /* NotificationsView.swift in Sources */, + DC7DA9F62AD84DF200F86B99 /* String+Substring.swift in Sources */, DC63BDF729AEB30C0067A361 /* BackgroundPaymentsConfig.swift in Sources */, DC67E40B27F3798600496C04 /* AnimatedMenu.swift in Sources */, DC2F431627B6983B0006FCC4 /* CopyOptionsSheet.swift in Sources */, @@ -1584,6 +1651,7 @@ DC82EED629789853007A5853 /* TxHistoryExporter.swift in Sources */, DC98D3982AF2AE41005BD177 /* ReceiveView.swift in Sources */, DC9E7EC32A12955300A5F1D0 /* LiquidityHTML.swift in Sources */, + DCCFE6C22B7140FA002FFF11 /* LoggerFactory+Foreground.swift in Sources */, 7555FF7F242A565900829871 /* AppDelegate.swift in Sources */, DC74174B270F332700F7E3E3 /* KotlinTypes.swift in Sources */, DC142135261E72320075857A /* AboutHTML.swift in Sources */, @@ -1610,6 +1678,7 @@ DCD777D226DE9FE800979A12 /* DelayedSave.swift in Sources */, DCEE3E542931446A00EB4DFF /* Collections+AsInt.swift in Sources */, DCACF70E256701870009B01E /* LockView.swift in Sources */, + DCCFE6B92B69A4FA002FFF11 /* LogFileInfo.swift in Sources */, DC63BDF929AEB8180067A361 /* BackgroundPaymentsSelector.swift in Sources */, DCB30E542A0AABAF00E7D7A2 /* InfoPopoverWindow.swift in Sources */, DCA6DEC62829BDEB0073C658 /* CrossProcessCommunication.swift in Sources */, @@ -1649,6 +1718,8 @@ DC118C0C27B561210080BBAC /* CurrencyAmount.swift in Sources */, DC04C2632A9009890021F2E8 /* MergeChannelsView.swift in Sources */, DC46BAF726CACCF700E760A6 /* KotlinExtensions+Conversion.swift in Sources */, + DCCFE6A42B63021E002FFF11 /* KotlinLogger.swift in Sources */, + DCCFE6AE2B64310E002FFF11 /* LoggerFactory.swift in Sources */, DC49FE992AC49C6300D8D2E2 /* KotlinExtensions+Bitcoin.swift in Sources */, DC142140261E72E40075857A /* AnyHTML.swift in Sources */, DC2CE3AF29AFEB0500BA0B00 /* Bundle+Icon.swift in Sources */, @@ -1701,6 +1772,7 @@ DC46BAF426CACCF700E760A6 /* KotlinFlow.swift in Sources */, DCB493CD269F8531001B0F09 /* Int+TimeInterval.swift in Sources */, DC118C0227B453110080BBAC /* PaymentRequestedView.swift in Sources */, + DCCFE6B22B6445F3002FFF11 /* LogFileHandler.swift in Sources */, DC422F3529392B0500E72253 /* Int+ToDate.swift in Sources */, DC384D83265C32F100131772 /* TextField+Verbatim.swift in Sources */, DCFA8759260E6F2E00AE8953 /* IntroView.swift in Sources */, @@ -1722,6 +1794,7 @@ DCAC5B7027726FC80077BB98 /* DeepLink.swift in Sources */, DC9473FA261270B4008D7242 /* MVI+Mock.swift in Sources */, DCDD9ECE28637474001800A3 /* Orientation.swift in Sources */, + DCCFE6B02B64326F002FFF11 /* OSLogHandler.swift in Sources */, DCDD9ECB28637242001800A3 /* MainView.swift in Sources */, DCDD9ED2286377C5001800A3 /* MainView_Small.swift in Sources */, C8D7AFF5BC5754DBBEEB2688 /* ElectrumConfigurationView.swift in Sources */, @@ -1733,6 +1806,7 @@ DCCC7FD526B0A006008ACD9B /* SquareSize.swift in Sources */, DC2CE54D28A3D2F50070A2E1 /* TruncatableView.swift in Sources */, DCDD9ED628637FD7001800A3 /* AppStatusButton.swift in Sources */, + DCCFE6A62B63028A002FFF11 /* UnfairLock.swift in Sources */, DCB493D1269F890D001B0F09 /* SyncTxManager_PendingSettings.swift in Sources */, DCAEF8F727628BEB00015993 /* Either.swift in Sources */, DCA6DECC282AAA740073C658 /* SharedSecurity.swift in Sources */, @@ -1741,6 +1815,7 @@ DCD7E0F128ED89A0009C30E5 /* GlobalEnvironment.swift in Sources */, DC09086325B626B300A46136 /* AppStatusPopover.swift in Sources */, DC0732EC263CA6C3004CB88D /* PaymentOptionsView.swift in Sources */, + DC1E75722B73DD500026F36E /* LogFileParser.swift in Sources */, DC49DA8E258BB882005BC4BC /* ScaledButtonStyle.swift in Sources */, DCAEF8D9275E69B000015993 /* SyncSeedManager_State.swift in Sources */, DCB04685260D162C007FDA37 /* ViewName.swift in Sources */, @@ -1824,7 +1899,10 @@ DCA6DED1282ABA930073C658 /* KeychainConstants.swift in Sources */, DCEB2796282D7AAB0096B87E /* KotlinTypes.swift in Sources */, DC9130A02AE045FA00F9B8C6 /* Sequence+Sum.swift in Sources */, + DCCFE6C02B713FBE002FFF11 /* LogFileHandler.swift in Sources */, + DCCFE6B42B680DF9002FFF11 /* OSLogHandler.swift in Sources */, DCB511CA281AED58001BC525 /* NotificationService.swift in Sources */, + DCCFE6A82B63083F002FFF11 /* UnfairLock.swift in Sources */, DCA6DEC82829C3150073C658 /* GenericPasswordStore.swift in Sources */, DCA6DECD282AB10C0073C658 /* SharedSecurity.swift in Sources */, DCEB2799282D7B260096B87E /* KotlinExtensions+Conversion.swift in Sources */, @@ -1833,20 +1911,25 @@ DC641C7B2821726F00862DCD /* FormattedAmount.swift in Sources */, DC641C77282171D200862DCD /* KotlinExtensions+Currency.swift in Sources */, DC641C762821716A00862DCD /* UserDefaults+Serialization.swift in Sources */, + DCCFE6BF2B713FBB002FFF11 /* LogFileManager.swift in Sources */, DCF9CFD52862656E001AD33F /* Asserts.swift in Sources */, DC641C7C282172BB00862DCD /* DelayedSave.swift in Sources */, DCA6DECE282AB12B0073C658 /* SecurityFile.swift in Sources */, DC32FB3529A3D3FE009912AC /* XpcManager.swift in Sources */, + DCCFE6BE2B713FB8002FFF11 /* LogFileInfo.swift in Sources */, DC49FE9C2AC49E0400D8D2E2 /* KotlinExtensions+Lightning.swift in Sources */, DC6ACC592B10F4FE0079179B /* RecoveryPhrase.swift in Sources */, DCA6DEC72829BFD70073C658 /* CrossProcessCommunication.swift in Sources */, DC641C7428208BD600862DCD /* String+VersionComparison.swift in Sources */, DCA6DEC92829C3180073C658 /* GenericPasswordConvertible.swift in Sources */, + DCCFE6A72B630836002FFF11 /* KotlinLogger.swift in Sources */, DCEB2797282D7ADC0096B87E /* KotlinFlow.swift in Sources */, DC641C78282171EA00862DCD /* KotlinAssociatedObject.swift in Sources */, + DCCFE6B32B680DF5002FFF11 /* LoggerFactory.swift in Sources */, DCA6DECA2829C31B0073C658 /* KeyStoreError.swift in Sources */, DC49FE9D2AC49E0800D8D2E2 /* KotlinExtensions+Bitcoin.swift in Sources */, DC422F3629392C0000E72253 /* Int+ToDate.swift in Sources */, + DCCFE6C52B714226002FFF11 /* LoggerFactory+Background.swift in Sources */, DC641C83282189AC00862DCD /* Utils.swift in Sources */, DC0D2EA8293928E100284608 /* KotlinExtensions+Payments.swift in Sources */, ); @@ -2376,6 +2459,14 @@ minimumVersion = 0.0.2; }; }; + DCCFE6A92B6430AB002FFF11 /* XCRemoteSwiftPackageReference "swift-log" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/apple/swift-log.git"; + requirement = { + kind = upToNextMinorVersion; + minimumVersion = 1.5.4; + }; + }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ @@ -2414,6 +2505,16 @@ package = DCA5391729F1DAA3001BD3D5 /* XCRemoteSwiftPackageReference "SwiftySegmentedPicker" */; productName = SegmentedPicker; }; + DCCFE6AA2B6430AB002FFF11 /* Logging */ = { + isa = XCSwiftPackageProductDependency; + package = DCCFE6A92B6430AB002FFF11 /* XCRemoteSwiftPackageReference "swift-log" */; + productName = Logging; + }; + DCCFE6B62B682E22002FFF11 /* Logging */ = { + isa = XCSwiftPackageProductDependency; + package = DCCFE6A92B6430AB002FFF11 /* XCRemoteSwiftPackageReference "swift-log" */; + productName = Logging; + }; /* End XCSwiftPackageProductDependency section */ }; rootObject = 7555FF73242A565900829871 /* Project object */; diff --git a/phoenix-ios/phoenix-ios.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/phoenix-ios/phoenix-ios.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index e7ec914d7..871b8ce39 100644 --- a/phoenix-ios/phoenix-ios.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/phoenix-ios/phoenix-ios.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -126,6 +126,15 @@ "version" : "2.1.1" } }, + { + "identity" : "swift-log", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-log.git", + "state" : { + "revision" : "e97a6fcb1ab07462881ac165fdbb37f067e205d5", + "version" : "1.5.4" + } + }, { "identity" : "swift-protobuf", "kind" : "remoteSourceControl", diff --git a/phoenix-ios/phoenix-ios/AppDelegate.swift b/phoenix-ios/phoenix-ios/AppDelegate.swift index 7a4ac76ed..8e8c03cbf 100644 --- a/phoenix-ios/phoenix-ios/AppDelegate.swift +++ b/phoenix-ios/phoenix-ios/AppDelegate.swift @@ -1,17 +1,14 @@ import UIKit import PhoenixShared -import os.log import Firebase import Combine import BackgroundTasks +fileprivate let filename = "AppDelegate" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "AppDelegate" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif diff --git a/phoenix-ios/phoenix-ios/MVI/MVI+Mock.swift b/phoenix-ios/phoenix-ios/MVI/MVI+Mock.swift index aa72b11d9..c14852d0f 100644 --- a/phoenix-ios/phoenix-ios/MVI/MVI+Mock.swift +++ b/phoenix-ios/phoenix-ios/MVI/MVI+Mock.swift @@ -21,9 +21,6 @@ extension View { func mock(_ mock: Initialization.Model) -> some View { environment(\.controllerFactory, MockControllerFactory(mock)) } - func mock(_ mock: LogsConfiguration.Model) -> some View { - environment(\.controllerFactory, MockControllerFactory(mock)) - } func mock(_ mock: Receive.Model) -> some View { environment(\.controllerFactory, MockControllerFactory(mock)) } @@ -119,18 +116,6 @@ class MockControllerFactory : ControllerFactory { } } - var mock_logsConfiguration: LogsConfiguration.Model? = nil - init(_ mock: LogsConfiguration.Model) { - mock_logsConfiguration = mock - } - func logsConfiguration() -> MVIController { - if let mock = mock_logsConfiguration { - return MVIControllerMock(model: mock) - } else { - return base.logsConfiguration() - } - } - var mock_receive: Receive.Model? = nil init(_ mock: Receive.Model) { mock_receive = mock diff --git a/phoenix-ios/phoenix-ios/MVI/MVI.swift b/phoenix-ios/phoenix-ios/MVI/MVI.swift index 06a0c0656..f5a9e0a89 100644 --- a/phoenix-ios/phoenix-ios/MVI/MVI.swift +++ b/phoenix-ios/phoenix-ios/MVI/MVI.swift @@ -1,18 +1,14 @@ import SwiftUI import PhoenixShared import Combine -import os.log +fileprivate let filename = "MVI" #if DEBUG && false -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "MVI" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - class MVIState: ObservableObject { private var _initialModel: Model? = nil @@ -262,11 +258,6 @@ class FakeControllerFactory: ControllerFactory { fatalError("Missing @Environment: ControllerFactory") } - func logsConfiguration() -> - MVIController { - fatalError("Missing @Environment: ControllerFactory") - } - func receive() -> MVIController { fatalError("Missing @Environment: ControllerFactory") diff --git a/phoenix-ios/phoenix-ios/SceneDelegate.swift b/phoenix-ios/phoenix-ios/SceneDelegate.swift index f6bc5bd2d..2b9de58c5 100644 --- a/phoenix-ios/phoenix-ios/SceneDelegate.swift +++ b/phoenix-ios/phoenix-ios/SceneDelegate.swift @@ -1,15 +1,13 @@ import UIKit import SwiftUI import Combine -import os.log + +fileprivate let filename = "SceneDelegate" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "SceneDelegate" -) +fileprivate let log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif class SceneDelegate: UIResponder, UIWindowSceneDelegate { diff --git a/phoenix-ios/phoenix-ios/extensions/String+Substring.swift b/phoenix-ios/phoenix-ios/extensions/String+Substring.swift new file mode 100644 index 000000000..08ba0e566 --- /dev/null +++ b/phoenix-ios/phoenix-ios/extensions/String+Substring.swift @@ -0,0 +1,15 @@ +import Foundation + +extension String { + + /// Getting the substring of a String in Swift is complete insanity. + /// This function works like substring in most other languages. + /// + func substring(location: Int, length: Int? = nil) -> String { + let start = min(max(0, location), self.count) + let limitedLength = min(self.count - start, length ?? Int.max) + let from = index(startIndex, offsetBy: start) + let to = index(startIndex, offsetBy: start + limitedLength) + return String(self[from.. (String, String) { + + // The tag is something like: + // - "fr.acinq.lightning.blockchain.electrum.ElectrumWatcher" + // - "fr.acinq.phoenix.managers.CurrencyManager" + // + // We want to split this into something like: + // - ("lightning-kmp", "ElectrumWatcher") + // - ("phoenix-kmp", "CurrencyManager") + // + // So there's a clear: (module, filename) + + if let idx = tag.lastIndex(of: ".") { + let idxPlusOne = tag.index(after: idx) + if idxPlusOne != tag.endIndex { + let subsystem = tag.prefix(upTo: idx) + let filename = String(tag.suffix(from: idxPlusOne)) + + if subsystem.hasPrefix("fr.acinq.lightning") { + return ("lightning-kmp", filename) + } else if subsystem.hasPrefix("fr.acinq.phoenix") { + return ("phoenix-kmp", filename) + } else { + return (String(subsystem), filename) + } + } + } + + return ("", tag) + } + + private func getLogger(_ tag: String) -> Logger { + lock.locked { + if let cachedLogger = loggers[tag] { + return cachedLogger + } + + let (module, filename) = self.splitTag(tag) + let newLogger = LoggerFactory.shared.logger(module: module, filename: filename, level: .trace) + loggers[tag] = newLogger + + return newLogger + } + } + + public func logger(_ severity: Kermit_coreSeverity, _ msg: String, _ tag: String) -> Void { + + let logger = getLogger(tag) + switch severity { + case Kermit_coreSeverity.verbose : logger.trace("\(msg)") + case Kermit_coreSeverity.debug : logger.debug("\(msg)") + case Kermit_coreSeverity.info : logger.info("\(msg)") + case Kermit_coreSeverity.warn : logger.warning("\(msg)") + case Kermit_coreSeverity.error : logger.error("\(msg)") + case Kermit_coreSeverity.assert : logger.error("\(msg)") + default : logger.notice("\(msg)") + } + } +} diff --git a/phoenix-ios/phoenix-ios/kotlin/KotlinObservables.swift b/phoenix-ios/phoenix-ios/kotlin/KotlinObservables.swift index 53f7246c4..9f3dc4e0b 100644 --- a/phoenix-ios/phoenix-ios/kotlin/KotlinObservables.swift +++ b/phoenix-ios/phoenix-ios/kotlin/KotlinObservables.swift @@ -1,18 +1,14 @@ import Foundation import Combine import PhoenixShared -import os.log +fileprivate let filename = "KotlinObservables" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "KotlinObservables" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - class ObservableConnectionsMonitor: ObservableObject { @Published var connections: Connections diff --git a/phoenix-ios/phoenix-ios/kotlin/KotlinPublishers+Lightning.swift b/phoenix-ios/phoenix-ios/kotlin/KotlinPublishers+Lightning.swift index cd2c47870..f7ce1f887 100644 --- a/phoenix-ios/phoenix-ios/kotlin/KotlinPublishers+Lightning.swift +++ b/phoenix-ios/phoenix-ios/kotlin/KotlinPublishers+Lightning.swift @@ -1,15 +1,12 @@ import Foundation import Combine import PhoenixShared -import os.log +fileprivate let filename = "KotlinPublishers+Lightning" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "KotlinPublishers+Lightning" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif extension Lightning_kmpPeer { diff --git a/phoenix-ios/phoenix-ios/kotlin/KotlinPublishers+Phoenix.swift b/phoenix-ios/phoenix-ios/kotlin/KotlinPublishers+Phoenix.swift index 6616cd972..098420505 100644 --- a/phoenix-ios/phoenix-ios/kotlin/KotlinPublishers+Phoenix.swift +++ b/phoenix-ios/phoenix-ios/kotlin/KotlinPublishers+Phoenix.swift @@ -1,15 +1,12 @@ import Foundation import Combine import PhoenixShared -import os.log +fileprivate let filename = "KotlinPublishers+Phoenix" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "KotlinPublishers+Phoenix" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif extension PeerManager { diff --git a/phoenix-ios/phoenix-ios/kotlin/KotlinTypes.swift b/phoenix-ios/phoenix-ios/kotlin/KotlinTypes.swift index 46f5b4d00..a2e8ed90d 100644 --- a/phoenix-ios/phoenix-ios/kotlin/KotlinTypes.swift +++ b/phoenix-ios/phoenix-ios/kotlin/KotlinTypes.swift @@ -98,11 +98,3 @@ extension LnurlAuth { typealias Scheme_DEFAULT = LnurlAuth.SchemeDEFAULT_SCHEME typealias Scheme_ANDROID_LEGACY = LnurlAuth.SchemeANDROID_LEGACY_SCHEME } - -extension LogsConfiguration { - typealias Model_Awaiting = ModelAwaiting - typealias Model_Exporting = ModelExporting - typealias Model_Ready = ModelReady - - typealias Intent_Export = IntentExport -} diff --git a/phoenix-ios/phoenix-ios/logging/LoggerFactory+Background.swift b/phoenix-ios/phoenix-ios/logging/LoggerFactory+Background.swift new file mode 100644 index 000000000..99ab59429 --- /dev/null +++ b/phoenix-ios/phoenix-ios/logging/LoggerFactory+Background.swift @@ -0,0 +1,9 @@ +import Foundation + +/// This file is **ONLY** for the Notify-Service-Extension (background process) +/// +extension LoggerFactory { + class var friendlyProcessName: String { + return friendlyProcessName_background + } +} diff --git a/phoenix-ios/phoenix-ios/logging/LoggerFactory+Foreground.swift b/phoenix-ios/phoenix-ios/logging/LoggerFactory+Foreground.swift new file mode 100644 index 000000000..697e9842a --- /dev/null +++ b/phoenix-ios/phoenix-ios/logging/LoggerFactory+Foreground.swift @@ -0,0 +1,9 @@ +import Foundation + +/// This file is **ONLY** for the main Phoenix app +/// +extension LoggerFactory { + class var friendlyProcessName: String { + return friendlyProcessName_foreground + } +} diff --git a/phoenix-ios/phoenix-ios/logging/LoggerFactory.swift b/phoenix-ios/phoenix-ios/logging/LoggerFactory.swift new file mode 100644 index 000000000..39aa63a18 --- /dev/null +++ b/phoenix-ios/phoenix-ios/logging/LoggerFactory.swift @@ -0,0 +1,146 @@ +import Foundation +import Logging + +class LoggerFactory { + + static let shared = LoggerFactory() + + private let logFileManager: LogFileManager + + private init() { // must use shared instance + + let logsDir = try! LoggerFactory.logsDirectory() + let formatter = LoggerFactory.formatter() + + logFileManager = LogFileManager( + logsDirectory: logsDir, + logFilePrefix: LoggerFactory.logFilePrefix, + rollingConfig: LogFileManager.RollingConfiguration( + maximumFileSize: 1024 * 1024 * 2, // 2 MiB, + rollingFrequency: 60 * 60 * 24, // 24 hours, + rollOnAppLaunch: false // allow log files to span app launches + ), + cleanupConfig: LogFileManager.CleanupConfiguration( + maximumNumberOfLogFiles: 8, // 8 archived log files (+ current log file) + logFilesDiskQuota: 1024 * 1024 * 20 // 20 MiB + ), + formatter: formatter + ) + + logFileManager.prepare() + } + + class var friendlyProcessName_foreground: String { + return "Phoenix" + } + + class var friendlyProcessName_background: String { + return "NotifySrvExt" + } + + class var logFilePrefix: String { + return "\(self.friendlyProcessName)-" + } + + class func logsDirectory() throws -> URL { + + let sharedDir = FileManager.default.containerURL( + forSecurityApplicationGroupIdentifier: "group.co.acinq.phoenix" + )! + + let logsDir: URL + if #available(iOS 16.0, *) { + logsDir = sharedDir.appending(path: "logs", directoryHint: .isDirectory) + } else { + logsDir = sharedDir.appendingPathComponent("logs", isDirectory: true) + } + + try FileManager.default.createDirectory(at: logsDir, withIntermediateDirectories: true) + return logsDir + } + + class func formatter() -> LogFormatter { + + let pi = ProcessInfo.processInfo + let pid = pi.processIdentifier + let df = ISO8601DateFormatter() + + let formatter = {( + level: Logging.Logger.Level, + message: String, + module: String, + filename: String + ) -> String in + + let ts = df.string(from: Date.now) + let lvl = level.logFileAbbreviation + let tid = Thread.currentThreadID + + return "[\(ts)] [\(pid):\(tid)] [\(module)/\(filename)] [\(lvl)] \(message)" + } + + return formatter + } + + func handler(module: String, filename: String) -> LogHandler { + + let osLogHandler = OSLogHandler(module: module, filename: filename) + let fileHandler = LogFileHandler(module: module, filename: filename, logFileManager: logFileManager) + + return MultiplexLogHandler([osLogHandler, fileHandler]) + } + + func logger(module: String, filename: String, level: Logger.Level) -> Logger { + + // the Logger's label works similarly to a DispatchQueue label + let label = "\(module)/\(filename)" + + var logger = Logger(label: label) { _ in + handler(module: module, filename: filename) + } + logger.logLevel = level + return logger + } + + func logger(_ filename: String, _ level: Logger.Level) -> Logger { + return logger(module: "swift", filename: filename, level: level) + } +} + +extension Logging.Logger.Level { + var logFileAbbreviation: String { + switch self { + case .trace : return "T" + case .debug : return "D" + case .info : return "I" + case .notice : return "N" + case .warning : return "W" + case .error : return "E" + case .critical : return "C" + } + } + + static func fromLogFileAbbreviation(_ str: String) -> Logging.Logger.Level? { + switch str { + case "T" : return .trace + case "D" : return .debug + case "I" : return .info + case "N" : return .notice + case "W" : return .warning + case "E" : return .error + case "C" : return .critical + default : return nil + } + } +} + +extension Thread { + class var currentThreadID: String { + var tid: __uint64_t = 0 + if (pthread_threadid_np(nil, &tid) == 0) { + return "\(tid)" + } else { + return "?" + } + } +} diff --git a/phoenix-ios/phoenix-ios/logging/OSLogHandler.swift b/phoenix-ios/phoenix-ios/logging/OSLogHandler.swift new file mode 100644 index 000000000..0a09db648 --- /dev/null +++ b/phoenix-ios/phoenix-ios/logging/OSLogHandler.swift @@ -0,0 +1,65 @@ +import Foundation +import Logging +import os.log + +struct OSLogHandler: LogHandler { + + private let logger: os.Logger + + init(module: String, filename: String) { + logger = Logger(subsystem: module, category: filename) + } + + public var logLevel: Logging.Logger.Level = .trace + + public var metadata = Logger.Metadata() { + didSet { + self.prettyMetadata = self.prettify(self.metadata) + } + } + + public subscript(metadataKey metadataKey: String) -> Logging.Logger.Metadata.Value? { + get { self.metadata[metadataKey] } + set { self.metadata[metadataKey] = newValue } + } + + private var prettyMetadata: String? + private func prettify(_ metadata: Logging.Logger.Metadata) -> String? { + guard !metadata.isEmpty else { + return nil + } + return metadata.map { "\($0)=\($1)" }.joined(separator: ", ") + } + + public func log( + level: Logging.Logger.Level, + message: Logging.Logger.Message, + metadata: Logging.Logger.Metadata?, + file: String, + function: String, + line: UInt + ){ + if let pm = prettyMetadata { + switch level { + case .trace : logger.trace("{\(pm)} \(message.description)") + case .debug : logger.debug("{\(pm)} \(message.description)") + case .info : logger.info("{\(pm)} \(message.description)") + case .notice : logger.notice("{\(pm)} \(message.description)") + case .warning : logger.warning("{\(pm)} \(message.description)") + case .error : logger.error("{\(pm)} \(message.description)") + case .critical : logger.critical("{\(pm)} \(message.description)") + } + + } else { + switch level { + case .trace : logger.trace("\(message.description)") + case .debug : logger.debug("\(message.description)") + case .info : logger.info("\(message.description)") + case .notice : logger.notice("\(message.description)") + case .warning : logger.warning("\(message.description)") + case .error : logger.error("\(message.description)") + case .critical : logger.critical("\(message.description)") + } + } + } +} diff --git a/phoenix-ios/phoenix-ios/logging/fileLogging/LogFileHandler.swift b/phoenix-ios/phoenix-ios/logging/fileLogging/LogFileHandler.swift new file mode 100644 index 000000000..c08e7c569 --- /dev/null +++ b/phoenix-ios/phoenix-ios/logging/fileLogging/LogFileHandler.swift @@ -0,0 +1,59 @@ +import Foundation +import Logging + +struct LogFileHandler: LogHandler { + + let module: String + let filename: String + let logFileManager: LogFileManager + + init(module: String, filename: String, logFileManager: LogFileManager) { + self.module = module + self.filename = filename + self.logFileManager = logFileManager + } + + public var logLevel: Logging.Logger.Level = .trace + + public var metadata = Logger.Metadata() { + didSet { + self.prettyMetadata = self.prettify(self.metadata) + } + } + + public subscript(metadataKey metadataKey: String) -> Logging.Logger.Metadata.Value? { + get { self.metadata[metadataKey] } + set { self.metadata[metadataKey] = newValue } + } + + private var prettyMetadata: String? + private func prettify(_ metadata: Logging.Logger.Metadata) -> String? { + guard !metadata.isEmpty else { + return nil + } + return metadata.map { "\($0)=\($1)" }.joined(separator: ", ") + } + + public func log( + level: Logging.Logger.Level, + message: Logging.Logger.Message, + metadata: Logging.Logger.Metadata?, + file: String, + function: String, + line: UInt + ){ + let msg: String + if let pm = prettyMetadata { + msg = "{\(pm)} \(message.description)" + } else { + msg = message.description + } + + logFileManager.log( + level: level, + message: msg, + module: module, + filename: filename + ) + } +} diff --git a/phoenix-ios/phoenix-ios/logging/fileLogging/LogFileInfo.swift b/phoenix-ios/phoenix-ios/logging/fileLogging/LogFileInfo.swift new file mode 100644 index 000000000..ad8f3e756 --- /dev/null +++ b/phoenix-ios/phoenix-ios/logging/fileLogging/LogFileInfo.swift @@ -0,0 +1,70 @@ +import Foundation + +/// A simple wrapper around a logFile item. +/// +/// The resourceValues (such as `fileSize`) are snapshots taken from the +/// filesystem (and do not automatically update). +/// +struct LogFileInfo { + + let url: URL + let resourceValues: URLResourceValues + + init(url: URL, resourceValues: URLResourceValues) { + self.url = url + self.resourceValues = resourceValues + } + + init?(url: URL) { + do { + self.url = url + self.resourceValues = try url.resourceValues(forKeys: LogFileInfo.resourceValueKeys()) + } catch { + return nil + } + } + + var fileName: String { + get { url.lastPathComponent } + } + + var fileSize: Int? { + get { resourceValues.fileSize } + } + + var creationDate: Date? { + get { resourceValues.creationDate } + } + + var age: TimeInterval? { + get { + if let date = self.creationDate { + return date.timeIntervalSinceNow * -1.0 + } else { + return nil + } + } + } + + static func resourceValueKeys() -> Set { + return Set([.fileSizeKey, .creationDateKey]) + } + + /// Returns true if `lhs.creationDate < rhs.creationDate`, false otherwise. + /// + static func sortedByCreationDate(lhs: LogFileInfo, rhs: LogFileInfo) -> Bool { + + let lcd = lhs.creationDate + let rcd = rhs.creationDate + + if let lcd, let rcd { + return lcd < rcd + } else { + // if any creationDate is nil, we assume distantPast: + // * lcd(non-nil) < nil => false + // * nil < rcd(non-nil) => true + // * nil < nil => false (they're equal) + return rcd != nil + } + } +} diff --git a/phoenix-ios/phoenix-ios/logging/fileLogging/LogFileManager.swift b/phoenix-ios/phoenix-ios/logging/fileLogging/LogFileManager.swift new file mode 100644 index 000000000..7a58e06c8 --- /dev/null +++ b/phoenix-ios/phoenix-ios/logging/fileLogging/LogFileManager.swift @@ -0,0 +1,751 @@ +/** + * Inspired by CocoaLumberjack's DDFileLogger, + * which I wrote a long time ago in Objective-C. + */ + +import Foundation +import Logging +import os.log + +/// If the LogsFileManager itself encounters errors, we log them directly to OSLog. +/// So this is our internal logging mechanism. +/// +fileprivate let ilog = Logger( + subsystem: Bundle.main.bundleIdentifier!, + category: "LogFileManager" +) + +typealias LogFormatter = ( + _ /* level */: Logging.Logger.Level, + _ /* message */: String, + _ /* module */: String, + _ /* filename */: String +) -> String + +/// The LogFileManager is the primary configuration & logic for a group of LogFileHandlers. +/// +/// Normally a single LogFileManager instance is shared between ALL LogFileHandler instances. +/// This is because you want all logs from all parts of the app going to the same logFile. +/// +/// However, there are times when you might want separate LogFileManager instances. +/// For example, your app might be split into the main iOS app, and a bundled app-extension. +/// In this case, you probably want separate logs for the app-extension. +/// +/// Another example is if your app is split into modules, and you want separate logs for each module. +/// +/// To accomplish this, make sure you either: +/// - use a different `logsDirectory` for each LogFileManager instance +/// - or alternatively, set a different `logFilePrefix` for each LogFileManager instance +/// +class LogFileManager { + + /// ### Log File Rolling: + /// + /// When your application is running, and messages are being streamed to the logFile, + /// there comes a time when you want to close the logFile and create a new one. + /// This is called "rolling" the log file, and there are several configuration options + /// to control when that happens. + /// + /// Both `maximumFileSize` and `rollingFrequency` are used to manage rolling during runtime. + /// That is, whichever occurs first will cause the log file to be rolled. + /// + /// For example: + /// The `rollingFrequency` is set to 24 hours, + /// but the log file surpasses the configured `maximumFileSize` after only 20 hours. + /// The log file will be rolled at that 20 hour mark. + /// A new log file will be created, and the 24 hour timer will be restarted. + /// + struct RollingConfiguration { + + /// The approximate maximum size (in bytes) to allow log files to grow. + /// If a log file is larger than this value after a log statement is appended, + /// then the log file is rolled. + /// + /// The default value is 1 MiB. + /// You may optionally disable this option by setting it to zero. + /// + let maximumFileSize: UInt64 + + /// How often to roll the log file. + /// The frequency is given as a `TimeInterval`, which is a Double that specifies the interval in seconds. + /// Once the log file gets to be this old, it is rolled. + /// + /// The default value is 24 hours. + /// You may optionally disable this option by setting it to zero (or a negative value). + /// + let rollingFrequency: TimeInterval + + /// When set, a new log file will be created each time the app is launched. + /// + /// Note that if you set this value to true, you'll likely need to compensate by increasing + /// the `cleanupConfig.maximumNumberOfLogFiles`, or you'll reduce the amount of log statements + /// your app has access to. + /// + /// The default value is false. + /// + let rollOnAppLaunch: Bool + + /// If you completely disable all rolling: + /// - maximumFileSize == 0 + /// - rollingFrequency == 0 + /// - rollOnAppLaunch = false + /// + /// This is considered a configuration error, your configuration options will be ignored, + /// and the system will fallback to using the default configuration (for system safety). + /// + var isInvalid: Bool { + return (maximumFileSize == 0) && (rollingFrequency <= 0) && (rollOnAppLaunch == false) + } + + func sanitized() -> RollingConfiguration { + return isInvalid ? RollingConfiguration.default : self + } + + static var `default`: RollingConfiguration { + RollingConfiguration( + maximumFileSize: 1024 * 1024, // 1 MiB + rollingFrequency: 60 * 60 * 24, // 24 hours + rollOnAppLaunch: false + ) + } + } + + /// #### Log file cleanup: + /// + /// As log files are rolled, you end up with a number of "archived" log files. + /// That is, older log files that are no longer being written to, + /// and contain log statements going back further in time the older the log file. + /// You likely don't want to keep these log files for forever, so there's a cleanup process, + /// with several configuration options to control how that happens. + /// + struct CleanupConfiguration { + + /// The maximum number of archived log files to keep on disk. + /// + /// For example, if this property is set to 3, then the LogFileManager will only + /// keep 3 archived log files (plus the current active log file) on disk. + /// Once the active log file is rolled/archived, then the oldest of the + /// existing 3 rolled/archived log files is deleted. + /// + /// The default value is 5. + /// You may optionally disable this option by setting it to zero (or a negative value). + /// + let maximumNumberOfLogFiles: Int + + /// The maximum space that logs can take (in bytes). + /// + /// After rolling a logfile, the total disk space is calculated by inspecting each archived logfile. + /// If the total exceeds the logFilesDiskQuota, then the oldest archived logFile will be deleted, + /// until the total is under the quota. + /// + /// The default value is 20 MiB. + /// You may optionally disable this option by setting it to zero. + /// + var logFilesDiskQuota: UInt64 + + /// If you completely disable all cleanup: + /// - maximumNumberOfLogFiles == 0 + /// - logFilesDiskQuota == 0 + /// + /// This is considered a configuration error, your configuration options will be ignored, + /// and the system will fallback to using the default configuration (for system safety). + /// + var isInvalid: Bool { + return (maximumNumberOfLogFiles <= 0) && (logFilesDiskQuota == 0) + } + + func sanitized() -> CleanupConfiguration { + return isInvalid ? CleanupConfiguration.default : self + } + + static var `default`: CleanupConfiguration { + CleanupConfiguration( + maximumNumberOfLogFiles: 5, + logFilesDiskQuota: 1024 * 1024 * 20 // 20 MiB + ) + } + } + + /// The directory where all the log files will be stored. + /// + let logsDirectory: URL + + /// An optional prefix for every logFile name. + /// + /// By default the logFile will be something like: "2024-03-11T20:04:11:452Z.log" + /// If you set the prefix to "MyApp-" then the name will be: "MyApp-2024-03-11T20:04:11:452Z.log" + /// + /// Important: + /// If you **share** a logsDirectory (either between multiple apps, or between an app & app extension), + /// then you should consider setting a logFilePrefix to ensure separate log files. + /// + let logFilePrefix: String? + + /// The formatter defines how you want log messages to appear in the log file. + /// + let formatter: LogFormatter + + /// Serial queues ensures that only one operation is in-flight at any given time. + /// + private let loggingQueue = DispatchQueue(label: "LogFileManager.logging") + private let cleanupQueue = DispatchQueue(label: "LogFileManager.cleanup") + + private var _rollingConfig: RollingConfiguration + private var _cleanupConfig: CleanupConfiguration + + private var _currentLogFileInfo: LogFileInfo? = nil + private var _currentLogFileHandle: FileHandle? = nil + private var _currentLogFileVnode: DispatchSourceFileSystemObject? = nil + + private var _rollingTimer: DispatchSourceTimer? = nil + + private static let rollingLeewaySeconds: Int = 1 + + /// Normally a single LogFileManager instance is shared between ALL LogFileHandler instances. + /// This is because you want all logs from all parts of the app going to the same logFile. + /// + /// However, there are times when you might want separate LogFileManager instance. + /// For example, your app might be split into the main iOS app, and a bundled app-extension. + /// In this case, you probably want separate logs for the app-extension. + /// + /// Another example is if your app is split into modules, and you want separate logs for each module. + /// + /// To accomplish this, make sure you either: + /// - use a different `logsDirectory` for each LogFileManager instance + /// - or alternatively, set a different `logFilePrefix` for each LogFileManager instance + /// + init( + logsDirectory: URL, + logFilePrefix: String? = nil, + rollingConfig: RollingConfiguration, + cleanupConfig: CleanupConfiguration, + formatter: @escaping LogFormatter + ) { + self.logsDirectory = logsDirectory + self.logFilePrefix = logFilePrefix + self._rollingConfig = rollingConfig.sanitized() + self._cleanupConfig = cleanupConfig.sanitized() + self.formatter = formatter + + ilog.debug("logsDirectory: \(logsDirectory.path)") + } + + // -------------------------------------------------- + // MARK: Public + // -------------------------------------------------- + + var rollingConfig: RollingConfiguration { + get { + loggingQueue.sync { + self._rollingConfig + } + } + set { + loggingQueue.async { + let oldConfig = self._rollingConfig + let newConfig = newValue.sanitized() + self._rollingConfig = newConfig + if oldConfig.maximumFileSize != newConfig.maximumFileSize { + self.maybeRollLogFileDueToSize() + } + if oldConfig.rollingFrequency != newConfig.rollingFrequency { + self.maybeRollLogFileDueToAge() + } + } + } + } + + var cleanupConfig: CleanupConfiguration { + get { + cleanupQueue.sync { + self._cleanupConfig + } + } + set { + cleanupQueue.async { + let oldConfig = self._cleanupConfig + let newConfig = newValue.sanitized() + self._cleanupConfig = newConfig + if oldConfig.maximumNumberOfLogFiles != newConfig.maximumNumberOfLogFiles || + oldConfig.logFilesDiskQuota != newConfig.logFilesDiskQuota + { + self.deleteOldLogFiles() + } + } + } + } + + /// This method may optionally be called to prep the LogFileManager for use. + /// Ideally, you would call this after initializing the instance, + /// and after setting the desired configuration values. + /// + /// Calling this function allows it to start some disk IO processes that + /// are required before it can start writing log statements to disk, such as: + /// + /// - checking the logsDirectory for existing log files + /// - comparing timestamps of logFile entries + /// - possibly creating a new logFile for use + /// - opening the appropriate logFile for writing + /// + func prepare() { + + loggingQueue.async { + let _ = try? self.currentLogFileHandle() + } + } + + /// Returns an array of `LogFileInfo` objects, + /// each representing an existing log file on disk, + /// and containing information about the log file such as it's size & creation date. + /// + /// The items in the array are sorted by creation date. + /// The first item in the array will be the most recently created log file. + /// + func sortedLogFiles() -> [LogFileInfo] { + + let keys = LogFileInfo.resourceValueKeys() + let options: FileManager.DirectoryEnumerationOptions = [ + .skipsHiddenFiles, + .skipsPackageDescendants, + .skipsSubdirectoryDescendants + ] + + do { + let allUrls = try FileManager.default.contentsOfDirectory( + at: logsDirectory, + includingPropertiesForKeys: Array(keys), + options: options + ) + + return allUrls + .filter { self.isLogFile($0) } + .compactMap { LogFileInfo(url: $0) } + .sorted { LogFileInfo.sortedByCreationDate(lhs: $0, rhs: $1) } + .reversed() + + } catch { + return [] + } + } + + func log( + level: Logging.Logger.Level, + message: String, + module: String, + filename: String + ) { + + var string: String = formatter(level, message, module, filename) + loggingQueue.sync { + if !string.hasSuffix("\n") { + string.append("\n") + } + if let data = string.data(using: .utf8) { + self.logData(data) + } + } + } + + // -------------------------------------------------- + // MARK: Naming + // -------------------------------------------------- + + private func isLogFile(_ url: URL) -> Bool { + + let filename = url.lastPathComponent + + if let logFilePrefix { + if !filename.hasPrefix(logFilePrefix) { + return false + } + } + + return filename.hasSuffix(".log") + } + + private func newLogFileBaseName() -> String { + + let formattedDate = ISO8601DateFormatter().string(from: Date.now) + + if let logFilePrefix { + return "\(logFilePrefix)\(formattedDate)" + } else { + return formattedDate + } + } + + // -------------------------------------------------- + // MARK: Internals + // -------------------------------------------------- + + /// This method is called on the `loggingQueue` + /// + private func createNewLogFile() throws -> URL { + + // This method is called on the `loggingQueue` + + let baseFileName = newLogFileBaseName() + + var attempt = 1 + var errorCount = 0 + let MAX_ERROR_COUNT = 5 + + while true { + + let fileName: String + if attempt == 1 { + fileName = "\(baseFileName).log" + } else { + fileName = "\(baseFileName) \(attempt).log" + } + + let fileUrl: URL + if #available(iOS 16.0, *) { + fileUrl = logsDirectory.appending(path: fileName, directoryHint: .notDirectory) + } else { + fileUrl = logsDirectory.appendingPathComponent(fileName, isDirectory: false) + } + + do { + let options: Data.WritingOptions = .withoutOverwriting + try Data().write(to: fileUrl, options: options) + + cleanupQueue.async { + self.deleteOldLogFiles() + } + return fileUrl + + } catch { + attempt += 1 + errorCount += 1 + + if (errorCount >= MAX_ERROR_COUNT) { + ilog.error("Cannot create log file: \(error)") + throw error + } + } + } + } + + /// This method is called on the `loggingQueue` + /// + private func canReuse(_ logFile: LogFileInfo) -> Bool { + + let config = _rollingConfig + if config.rollOnAppLaunch { + return false + } + + if let size = logFile.fileSize { + if size >= config.maximumFileSize { + return false + } + } + + if let age = logFile.age { + if age >= config.rollingFrequency { + return false + } + } + + return true + } + + /// This method is called on the `loggingQueue` + /// + private func currentLogFileInfo() throws -> LogFileInfo { + + // This method is called on the `loggingQueue` + + if let currentLogFileInfo = _currentLogFileInfo { + return currentLogFileInfo + } + + // Possible situations: + // + // 1. Starting the app fresh + // Which means we want to check and see if we can continue writing to the old log file. + // + // 2. We just rolled the last log file + // If we're sharing the log files between multiple processes, + // then we want to check the disk, and see if there's a new logFile we should be using. + // + if let mostRecentLogFileInfo = sortedLogFiles().first { + if canReuse(mostRecentLogFileInfo) { + _currentLogFileInfo = mostRecentLogFileInfo + return mostRecentLogFileInfo + } + } + + let newLogFileUrl = try createNewLogFile() + + let keys = LogFileInfo.resourceValueKeys() + let resourceValues = try newLogFileUrl.resourceValues(forKeys: keys) + + let newLogFileInfo = LogFileInfo(url: newLogFileUrl, resourceValues: resourceValues) + + _currentLogFileInfo = newLogFileInfo + return newLogFileInfo + } + + /// This method is called on the `loggingQueue` + /// + private func currentLogFileHandle() throws -> FileHandle { + + // This method is called on the `loggingQueue` + + if let currentLogFileHandle = _currentLogFileHandle { + return currentLogFileHandle + } + + let logFileInfo = try currentLogFileInfo() + + let logFileHandle = try FileHandle(forWritingTo: logFileInfo.url) + let _ = try logFileHandle.seekToEnd() + + _currentLogFileHandle = logFileHandle + + scheduleTimerToRollLogFileDueToAge() + monitorCurrentLogFileForExternalChanges() + + return logFileHandle + } + + /// This method is called on the `loggingQueue` + /// + private func logData(_ data: Data) { + + if data.isEmpty { + return + } + + guard let handle = try? currentLogFileHandle() else { + return + } + + let fd = handle.fileDescriptor + while(flock(fd, LOCK_EX) != 0) { + // log.debug("Could not lock logfile, retrying in 1ms: \(errno): \(strerror(errno))") + usleep(1000) + } + + do { + try handle.seekToEnd() + try handle.write(contentsOf: data) + } catch { + ilog.error("Error writing to logFile: \(error)") + } + + flock(fd, LOCK_UN) + maybeRollLogFileDueToSize() + } + + // -------------------------------------------------- + // MARK: Rolling + // -------------------------------------------------- + + /// This method is called on the `loggingQueue` + /// + private func scheduleTimerToRollLogFileDueToAge() { + + if let timer = _rollingTimer { + timer.cancel() + _rollingTimer = nil + } + + guard let logFileInfo = _currentLogFileInfo else { + ilog.warning("scheduleTimerToRollLogFileDueToAge: currentLogFileInfo is nil; cannot proceed") + return + } + + let config = _rollingConfig + if config.rollingFrequency <= 0.0 { + return + } + + var delay = config.rollingFrequency + if let creationDate = logFileInfo.creationDate { + let rollingDate = creationDate.addingTimeInterval(config.rollingFrequency) + delay = rollingDate.timeIntervalSinceNow + // ^^ could be negative, but that's not a problem (timer fires right away) + } + + let timer = DispatchSource.makeTimerSource(flags: [], queue: loggingQueue) + timer.setEventHandler { [weak self] in + self?.maybeRollLogFileDueToAge() + } + + timer.schedule( + deadline: DispatchTime.now() + delay, + repeating: .never, + leeway: DispatchTimeInterval.seconds(LogFileManager.rollingLeewaySeconds) + ) + + _rollingTimer = timer + timer.activate() + } + + /// This method is called on the `loggingQueue` + /// + private func maybeRollLogFileDueToAge() { + + guard let logFileInfo = _currentLogFileInfo else { + // No current log file, so nothing to roll right now. + // This might happen if called before we've started logging (common), + // or if called just after rolling a log file (but before the next log statement). + return + } + + let config = _rollingConfig + if config.rollingFrequency <= 0.0 { + return + } + + let leeway = Double(LogFileManager.rollingLeewaySeconds) + if let age = logFileInfo.age, (age + leeway) >= config.rollingFrequency { + ilog.info("Rolling log file due to age (\(age))...") + rollLogFileNow() + } else { + scheduleTimerToRollLogFileDueToAge() + } + } + + /// This method is called on the `loggingQueue` + /// + private func maybeRollLogFileDueToSize() { + + guard let logFileHandle = _currentLogFileHandle else { + // No current log file, so nothing to roll right now. + // This might happen if called before we've started logging (common), + // or if called just after rolling a log file (but before the next log statement). + return + } + + let config = _rollingConfig + if config.maximumFileSize == 0 { + return + } + + var fileSize: UInt64 = 0 + do { + fileSize = try logFileHandle.offset() + } catch { + ilog.error("maybeRollLogFileDueToSize: Cannot get logFileHandle.offset: \(error)") + } + + if fileSize >= config.maximumFileSize { + ilog.info("Rolling log file due to size (\(fileSize))...") + rollLogFileNow() + } + } + + /// This method is called on the `loggingQueue` + /// + private func monitorCurrentLogFileForExternalChanges() { + + if let logFileVnode = _currentLogFileVnode { + logFileVnode.cancel() + _currentLogFileVnode = nil + } + + guard let logFileHandle = _currentLogFileHandle else { + return + } + + let logFileVnode = DispatchSource.makeFileSystemObjectSource( + fileDescriptor: logFileHandle.fileDescriptor, + eventMask: [.delete, .rename, .revoke], + queue: loggingQueue + ) + + logFileVnode.setEventHandler { [weak self] in + ilog.info("Rolling log file - current was deleted/renamed externally...") + self?.rollLogFileNow() + } + + _currentLogFileVnode = logFileVnode + logFileVnode.activate() + } + + /// This method is called on the `loggingQueue` + /// + private func rollLogFileNow() { + + guard let logFileHandle = _currentLogFileHandle else { + return + } + + do { + try logFileHandle.synchronize() + } catch { + ilog.error("Failed to synchronize file: \(error)") + } + + do { + try logFileHandle.close() + } catch { + ilog.error("Failed to close file: \(error)") + } + + _currentLogFileHandle = nil + _currentLogFileInfo = nil + + if let vnode = _currentLogFileVnode { + vnode.cancel() + _currentLogFileVnode = nil + } + + if let timer = _rollingTimer { + timer.cancel() + _rollingTimer = nil + } + } + + // -------------------------------------------------- + // MARK: Cleanup + // -------------------------------------------------- + + /// This method is called on the `cleanupQueue` + /// + private func deleteOldLogFiles() { + + let allLogFiles = self.sortedLogFiles() + // ^ sorted by creation date, with index 0 being the current log file + let candidateLogFiles = allLogFiles.isEmpty ? allLogFiles : Array(allLogFiles[1...]) + + let config = _cleanupConfig + var firstIndexToDelete: Int? = nil + + if config.logFilesDiskQuota > 0 { + var used: UInt64 = 0 + for (index, logFile) in candidateLogFiles.enumerated() { + used += UInt64(logFile.fileSize ?? 0) + if (used > config.logFilesDiskQuota) { + firstIndexToDelete = index + break + } + } + } + + if config.maximumNumberOfLogFiles > 0 { + if let currentIndex = firstIndexToDelete { + firstIndexToDelete = min(currentIndex, config.maximumNumberOfLogFiles) + } else { + firstIndexToDelete = config.maximumNumberOfLogFiles + } + } + + if let firstIndexToDelete, firstIndexToDelete < candidateLogFiles.count { + // removing all log files starting with firstIndexToDelete + for i in (firstIndexToDelete ..< candidateLogFiles.count) { + let logFile = candidateLogFiles[i] + do { + ilog.info("Deleting log file: \(logFile.fileName)") + try FileManager.default.removeItem(at: logFile.url) + } catch { + ilog.error("Error deleting log file: \(error)") + } + } + } + } +} diff --git a/phoenix-ios/phoenix-ios/logging/fileLogging/LogFileParser.swift b/phoenix-ios/phoenix-ios/logging/fileLogging/LogFileParser.swift new file mode 100644 index 000000000..61c3b0e99 --- /dev/null +++ b/phoenix-ios/phoenix-ios/logging/fileLogging/LogFileParser.swift @@ -0,0 +1,259 @@ +import Foundation +import Logging + +fileprivate let filename = "LogFileParser" +#if DEBUG && true +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) +#else +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) +#endif + +/// A fully parsed log entry with all the data. +/// +struct LogFileEntry { + let raw: String // unparsed entry from log file + let timestamp: Date + let processID: Int32 + let threadID: UInt64 + let module: String + let filename: String + let level: Logging.Logger.Level + let message: String +} + +/// A lightly parsed log entry (for when you only need the timestamp). +/// +struct LogFileEntryTimestamp { + let raw: String // unparsed entry from LogFile + let timestamp: Date +} + + +class LogFileParser { + + /// An error may be thrown if there are IO errors when opening/reading the file. + /// Errors when attempting to parse particular log entries are ignored (but log messages are generated). + /// + static func fullParse(_ url: URL) async throws -> [LogFileEntry] { + + let rawEntries = try await parseRawEntries(url) + let df = ISO8601DateFormatter() + + var entries: [LogFileEntry] = [] + for rawEntry in rawEntries { + if let entry = parseEntry(rawEntry, df) { + entries.append(entry) + } + } + + return entries + } + + /// An error may be thrown if there are IO errors when opening/reading the file. + /// Errors when attempting to parse particular log entries are ignored (but log messages are generated). + /// + static func lightParse(_ url: URL) async throws -> [LogFileEntryTimestamp] { + + let rawEntries = try await parseRawEntries(url) + let df = ISO8601DateFormatter() + + var entries: [LogFileEntryTimestamp] = [] + for rawEntry in rawEntries { + if let entry = parseLightEntry(rawEntry, df) { + entries.append(entry) + } + } + + return entries + } + + private static func parseRawEntries(_ url: URL) async throws -> [String] { + + var rawEntries: [String] = [] + + var buffer: String = "" + for try await line in url.lines { + if line.hasPrefix("[") { + if !buffer.isEmpty { + rawEntries.append(buffer) + } + buffer = line + } else if !buffer.isEmpty { + buffer += line + } + } + + if !buffer.isEmpty { + rawEntries.append(buffer) + } + + return rawEntries + } + + private static func parseEntry( + _ string: String, + _ df: ISO8601DateFormatter + ) -> LogFileEntry? { + + var offset: String.Index = string.startIndex + guard let timestamp = parseTimestamp(string, df, &offset) else { + return nil + } + guard let (processID, threadID) = parseProcessThread(string, &offset) else { + return nil + } + guard let (module, filename) = parseModuleFilename(string, &offset) else { + return nil + } + guard let level = parseLevel(string, &offset) else { + return nil + } + + var msg = string.suffix(from: offset) + if msg.hasPrefix(" ") { + msg = msg.suffix(from: msg.index(after: offset)) + } + + return LogFileEntry( + raw: string, + timestamp: timestamp, + processID: processID, + threadID: threadID, + module: module, + filename: filename, + level: level, + message: String(msg) + ) + } + + private static func parseLightEntry( + _ string: String, + _ df: ISO8601DateFormatter + ) -> LogFileEntryTimestamp? { + + var offset: String.Index = string.startIndex + guard let timestamp = parseTimestamp(string, df, &offset) else { + return nil + } + + return LogFileEntryTimestamp( + raw: string, + timestamp: timestamp + ) + } + + private static func parseTimestamp( + _ fullString: String, + _ df: ISO8601DateFormatter, + _ index: inout String.Index + ) -> Date? { + + let label = "timestamp" + guard let substring = parseEnclosure(fullString, label, &index) else { + return nil + } + + let result = df.date(from: String(substring)) + if result == nil { + log.debug("parseItem: \(label): cannot parse timestamp: \(substring)") + } + + return result + } + + private static func parseProcessThread( + _ fullString: String, + _ index: inout String.Index + ) -> (Int32, UInt64)? { + + let label = "process/thread" + guard let substring = parseEnclosure(fullString, label, &index) else { + return nil + } + + let components = substring.components(separatedBy: ":") + guard components.count == 2 else { + log.debug("parseItem: \(label): components.count != 2") + return nil + } + + guard let processID = Int32(components[0]) else { + log.debug("parseItem: \(label): cannot prase processID: \(components[0])") + return nil + } + + guard let threadID = UInt64(components[1]) else { + log.debug("parseItem: \(label): cannot parse threadID: \(components[1])") + return nil + } + + return (processID, threadID) + } + + private static func parseModuleFilename( + _ fullString: String, + _ index: inout String.Index + ) -> (String, String)? { + + let label = "module/filename" + guard let substring = parseEnclosure(fullString, label, &index) else { + return nil + } + + let components = substring.components(separatedBy: "/") + if components.count == 2 { + return (components[0], components[1]) + } else if components.count > 2 { + // Either the module or filename has a "/" character. + // This isn't supposed to happen, but if it does, we'll assume it's part of the module. + let module = components.dropLast().joined(separator: "/") + let filename = components.last! + return (module, filename) + } else { + log.debug("parseItem: \(label): cannot parse components: \(substring)") + return nil + } + } + + private static func parseLevel( + _ fullString: String, + _ index: inout String.Index + ) -> Logging.Logger.Level? { + + let label = "level" + guard let substring = parseEnclosure(fullString, label, &index) else { + return nil + } + + let result = Logging.Logger.Level.fromLogFileAbbreviation(String(substring)) + if result == nil { + log.debug("parseItem: \(label): cannot parse level: \(substring)") + } + + return result + } + + private static func parseEnclosure( + _ fullString: String, + _ label: String, + _ index: inout String.Index + ) -> String.SubSequence? { + + let substring0 = fullString[index...] + guard let preIndex = substring0.firstIndex(of: "[") else { + log.debug("parseItem: \(label): missing enclosure: '['") + return nil + } + + let startIndex = substring0.index(after: preIndex) + let substring1 = substring0[startIndex...] + guard let endIndex = substring1.firstIndex(of: "]") else { + log.debug("parseItem: \(label): missing enclosure: ']'") + return nil + } + + index = fullString.index(after: endIndex) + return substring1[.. + + init() { + _lock = UnsafeMutablePointer.allocate(capacity: 1) + _lock.initialize(to: os_unfair_lock()) + } + + deinit { + _lock.deallocate() + } + + func locked(_ f: () throws -> ReturnValue) rethrows -> ReturnValue { + os_unfair_lock_lock(_lock) + defer { os_unfair_lock_unlock(_lock) } + return try f() + } +} diff --git a/phoenix-ios/phoenix-ios/views/configuration/ConfigurationView.swift b/phoenix-ios/phoenix-ios/views/configuration/ConfigurationView.swift index bb43e0fef..90cbce890 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/ConfigurationView.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/ConfigurationView.swift @@ -1,15 +1,12 @@ import SwiftUI import PhoenixShared import Combine -import os.log +fileprivate let filename = "ConfigurationView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "ConfigurationView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif fileprivate enum NavLinkTag: String { diff --git a/phoenix-ios/phoenix-ios/views/configuration/advanced/channels/ChannelInfoPopup.swift b/phoenix-ios/phoenix-ios/views/configuration/advanced/channels/ChannelInfoPopup.swift index 6958ce6d5..df4366b0d 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/advanced/channels/ChannelInfoPopup.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/advanced/channels/ChannelInfoPopup.swift @@ -1,18 +1,14 @@ import SwiftUI import SegmentedPicker import PhoenixShared -import os.log +fileprivate let filename = "ChannelInfoPopup" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "ChannelInfoPopup" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct ChannelInfoPopup: View, ViewName { enum Tab: String, CaseIterable { diff --git a/phoenix-ios/phoenix-ios/views/configuration/advanced/channels/ChannelsConfigurationView.swift b/phoenix-ios/phoenix-ios/views/configuration/advanced/channels/ChannelsConfigurationView.swift index 310571836..576d3c8b0 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/advanced/channels/ChannelsConfigurationView.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/advanced/channels/ChannelsConfigurationView.swift @@ -1,17 +1,13 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "ChannelsConfigurationView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "ChannelsConfigurationView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct ChannelsConfigurationView: View { @State var sharing: String? = nil diff --git a/phoenix-ios/phoenix-ios/views/configuration/advanced/channels/ImportChannelsView.swift b/phoenix-ios/phoenix-ios/views/configuration/advanced/channels/ImportChannelsView.swift index 584069abb..1f72d7b43 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/advanced/channels/ImportChannelsView.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/advanced/channels/ImportChannelsView.swift @@ -1,14 +1,11 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "ImportChannelsView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "ImportChannelsView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif fileprivate enum ImportResultFailure { diff --git a/phoenix-ios/phoenix-ios/views/configuration/advanced/logs/LogsConfigurationView.swift b/phoenix-ios/phoenix-ios/views/configuration/advanced/logs/LogsConfigurationView.swift index 27bf27d24..a4d70d453 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/advanced/logs/LogsConfigurationView.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/advanced/logs/LogsConfigurationView.swift @@ -1,44 +1,54 @@ import SwiftUI import PhoenixShared -import os.log +import OSLog +fileprivate let filename = "LogsConfigurationView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "LogsConfigurationView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif +struct LogsConfigurationView: View { -struct LogsConfigurationView: MVIView { + @State var isExporting = false + @State var shareUrl: URL? = nil - @StateObject var mvi = MVIState({ $0.logsConfiguration() }) + @StateObject var toast = Toast() - @Environment(\.controllerFactory) var factoryEnv - var factory: ControllerFactory { return factoryEnv } - - @State var share: NSURL? = nil + @Environment(\.colorScheme) var colorScheme + // -------------------------------------------------- + // MARK: View Builders + // -------------------------------------------------- + @ViewBuilder - var view: some View { + var body: some View { - content() + layers() .navigationTitle(NSLocalizedString("Logs", comment: "Navigation bar title")) .navigationBarTitleDisplayMode(.inline) } + @ViewBuilder + func layers() -> some View { + + ZStack { + Color.primaryBackground + .ignoresSafeArea(.all, edges: .all) + + content() + toast.view() + } + } + @ViewBuilder func content() -> some View { VStack(alignment: HorizontalAlignment.center, spacing: 0) { Text("Here you can export the application logs, or share them.") - .foregroundColor(Color.primary) - .frame(maxWidth: .infinity) .padding() - .background(Color.primaryBackground) List { Button { @@ -47,7 +57,7 @@ struct LogsConfigurationView: MVIView { Label { HStack(alignment: VerticalAlignment.center, spacing: 4) { Text("Share the logs") - if isExporting() { + if isExporting { Spacer() ProgressView().progressViewStyle(CircularProgressViewStyle()) } @@ -56,34 +66,204 @@ struct LogsConfigurationView: MVIView { Image(systemName: "square.and.arrow.up") } } - .disabled(isExporting()) - .sharing($share) + .disabled(isExporting) } // .listStyle(.insetGrouped) .listBackgroundColor(.primaryBackground) } // - .onChange(of: mvi.model) { newModel in - mviModelDidChange(model: newModel) + .sheet(isPresented: shareUrlBinding()) { + let items: [Any] = [shareUrl!] + ActivityView(activityItems: items, applicationActivities: nil) } } - private func isExporting() -> Bool { - return mvi.model is LogsConfiguration.Model_Exporting - } + // -------------------------------------------------- + // MARK: View Helpers + // -------------------------------------------------- - func mviModelDidChange(model newModel: LogsConfiguration.Model) { - log.trace("mviModelDidChange()") + func shareUrlBinding() -> Binding { - if let model = newModel as? LogsConfiguration.Model_Ready { - share = NSURL(fileURLWithPath: model.path) - } + return Binding( + get: { + return shareUrl != nil + }, + set: { + if !$0 { + if let tempFileUrl = shareUrl { + shareUrl = nil + DispatchQueue.global(qos: .utility).asyncAfter(deadline: .now() + 5.0) { + do { + try FileManager.default.removeItem(at: tempFileUrl) + log.debug("Deleted tmp file: \(tempFileUrl)") + } catch { + log.error("Error deleting tmp file: \(error)") + } + } + } + } + } + ) } private func export() { log.trace("export()") - mvi.intent(LogsConfiguration.Intent_Export()) + guard isExporting == false else { + return + } + + isExporting = true + Task.detached { + await asyncExport_logFiles() + } + } + + // -------------------------------------------------- + // MARK: Exporting + // -------------------------------------------------- + + nonisolated func asyncExport_logFiles() async { + log.trace("asyncExport_logFiles()") + + do { + let logsDirectory = try LoggerFactory.logsDirectory() + + let options: FileManager.DirectoryEnumerationOptions = [ + .skipsHiddenFiles, + .skipsPackageDescendants, + .skipsSubdirectoryDescendants + ] + let allUrls = try FileManager.default.contentsOfDirectory( + at: logsDirectory, + includingPropertiesForKeys: [], + options: options + ) + + let logFileUrls = allUrls.filter { $0.lastPathComponent.hasSuffix(".log") } + + // Architecture notes: + // Our primary concern here is not speed but memory usage. + // + // Idea for future improvement: + // - Create an AsyncStream for each log file (that outputs LogFileEntryTimestamp items) + // - Combine multiple streams into a single AsyncStream + // - The combined stream simply outputs the earliest item from each substream + // + // This would drastically reduce memory pressure, + // and allow us to write to the temp file at the same time + // that we're reading from the log files. + + var allEntries: [LogFileEntryTimestamp] = [] + for url in logFileUrls { + let entries = try await LogFileParser.lightParse(url) + + let filename = url.lastPathComponent + let processAbbreviation: String + if filename.hasPrefix(LoggerFactory.friendlyProcessName_foreground) { + processAbbreviation = "FG" + } else if filename.hasPrefix(LoggerFactory.friendlyProcessName_background) { + processAbbreviation = "BG" + } else { + processAbbreviation = "??" + } + + let updatedEntries = entries.map { entry in + LogFileEntryTimestamp( + raw: "[\(processAbbreviation)] \(entry.raw)", + timestamp: entry.timestamp + ) + } + + allEntries.append(contentsOf: updatedEntries) + } + + allEntries.sort { (a, b) in + return a.timestamp < b.timestamp + } + + let random = UUID().uuidString + .replacingOccurrences(of: "-", with: "") + .substring(location: 0, length: 8) + + let tempDir = FileManager.default.temporaryDirectory + let tempFilename = "\(random).log" + let tempFile = tempDir.appendingPathComponent(tempFilename, isDirectory: false) + + let entriesData = allEntries.map { $0.raw }.joined(separator: "\n").data(using: .utf8)! + try entriesData.write(to: tempFile) + + await exportingFinished(tempFile) + + } catch { + log.error("Error exporting logs: \(error)") + await exportingFailed() + } + } + +/* This doesn't work, because Apple broke OSLogStore on iOS: + - You're unable to fetch log statements from previous app launches (of your own app) + - You're unable to fetch log statements from app extensions (part of your own app) + + This makes OSLogStore practically worthless for our purposes. + And we're forced to switch to another logging solution that actually works. + + nonisolated func asyncExport_osLogStore() async { + log.trace("asyncExport_osLogStore()") + + do { + let store = try OSLogStore(scope: .currentProcessIdentifier) + let position = store.position(timeIntervalSinceLatestBoot: 0) + let entries = try store.getEntries(at: position) + .compactMap { $0 as? OSLogEntryLog } + .filter { !$0.subsystem.hasPrefix("com.apple.") } // remove Apple spam (there's a LOT of it) + .map { "[\($0.date.formatted(.iso8601))] [\($0.subsystem)] [\($0.category)] \($0.composedMessage)" } + + log.debug("entries.count = \(entries.count)") + + let random = UUID().uuidString + .replacingOccurrences(of: "-", with: "") + .substring(location: 0, length: 8) + + let tempDir = FileManager.default.temporaryDirectory + let tempFilename = "\(random).log" + let tempFile = tempDir.appendingPathComponent(tempFilename, isDirectory: false) + + let entriesData = entries.joined(separator: "\n").data(using: .utf8)! + try entriesData.write(to: tempFile) + + await exportingFinished(tempFile) + + } catch { + log.error("Error exporting logs: \(error)") + await exportingFailed() + } + } +*/ + + @MainActor + private func exportingFailed() { + log.trace("exportingFailed()") + assertMainThread() + + isExporting = false + toast.pop( + NSLocalizedString("Exporting Failed", comment: "TxHistoryExporter"), + colorScheme: colorScheme.opposite, + style: .chrome, + duration: 15.0, + alignment: .middle, + showCloseButton: true + ) + } + + @MainActor + private func exportingFinished(_ tempFile: URL) { + log.trace("exportingFinished()") + assertMainThread() + + isExporting = false + shareUrl = tempFile } } diff --git a/phoenix-ios/phoenix-ios/views/configuration/advanced/wallet/FinalWalletDetails.swift b/phoenix-ios/phoenix-ios/views/configuration/advanced/wallet/FinalWalletDetails.swift index 42cfb0629..6912cab9e 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/advanced/wallet/FinalWalletDetails.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/advanced/wallet/FinalWalletDetails.swift @@ -1,17 +1,13 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "FinalWalletDetails" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "FinalWalletDetails" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct FinalWalletDetails: View { @State var finalWallet = Biz.business.peerManager.finalWalletValue() diff --git a/phoenix-ios/phoenix-ios/views/configuration/advanced/wallet/SwapInWalletDetails.swift b/phoenix-ios/phoenix-ios/views/configuration/advanced/wallet/SwapInWalletDetails.swift index d559287e9..b76b62bd8 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/advanced/wallet/SwapInWalletDetails.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/advanced/wallet/SwapInWalletDetails.swift @@ -1,14 +1,11 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "SwapInWalletDetails" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "SwapInWalletDetails" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct SwapInWalletDetails: View { diff --git a/phoenix-ios/phoenix-ios/views/configuration/advanced/wallet/WalletInfoView.swift b/phoenix-ios/phoenix-ios/views/configuration/advanced/wallet/WalletInfoView.swift index 1785c2f47..2862d4e15 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/advanced/wallet/WalletInfoView.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/advanced/wallet/WalletInfoView.swift @@ -1,15 +1,12 @@ import SwiftUI import PhoenixShared import Popovers -import os.log +fileprivate let filename = "WalletInfoView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "WalletInfoView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif fileprivate enum NavLinkTag: String { diff --git a/phoenix-ios/phoenix-ios/views/configuration/danger zone/ForceCloseChannelsView.swift b/phoenix-ios/phoenix-ios/views/configuration/danger zone/ForceCloseChannelsView.swift index ae88b6dfa..4b88e8485 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/danger zone/ForceCloseChannelsView.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/danger zone/ForceCloseChannelsView.swift @@ -1,17 +1,13 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "ForceCloseChannelsView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "ForceCloseChannelsView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct ForceCloseChannelsView : MVIView { @StateObject var mvi = MVIState({ $0.forceCloseChannelsConfiguration() }) diff --git a/phoenix-ios/phoenix-ios/views/configuration/danger zone/drain wallet/DrainWalletView.swift b/phoenix-ios/phoenix-ios/views/configuration/danger zone/drain wallet/DrainWalletView.swift index cefee33c2..5410547fa 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/danger zone/drain wallet/DrainWalletView.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/danger zone/drain wallet/DrainWalletView.swift @@ -1,17 +1,13 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "DrainWalletView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "DrainWalletView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct DrainWalletView: MVIView { @StateObject var mvi = MVIState({ $0.closeChannelsConfiguration() }) diff --git a/phoenix-ios/phoenix-ios/views/configuration/danger zone/drain wallet/DrainWalletView_Action.swift b/phoenix-ios/phoenix-ios/views/configuration/danger zone/drain wallet/DrainWalletView_Action.swift index 46054d0fc..861591509 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/danger zone/drain wallet/DrainWalletView_Action.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/danger zone/drain wallet/DrainWalletView_Action.swift @@ -1,14 +1,11 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "DrainWalletView_Action" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "DrainWalletView_Action" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct DrainWalletView_Action: MVISubView { diff --git a/phoenix-ios/phoenix-ios/views/configuration/danger zone/drain wallet/DrainWalletView_Confirm.swift b/phoenix-ios/phoenix-ios/views/configuration/danger zone/drain wallet/DrainWalletView_Confirm.swift index 925719dfe..976b62869 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/danger zone/drain wallet/DrainWalletView_Confirm.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/danger zone/drain wallet/DrainWalletView_Confirm.swift @@ -1,14 +1,11 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "DrainWalletView_Confirm" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "DrainWalletView_Confirm" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct DrainWalletView_Confirm: MVISubView { diff --git a/phoenix-ios/phoenix-ios/views/configuration/danger zone/reset wallet/ResetWalletView.swift b/phoenix-ios/phoenix-ios/views/configuration/danger zone/reset wallet/ResetWalletView.swift index bbdb97e0a..2c106fad9 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/danger zone/reset wallet/ResetWalletView.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/danger zone/reset wallet/ResetWalletView.swift @@ -1,17 +1,13 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "ResetWalletView_Options" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "ResetWalletView_Options" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct ResetWalletView: MVIView { @StateObject var mvi = MVIState({ $0.closeChannelsConfiguration() }) diff --git a/phoenix-ios/phoenix-ios/views/configuration/danger zone/reset wallet/ResetWalletView_Action.swift b/phoenix-ios/phoenix-ios/views/configuration/danger zone/reset wallet/ResetWalletView_Action.swift index 264f500db..9331d8d6e 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/danger zone/reset wallet/ResetWalletView_Action.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/danger zone/reset wallet/ResetWalletView_Action.swift @@ -1,14 +1,11 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "ResetWalletView_Action" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "ResetWalletView_Action" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif fileprivate enum DeleteState { diff --git a/phoenix-ios/phoenix-ios/views/configuration/danger zone/reset wallet/ResetWalletView_Confirm.swift b/phoenix-ios/phoenix-ios/views/configuration/danger zone/reset wallet/ResetWalletView_Confirm.swift index 904567af6..b4ad60f49 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/danger zone/reset wallet/ResetWalletView_Confirm.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/danger zone/reset wallet/ResetWalletView_Confirm.swift @@ -1,14 +1,11 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "ResetWalletView_Confirm" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "ResetWalletView_Confirm" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct ResetWalletView_Confirm: MVISubView { diff --git a/phoenix-ios/phoenix-ios/views/configuration/fees/channel management/LiquidityPolicyHelp.swift b/phoenix-ios/phoenix-ios/views/configuration/fees/channel management/LiquidityPolicyHelp.swift index c12c4c943..82a3adc92 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/fees/channel management/LiquidityPolicyHelp.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/fees/channel management/LiquidityPolicyHelp.swift @@ -1,14 +1,11 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "LiquidityPolicyHelp" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "LiquidityPolicyHelp" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct LiquidityPolicyHelp: View { diff --git a/phoenix-ios/phoenix-ios/views/configuration/fees/channel management/LiquidityPolicyView.swift b/phoenix-ios/phoenix-ios/views/configuration/fees/channel management/LiquidityPolicyView.swift index 09a86360f..0703dd362 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/fees/channel management/LiquidityPolicyView.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/fees/channel management/LiquidityPolicyView.swift @@ -1,14 +1,11 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "PaymentOptionsView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "PaymentOptionsView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct LiquidityPolicyView: View { diff --git a/phoenix-ios/phoenix-ios/views/configuration/fees/liquidity management/LiquidityAdsHelp.swift b/phoenix-ios/phoenix-ios/views/configuration/fees/liquidity management/LiquidityAdsHelp.swift index acddca1c0..8a0d8e0a0 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/fees/liquidity management/LiquidityAdsHelp.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/fees/liquidity management/LiquidityAdsHelp.swift @@ -1,13 +1,10 @@ import SwiftUI -import os.log +fileprivate let filename = "LiquidityAdsHelp" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "LiquidityAdsHelp" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct LiquidityAdsHelp: View { diff --git a/phoenix-ios/phoenix-ios/views/configuration/fees/liquidity management/LiquidityAdsView.swift b/phoenix-ios/phoenix-ios/views/configuration/fees/liquidity management/LiquidityAdsView.swift index 2b0c623e4..79335b99a 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/fees/liquidity management/LiquidityAdsView.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/fees/liquidity management/LiquidityAdsView.swift @@ -1,15 +1,12 @@ import SwiftUI import PhoenixShared import Popovers -import os.log +fileprivate let filename = "LiquidityAdsView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "LiquidityAdsView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct LiquidityAdsView: View { diff --git a/phoenix-ios/phoenix-ios/views/configuration/general/display configuration/BitcoinUnitSelector.swift b/phoenix-ios/phoenix-ios/views/configuration/general/display configuration/BitcoinUnitSelector.swift index 2f18c85b2..69ec4fe51 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/general/display configuration/BitcoinUnitSelector.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/general/display configuration/BitcoinUnitSelector.swift @@ -1,14 +1,11 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "BitcoinUnitSelector" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "BitcoinUnitSelector" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct BitcoinUnitSelector: View { diff --git a/phoenix-ios/phoenix-ios/views/configuration/general/display configuration/DisplayConfigurationView.swift b/phoenix-ios/phoenix-ios/views/configuration/general/display configuration/DisplayConfigurationView.swift index 6258c368a..8f3d81381 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/general/display configuration/DisplayConfigurationView.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/general/display configuration/DisplayConfigurationView.swift @@ -1,14 +1,11 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "DisplayConfigurationView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "DisplayConfigurationView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif fileprivate enum NavLinkTag: String { diff --git a/phoenix-ios/phoenix-ios/views/configuration/general/display configuration/FiatCurrencySelector.swift b/phoenix-ios/phoenix-ios/views/configuration/general/display configuration/FiatCurrencySelector.swift index bacc718a2..ab6176673 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/general/display configuration/FiatCurrencySelector.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/general/display configuration/FiatCurrencySelector.swift @@ -1,14 +1,11 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "FiatCurrencySelector" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "FiatCurrencySelector" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct FiatCurrencySelector: View { diff --git a/phoenix-ios/phoenix-ios/views/configuration/general/display configuration/RecentPaymentsSelector.swift b/phoenix-ios/phoenix-ios/views/configuration/general/display configuration/RecentPaymentsSelector.swift index 721a88318..4790ecb12 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/general/display configuration/RecentPaymentsSelector.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/general/display configuration/RecentPaymentsSelector.swift @@ -1,16 +1,12 @@ import SwiftUI -import os.log +fileprivate let filename = "RecentPaymentsSelector" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "RecentPaymentsSelector" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct RecentPaymentsSelector: View { @State var recentPaymentsConfig: RecentPaymentsConfig diff --git a/phoenix-ios/phoenix-ios/views/configuration/general/payment options/BackgroundPaymentsSelector.swift b/phoenix-ios/phoenix-ios/views/configuration/general/payment options/BackgroundPaymentsSelector.swift index 332fa6445..7175f3151 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/general/payment options/BackgroundPaymentsSelector.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/general/payment options/BackgroundPaymentsSelector.swift @@ -1,16 +1,12 @@ import SwiftUI -import os.log +fileprivate let filename = "BackgroundPaymentsSelector" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "BackgroundPaymentsSelector" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct BackgroundPaymentsSelector: View { @State var settings = NotificationsManager.shared.settings.value diff --git a/phoenix-ios/phoenix-ios/views/configuration/general/payment options/PaymentOptionsView.swift b/phoenix-ios/phoenix-ios/views/configuration/general/payment options/PaymentOptionsView.swift index 71eb71400..bdf0c1752 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/general/payment options/PaymentOptionsView.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/general/payment options/PaymentOptionsView.swift @@ -1,14 +1,11 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "PaymentOptionsView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "PaymentOptionsView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif fileprivate enum NavLinkTag: String { diff --git a/phoenix-ios/phoenix-ios/views/configuration/privacy and security/AppAccessView.swift b/phoenix-ios/phoenix-ios/views/configuration/privacy and security/AppAccessView.swift index f06381b0c..cb604ef5a 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/privacy and security/AppAccessView.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/privacy and security/AppAccessView.swift @@ -2,18 +2,14 @@ import Foundation import Combine import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "AppAccessView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "AppAccessView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct AppAccessView : View { @State var biometricSupport = AppSecurity.shared.deviceBiometricSupport() diff --git a/phoenix-ios/phoenix-ios/views/configuration/privacy and security/PaymentsBackupView.swift b/phoenix-ios/phoenix-ios/views/configuration/privacy and security/PaymentsBackupView.swift index 35d1f9840..7f6dea549 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/privacy and security/PaymentsBackupView.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/privacy and security/PaymentsBackupView.swift @@ -1,16 +1,12 @@ import SwiftUI -import os.log +fileprivate let filename = "PaymentsBackupView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "PaymentsBackupView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct PaymentsBackupView: View { @State var backupTransactions_enabled = Prefs.shared.backupTransactions.isEnabled diff --git a/phoenix-ios/phoenix-ios/views/configuration/privacy and security/electrum server/ElectrumAddressSheet.swift b/phoenix-ios/phoenix-ios/views/configuration/privacy and security/electrum server/ElectrumAddressSheet.swift index 0db529556..374d171eb 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/privacy and security/electrum server/ElectrumAddressSheet.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/privacy and security/electrum server/ElectrumAddressSheet.swift @@ -2,15 +2,12 @@ import SwiftUI import Combine import CryptoKit import PhoenixShared -import os.log +fileprivate let filename = "ElectrumAddressSheet" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "ElectrumAddressSheet" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif enum CertInfoType: Int { diff --git a/phoenix-ios/phoenix-ios/views/configuration/privacy and security/electrum server/ElectrumConfigurationView.swift b/phoenix-ios/phoenix-ios/views/configuration/privacy and security/electrum server/ElectrumConfigurationView.swift index 75c516408..5f708b060 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/privacy and security/electrum server/ElectrumConfigurationView.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/privacy and security/electrum server/ElectrumConfigurationView.swift @@ -1,15 +1,12 @@ import SwiftUI import PhoenixShared import Combine -import os.log +fileprivate let filename = "ElectrumConfigurationView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "ElectrumConfigurationView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct ElectrumConfigurationView: MVIView { diff --git a/phoenix-ios/phoenix-ios/views/configuration/privacy and security/recovery phrase/CloudBackupView.swift b/phoenix-ios/phoenix-ios/views/configuration/privacy and security/recovery phrase/CloudBackupView.swift index 1d19c644f..78f4575e9 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/privacy and security/recovery phrase/CloudBackupView.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/privacy and security/recovery phrase/CloudBackupView.swift @@ -1,13 +1,10 @@ import SwiftUI -import os.log +fileprivate let filename = "CloudBackupView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "CloudBackupView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct CloudBackupView: View { diff --git a/phoenix-ios/phoenix-ios/views/configuration/privacy and security/recovery phrase/RecoveryPhraseView.swift b/phoenix-ios/phoenix-ios/views/configuration/privacy and security/recovery phrase/RecoveryPhraseView.swift index d71499401..176ec8dc3 100644 --- a/phoenix-ios/phoenix-ios/views/configuration/privacy and security/recovery phrase/RecoveryPhraseView.swift +++ b/phoenix-ios/phoenix-ios/views/configuration/privacy and security/recovery phrase/RecoveryPhraseView.swift @@ -1,15 +1,12 @@ import SwiftUI import CloudKit import CircularCheckmarkProgress -import os.log +fileprivate let filename = "RecoveryPhraseView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "RecoveryPhraseView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct RecoveryPhraseView: View { diff --git a/phoenix-ios/phoenix-ios/views/content/ContentView.swift b/phoenix-ios/phoenix-ios/views/content/ContentView.swift index 651dd987e..1c6510b02 100644 --- a/phoenix-ios/phoenix-ios/views/content/ContentView.swift +++ b/phoenix-ios/phoenix-ios/views/content/ContentView.swift @@ -1,17 +1,13 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "ContentView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "ContentView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct ContentView: View { @ObservedObject var lockState = LockState.shared diff --git a/phoenix-ios/phoenix-ios/views/content/LoadingView.swift b/phoenix-ios/phoenix-ios/views/content/LoadingView.swift index 172026c29..66b9b4479 100644 --- a/phoenix-ios/phoenix-ios/views/content/LoadingView.swift +++ b/phoenix-ios/phoenix-ios/views/content/LoadingView.swift @@ -1,13 +1,10 @@ import SwiftUI -import os.log +fileprivate let filename = "LoadingView" #if DEBUG && false -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "LoadingView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct LoadingView: View { diff --git a/phoenix-ios/phoenix-ios/views/content/LockView.swift b/phoenix-ios/phoenix-ios/views/content/LockView.swift index fdee93996..b03f854fc 100644 --- a/phoenix-ios/phoenix-ios/views/content/LockView.swift +++ b/phoenix-ios/phoenix-ios/views/content/LockView.swift @@ -1,13 +1,10 @@ import SwiftUI -import os.log +fileprivate let filename = "LockView" #if DEBUG && false -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "LockView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct LockView: View { diff --git a/phoenix-ios/phoenix-ios/views/environment/DeepLink.swift b/phoenix-ios/phoenix-ios/views/environment/DeepLink.swift index eac59200a..e7d95f246 100644 --- a/phoenix-ios/phoenix-ios/views/environment/DeepLink.swift +++ b/phoenix-ios/phoenix-ios/views/environment/DeepLink.swift @@ -1,16 +1,12 @@ import Foundation -import os.log +fileprivate let filename = "DeepLinkManager" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "DeepLinkManager" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - enum DeepLink: String, Equatable { case paymentHistory case backup diff --git a/phoenix-ios/phoenix-ios/views/html/AnyHTML.swift b/phoenix-ios/phoenix-ios/views/html/AnyHTML.swift index ba35eaade..e05c1a306 100644 --- a/phoenix-ios/phoenix-ios/views/html/AnyHTML.swift +++ b/phoenix-ios/phoenix-ios/views/html/AnyHTML.swift @@ -1,13 +1,10 @@ import SwiftUI -import os.log +fileprivate let filename = "AnyHTML" #if DEBUG && false -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "AnyHTML" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif /// The `AnyHTML` class is an ObservableObject designed to asynchronously diff --git a/phoenix-ios/phoenix-ios/views/inspect/CpfpView.swift b/phoenix-ios/phoenix-ios/views/inspect/CpfpView.swift index e918579ef..e5cadee5c 100644 --- a/phoenix-ios/phoenix-ios/views/inspect/CpfpView.swift +++ b/phoenix-ios/phoenix-ios/views/inspect/CpfpView.swift @@ -1,14 +1,11 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "CpfpSheet" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "CpfpSheet" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct MinerFeeCPFP { diff --git a/phoenix-ios/phoenix-ios/views/inspect/DetailsView.swift b/phoenix-ios/phoenix-ios/views/inspect/DetailsView.swift index d63d123f9..00d5ca723 100644 --- a/phoenix-ios/phoenix-ios/views/inspect/DetailsView.swift +++ b/phoenix-ios/phoenix-ios/views/inspect/DetailsView.swift @@ -1,17 +1,13 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "DetailsView" #if DEBUG && false -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "DetailsView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct DetailsView: View { let location: PaymentView.Location diff --git a/phoenix-ios/phoenix-ios/views/inspect/EditInfoView.swift b/phoenix-ios/phoenix-ios/views/inspect/EditInfoView.swift index 9b647f3e0..784db7acf 100644 --- a/phoenix-ios/phoenix-ios/views/inspect/EditInfoView.swift +++ b/phoenix-ios/phoenix-ios/views/inspect/EditInfoView.swift @@ -1,17 +1,13 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "EditInfoView" #if DEBUG && false -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "EditInfoView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct EditInfoView: View { let location: PaymentView.Location diff --git a/phoenix-ios/phoenix-ios/views/inspect/PaymentView.swift b/phoenix-ios/phoenix-ios/views/inspect/PaymentView.swift index 16796459f..e44a07edc 100644 --- a/phoenix-ios/phoenix-ios/views/inspect/PaymentView.swift +++ b/phoenix-ios/phoenix-ios/views/inspect/PaymentView.swift @@ -1,17 +1,13 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "PaymentView" #if DEBUG && false -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "PaymentView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct PaymentView: View { enum Location { diff --git a/phoenix-ios/phoenix-ios/views/inspect/SummaryView.swift b/phoenix-ios/phoenix-ios/views/inspect/SummaryView.swift index 5535d2219..90bedcf80 100644 --- a/phoenix-ios/phoenix-ios/views/inspect/SummaryView.swift +++ b/phoenix-ios/phoenix-ios/views/inspect/SummaryView.swift @@ -1,15 +1,12 @@ import SwiftUI import PhoenixShared import Popovers -import os.log +fileprivate let filename = "SummaryView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "SummaryView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct SummaryView: View { diff --git a/phoenix-ios/phoenix-ios/views/layers/Toast.swift b/phoenix-ios/phoenix-ios/views/layers/Toast.swift index 4e960ee1c..af2c4627c 100644 --- a/phoenix-ios/phoenix-ios/views/layers/Toast.swift +++ b/phoenix-ios/phoenix-ios/views/layers/Toast.swift @@ -1,16 +1,12 @@ import SwiftUI -import os.log +fileprivate let filename = "Toast" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "Toast" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - class Toast: ObservableObject { enum ToastAlignment { diff --git a/phoenix-ios/phoenix-ios/views/main/AppStatusButton.swift b/phoenix-ios/phoenix-ios/views/main/AppStatusButton.swift index b12d966f5..494845073 100644 --- a/phoenix-ios/phoenix-ios/views/main/AppStatusButton.swift +++ b/phoenix-ios/phoenix-ios/views/main/AppStatusButton.swift @@ -1,17 +1,13 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "AppStatusButton" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "AppStatusButton" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct AppStatusButton: View { let headerButtonHeightReader: GeometryPreferenceReader, [CGFloat]> diff --git a/phoenix-ios/phoenix-ios/views/main/BgRefreshDisabledPopover.swift b/phoenix-ios/phoenix-ios/views/main/BgRefreshDisabledPopover.swift index b8d22f1ef..8e6b6ed64 100644 --- a/phoenix-ios/phoenix-ios/views/main/BgRefreshDisabledPopover.swift +++ b/phoenix-ios/phoenix-ios/views/main/BgRefreshDisabledPopover.swift @@ -1,16 +1,12 @@ import SwiftUI -import os.log +fileprivate let filename = "BgRefreshDisabledPopover" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "BgRefreshDisabledPopover" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct BgRefreshDisabledPopover: View { @EnvironmentObject var popoverState: PopoverState diff --git a/phoenix-ios/phoenix-ios/views/main/HomeView.swift b/phoenix-ios/phoenix-ios/views/main/HomeView.swift index 7917d680b..fe86862aa 100644 --- a/phoenix-ios/phoenix-ios/views/main/HomeView.swift +++ b/phoenix-ios/phoenix-ios/views/main/HomeView.swift @@ -2,15 +2,12 @@ import SwiftUI import Combine import PhoenixShared import Network -import os.log +fileprivate let filename = "HomeView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "HomeView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif fileprivate let PAGE_COUNT_START = 25 diff --git a/phoenix-ios/phoenix-ios/views/main/MainView.swift b/phoenix-ios/phoenix-ios/views/main/MainView.swift index 265970147..f714b1a9d 100644 --- a/phoenix-ios/phoenix-ios/views/main/MainView.swift +++ b/phoenix-ios/phoenix-ios/views/main/MainView.swift @@ -1,14 +1,11 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "MainView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "MainView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif enum HeaderButtonHeight: Preference {} diff --git a/phoenix-ios/phoenix-ios/views/main/MainView_Big.swift b/phoenix-ios/phoenix-ios/views/main/MainView_Big.swift index 66b83283b..203061459 100644 --- a/phoenix-ios/phoenix-ios/views/main/MainView_Big.swift +++ b/phoenix-ios/phoenix-ios/views/main/MainView_Big.swift @@ -1,14 +1,11 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "MainView_Big" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "MainView_Big" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif fileprivate enum LeadingSidebarContent { diff --git a/phoenix-ios/phoenix-ios/views/main/MainView_BigPrimary.swift b/phoenix-ios/phoenix-ios/views/main/MainView_BigPrimary.swift index 4ee0ba7f9..53f418453 100644 --- a/phoenix-ios/phoenix-ios/views/main/MainView_BigPrimary.swift +++ b/phoenix-ios/phoenix-ios/views/main/MainView_BigPrimary.swift @@ -1,14 +1,11 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "MainView_BigPrimary" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "MainView_BigPrimary" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif fileprivate enum NavLinkTag: String { diff --git a/phoenix-ios/phoenix-ios/views/main/MainView_Small.swift b/phoenix-ios/phoenix-ios/views/main/MainView_Small.swift index 9f03918aa..b1677f681 100644 --- a/phoenix-ios/phoenix-ios/views/main/MainView_Small.swift +++ b/phoenix-ios/phoenix-ios/views/main/MainView_Small.swift @@ -1,14 +1,11 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "MainView_Small" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "MainView_Small" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif fileprivate enum NavLinkTag: String { diff --git a/phoenix-ios/phoenix-ios/views/main/ToolsButton.swift b/phoenix-ios/phoenix-ios/views/main/ToolsButton.swift index 1175c1182..761905e19 100644 --- a/phoenix-ios/phoenix-ios/views/main/ToolsButton.swift +++ b/phoenix-ios/phoenix-ios/views/main/ToolsButton.swift @@ -1,13 +1,10 @@ import SwiftUI -import os.log +fileprivate let filename = "ToolsButton" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "ToolsButton" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct ToolsImage: View { diff --git a/phoenix-ios/phoenix-ios/views/notifications/BizNotificationCell.swift b/phoenix-ios/phoenix-ios/views/notifications/BizNotificationCell.swift index 5f9d42f07..2a584705d 100644 --- a/phoenix-ios/phoenix-ios/views/notifications/BizNotificationCell.swift +++ b/phoenix-ios/phoenix-ios/views/notifications/BizNotificationCell.swift @@ -1,17 +1,13 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "BizNotificationCell" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "BizNotificationCell" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct BizNotificationCell: View { enum Location { diff --git a/phoenix-ios/phoenix-ios/views/notifications/NoticeBox.swift b/phoenix-ios/phoenix-ios/views/notifications/NoticeBox.swift index 64f5eba5f..cb126d0f7 100644 --- a/phoenix-ios/phoenix-ios/views/notifications/NoticeBox.swift +++ b/phoenix-ios/phoenix-ios/views/notifications/NoticeBox.swift @@ -1,16 +1,12 @@ import SwiftUI -import os.log +fileprivate let filename = "NoticeBox" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "NoticeBox" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct NoticeBox: View { let backgroundColor: Color? diff --git a/phoenix-ios/phoenix-ios/views/notifications/NoticeMonitor.swift b/phoenix-ios/phoenix-ios/views/notifications/NoticeMonitor.swift index 3e1fc0abc..b1d5752c2 100644 --- a/phoenix-ios/phoenix-ios/views/notifications/NoticeMonitor.swift +++ b/phoenix-ios/phoenix-ios/views/notifications/NoticeMonitor.swift @@ -1,18 +1,14 @@ import SwiftUI import Combine import PhoenixShared -import os.log +fileprivate let filename = "NoticeMonitor" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "NoticeMonitor" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - class NoticeMonitor: ObservableObject { @Published private var isNewWallet = Prefs.shared.isNewWallet diff --git a/phoenix-ios/phoenix-ios/views/notifications/NotificationCell.swift b/phoenix-ios/phoenix-ios/views/notifications/NotificationCell.swift index e8881a5e8..fb5ce7b7e 100644 --- a/phoenix-ios/phoenix-ios/views/notifications/NotificationCell.swift +++ b/phoenix-ios/phoenix-ios/views/notifications/NotificationCell.swift @@ -1,18 +1,14 @@ import SwiftUI import Combine import PhoenixShared -import os.log +fileprivate let filename = "NotificationCell" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "NotificationCell" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - class NotificationCell { @ViewBuilder diff --git a/phoenix-ios/phoenix-ios/views/notifications/NotificationsView.swift b/phoenix-ios/phoenix-ios/views/notifications/NotificationsView.swift index 37c4ec770..562abbe3c 100644 --- a/phoenix-ios/phoenix-ios/views/notifications/NotificationsView.swift +++ b/phoenix-ios/phoenix-ios/views/notifications/NotificationsView.swift @@ -1,17 +1,13 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "NotificationsView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "NotificationsView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct NotificationsView : View { enum Location { diff --git a/phoenix-ios/phoenix-ios/views/onboarding/InitializationView.swift b/phoenix-ios/phoenix-ios/views/onboarding/InitializationView.swift index f83aca614..412c20622 100644 --- a/phoenix-ios/phoenix-ios/views/onboarding/InitializationView.swift +++ b/phoenix-ios/phoenix-ios/views/onboarding/InitializationView.swift @@ -1,17 +1,13 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "InitializationView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "InitializationView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct InitializationView: MVIView { @StateObject var mvi = MVIState({ $0.initialization() }) diff --git a/phoenix-ios/phoenix-ios/views/onboarding/IntroContainer.swift b/phoenix-ios/phoenix-ios/views/onboarding/IntroContainer.swift index 60be85a9b..fb38edb2d 100644 --- a/phoenix-ios/phoenix-ios/views/onboarding/IntroContainer.swift +++ b/phoenix-ios/phoenix-ios/views/onboarding/IntroContainer.swift @@ -1,16 +1,12 @@ import SwiftUI -import os.log +fileprivate let filename = "IntroContainer" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "IntroContainer" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct IntroContainer: View { @State var introFinished = false diff --git a/phoenix-ios/phoenix-ios/views/onboarding/IntroView.swift b/phoenix-ios/phoenix-ios/views/onboarding/IntroView.swift index f01e0b7c4..601b23a95 100644 --- a/phoenix-ios/phoenix-ios/views/onboarding/IntroView.swift +++ b/phoenix-ios/phoenix-ios/views/onboarding/IntroView.swift @@ -1,18 +1,14 @@ import Foundation import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "IntroView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "IntroView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct IntroView: View { let finish: () -> Void diff --git a/phoenix-ios/phoenix-ios/views/onboarding/ManualRestoreView.swift b/phoenix-ios/phoenix-ios/views/onboarding/ManualRestoreView.swift index 406d4c369..057aa8d3a 100644 --- a/phoenix-ios/phoenix-ios/views/onboarding/ManualRestoreView.swift +++ b/phoenix-ios/phoenix-ios/views/onboarding/ManualRestoreView.swift @@ -1,17 +1,13 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "RestoreWalletView" #if DEBUG && false -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "RestoreWalletView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct ManualRestoreView: MVIView { @StateObject var mvi = MVIState({ $0.restoreWallet() }) diff --git a/phoenix-ios/phoenix-ios/views/onboarding/RestoreView.swift b/phoenix-ios/phoenix-ios/views/onboarding/RestoreView.swift index 5b2086cb8..8044151dc 100644 --- a/phoenix-ios/phoenix-ios/views/onboarding/RestoreView.swift +++ b/phoenix-ios/phoenix-ios/views/onboarding/RestoreView.swift @@ -1,18 +1,14 @@ import SwiftUI import Combine import CloudKit -import os.log +fileprivate let filename = "RestoreView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "RestoreView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct RestoreView: View { @StateObject var fetcher = FetchSeedsObserver() diff --git a/phoenix-ios/phoenix-ios/views/receive/ModifyInvoiceSheet.swift b/phoenix-ios/phoenix-ios/views/receive/ModifyInvoiceSheet.swift index 436f7ba1e..3108adb7c 100644 --- a/phoenix-ios/phoenix-ios/views/receive/ModifyInvoiceSheet.swift +++ b/phoenix-ios/phoenix-ios/views/receive/ModifyInvoiceSheet.swift @@ -1,17 +1,13 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "ModifyInvoiceSheet" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "ModifyInvoiceSheet" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct ModifyInvoiceSheet: View { @ObservedObject var mvi: MVIState diff --git a/phoenix-ios/phoenix-ios/views/receive/ReceiveLightningView.swift b/phoenix-ios/phoenix-ios/views/receive/ReceiveLightningView.swift index 4a46dd9b6..a61df31a0 100644 --- a/phoenix-ios/phoenix-ios/views/receive/ReceiveLightningView.swift +++ b/phoenix-ios/phoenix-ios/views/receive/ReceiveLightningView.swift @@ -1,14 +1,11 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "ReceiveLightningView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "ReceiveLightningView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct InboundFeeWarning { diff --git a/phoenix-ios/phoenix-ios/views/receive/ReceiveView.swift b/phoenix-ios/phoenix-ios/views/receive/ReceiveView.swift index a56e664f6..fa0180e6d 100644 --- a/phoenix-ios/phoenix-ios/views/receive/ReceiveView.swift +++ b/phoenix-ios/phoenix-ios/views/receive/ReceiveView.swift @@ -1,14 +1,11 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "ReceiveView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "ReceiveView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct ReceiveView: MVIView { diff --git a/phoenix-ios/phoenix-ios/views/receive/SwapInView.swift b/phoenix-ios/phoenix-ios/views/receive/SwapInView.swift index acf4cf334..08868bf03 100644 --- a/phoenix-ios/phoenix-ios/views/receive/SwapInView.swift +++ b/phoenix-ios/phoenix-ios/views/receive/SwapInView.swift @@ -1,14 +1,11 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "SwapInView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "SwapInView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct SwapInView: View { diff --git a/phoenix-ios/phoenix-ios/views/send/CommentSheet.swift b/phoenix-ios/phoenix-ios/views/send/CommentSheet.swift index dda8a19a2..f73620499 100644 --- a/phoenix-ios/phoenix-ios/views/send/CommentSheet.swift +++ b/phoenix-ios/phoenix-ios/views/send/CommentSheet.swift @@ -1,16 +1,12 @@ import SwiftUI -import os.log +fileprivate let filename = "CommentSheet" #if DEBUG && false -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "CommentSheet" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct CommentSheet: View { @State var text: String diff --git a/phoenix-ios/phoenix-ios/views/send/FetchActivityNotice.swift b/phoenix-ios/phoenix-ios/views/send/FetchActivityNotice.swift index 6e5d2b738..b5b135b6f 100644 --- a/phoenix-ios/phoenix-ios/views/send/FetchActivityNotice.swift +++ b/phoenix-ios/phoenix-ios/views/send/FetchActivityNotice.swift @@ -1,13 +1,10 @@ import SwiftUI -import os.log +fileprivate let filename = "FetchActivityNotice" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "FetchActivityNotice" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif /// Designed to go into a small sub-view diff --git a/phoenix-ios/phoenix-ios/views/send/LnurlFlowErrorNotice.swift b/phoenix-ios/phoenix-ios/views/send/LnurlFlowErrorNotice.swift index 6ee13b94e..543c4b7b6 100644 --- a/phoenix-ios/phoenix-ios/views/send/LnurlFlowErrorNotice.swift +++ b/phoenix-ios/phoenix-ios/views/send/LnurlFlowErrorNotice.swift @@ -1,17 +1,13 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "LnurlFlowErrorNotice" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "LnurlFlowErrorNotice" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - enum LnurlFlowError { case pay(error: Scan.LnurlPay_Error) case withdraw(error: Scan.LnurlWithdraw_Error) diff --git a/phoenix-ios/phoenix-ios/views/send/LoginView.swift b/phoenix-ios/phoenix-ios/views/send/LoginView.swift index 18e99ce18..aead416c9 100644 --- a/phoenix-ios/phoenix-ios/views/send/LoginView.swift +++ b/phoenix-ios/phoenix-ios/views/send/LoginView.swift @@ -1,14 +1,11 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "LoginView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "LoginView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct LoginView: View { diff --git a/phoenix-ios/phoenix-ios/views/send/MetadataSheet.swift b/phoenix-ios/phoenix-ios/views/send/MetadataSheet.swift index a0b4706e2..e42673d2f 100644 --- a/phoenix-ios/phoenix-ios/views/send/MetadataSheet.swift +++ b/phoenix-ios/phoenix-ios/views/send/MetadataSheet.swift @@ -1,17 +1,13 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "MetadataSheet" #if DEBUG && false -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "MetadataSheet" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct MetadataSheet: View { let lnurlPay: LnurlPay.Intent diff --git a/phoenix-ios/phoenix-ios/views/send/MinerFeeSheet.swift b/phoenix-ios/phoenix-ios/views/send/MinerFeeSheet.swift index f34dbdd9c..174585871 100644 --- a/phoenix-ios/phoenix-ios/views/send/MinerFeeSheet.swift +++ b/phoenix-ios/phoenix-ios/views/send/MinerFeeSheet.swift @@ -1,18 +1,13 @@ import SwiftUI - import PhoenixShared -import os.log +fileprivate let filename = "MinerFeeSheet" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "MinerFeeSheet" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct MinerFeeSheet: View { let amount: Bitcoin_kmpSatoshi diff --git a/phoenix-ios/phoenix-ios/views/send/OnChainDetails.swift b/phoenix-ios/phoenix-ios/views/send/OnChainDetails.swift index 65bd248d2..3fc34b695 100644 --- a/phoenix-ios/phoenix-ios/views/send/OnChainDetails.swift +++ b/phoenix-ios/phoenix-ios/views/send/OnChainDetails.swift @@ -1,14 +1,11 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "OnChainDetails" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "OnChainDetails" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct OnChainDetails: View { diff --git a/phoenix-ios/phoenix-ios/views/send/PaymentLayerChoice.swift b/phoenix-ios/phoenix-ios/views/send/PaymentLayerChoice.swift index 9fde825ac..37f934245 100644 --- a/phoenix-ios/phoenix-ios/views/send/PaymentLayerChoice.swift +++ b/phoenix-ios/phoenix-ios/views/send/PaymentLayerChoice.swift @@ -1,17 +1,13 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "PaymentLayerChoice" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "PaymentLayerChoice" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct PaymentLayerChoice: View { @ObservedObject var mvi: MVIState diff --git a/phoenix-ios/phoenix-ios/views/send/PaymentRequestedView.swift b/phoenix-ios/phoenix-ios/views/send/PaymentRequestedView.swift index 8c77a76cb..47d44672c 100644 --- a/phoenix-ios/phoenix-ios/views/send/PaymentRequestedView.swift +++ b/phoenix-ios/phoenix-ios/views/send/PaymentRequestedView.swift @@ -1,14 +1,11 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "PaymentRequestedView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "PaymentRequestedView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif /// Used after a lnurl-withdraw is completed. diff --git a/phoenix-ios/phoenix-ios/views/send/PaymentSummaryView.swift b/phoenix-ios/phoenix-ios/views/send/PaymentSummaryView.swift index 014fe4205..0aba87465 100644 --- a/phoenix-ios/phoenix-ios/views/send/PaymentSummaryView.swift +++ b/phoenix-ios/phoenix-ios/views/send/PaymentSummaryView.swift @@ -1,14 +1,11 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "PaymentSummaryView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "PaymentSummaryView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct PaymentSummaryStrings { diff --git a/phoenix-ios/phoenix-ios/views/send/PaymentWarningPopover.swift b/phoenix-ios/phoenix-ios/views/send/PaymentWarningPopover.swift index 21fd95e42..35cb62bd3 100644 --- a/phoenix-ios/phoenix-ios/views/send/PaymentWarningPopover.swift +++ b/phoenix-ios/phoenix-ios/views/send/PaymentWarningPopover.swift @@ -1,13 +1,10 @@ import SwiftUI -import os.log +fileprivate let filename = "PaymentWarningPopover" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "PaymentWarningPopover" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct PaymentWarningPopover: View { diff --git a/phoenix-ios/phoenix-ios/views/send/RangeSheet.swift b/phoenix-ios/phoenix-ios/views/send/RangeSheet.swift index f87053139..7ed56ac37 100644 --- a/phoenix-ios/phoenix-ios/views/send/RangeSheet.swift +++ b/phoenix-ios/phoenix-ios/views/send/RangeSheet.swift @@ -1,14 +1,11 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "RangeSheet" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "RangeSheet" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct RangeSheet: View { diff --git a/phoenix-ios/phoenix-ios/views/send/ScanView.swift b/phoenix-ios/phoenix-ios/views/send/ScanView.swift index d982fd2d8..9d2643a4c 100644 --- a/phoenix-ios/phoenix-ios/views/send/ScanView.swift +++ b/phoenix-ios/phoenix-ios/views/send/ScanView.swift @@ -1,17 +1,13 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "ScanView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "ScanView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct ScanView: View { let location: SendView.Location diff --git a/phoenix-ios/phoenix-ios/views/send/SendView.swift b/phoenix-ios/phoenix-ios/views/send/SendView.swift index 804e1ba4a..1e42308c1 100644 --- a/phoenix-ios/phoenix-ios/views/send/SendView.swift +++ b/phoenix-ios/phoenix-ios/views/send/SendView.swift @@ -3,15 +3,12 @@ import Combine import AVFoundation import PhoenixShared import UIKit -import os.log +fileprivate let filename = "SendView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "SendView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct SendView: MVIView { diff --git a/phoenix-ios/phoenix-ios/views/send/TipSliderSheet.swift b/phoenix-ios/phoenix-ios/views/send/TipSliderSheet.swift index a06f781c1..93d095c81 100644 --- a/phoenix-ios/phoenix-ios/views/send/TipSliderSheet.swift +++ b/phoenix-ios/phoenix-ios/views/send/TipSliderSheet.swift @@ -1,17 +1,13 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "TipSliderSheet" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "TipSliderSheet" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct TipSliderSheet: View { let range: MsatRange diff --git a/phoenix-ios/phoenix-ios/views/send/ValidateView.swift b/phoenix-ios/phoenix-ios/views/send/ValidateView.swift index 880a1b20f..703a2e5cf 100644 --- a/phoenix-ios/phoenix-ios/views/send/ValidateView.swift +++ b/phoenix-ios/phoenix-ios/views/send/ValidateView.swift @@ -1,14 +1,11 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "ValidateView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "ValidateView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct PaymentNumbers { diff --git a/phoenix-ios/phoenix-ios/views/send/WebsiteLinkPopover.swift b/phoenix-ios/phoenix-ios/views/send/WebsiteLinkPopover.swift index eac386c9a..35509dec5 100644 --- a/phoenix-ios/phoenix-ios/views/send/WebsiteLinkPopover.swift +++ b/phoenix-ios/phoenix-ios/views/send/WebsiteLinkPopover.swift @@ -1,16 +1,12 @@ import SwiftUI -import os.log +fileprivate let filename = "WebsiteLinkPopover" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "WebsiteLinkPopover" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct WebsiteLinkPopover: View { let link: URL diff --git a/phoenix-ios/phoenix-ios/views/style/TextFieldCurrencyStyler.swift b/phoenix-ios/phoenix-ios/views/style/TextFieldCurrencyStyler.swift index 2b1eadf76..a912a948b 100644 --- a/phoenix-ios/phoenix-ios/views/style/TextFieldCurrencyStyler.swift +++ b/phoenix-ios/phoenix-ios/views/style/TextFieldCurrencyStyler.swift @@ -1,14 +1,11 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "TextFieldCurrencyStyler" #if DEBUG && false -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "TextFieldCurrencyStyler" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif enum TextFieldCurrencyStylerError: Error { diff --git a/phoenix-ios/phoenix-ios/views/style/TextFieldNumberStyler.swift b/phoenix-ios/phoenix-ios/views/style/TextFieldNumberStyler.swift index a52cfcb70..cbe2548cc 100644 --- a/phoenix-ios/phoenix-ios/views/style/TextFieldNumberStyler.swift +++ b/phoenix-ios/phoenix-ios/views/style/TextFieldNumberStyler.swift @@ -1,13 +1,10 @@ import SwiftUI -import os.log +fileprivate let filename = "TextFieldNumberStyler" #if DEBUG && false -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "TextFieldNumberStyler" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif enum TextFieldNumberStylerError: Error { diff --git a/phoenix-ios/phoenix-ios/views/tools/AppStatusPopover.swift b/phoenix-ios/phoenix-ios/views/tools/AppStatusPopover.swift index a9f0c9f74..66b283324 100644 --- a/phoenix-ios/phoenix-ios/views/tools/AppStatusPopover.swift +++ b/phoenix-ios/phoenix-ios/views/tools/AppStatusPopover.swift @@ -1,19 +1,15 @@ import SwiftUI import PhoenixShared -import os.log import CircularCheckmarkProgress import CloudKit +fileprivate let filename = "AppStatusPopover" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "AppStatusPopover" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct AppStatusPopover: View { @StateObject var connectionsMonitor = ObservableConnectionsMonitor() diff --git a/phoenix-ios/phoenix-ios/views/tools/CurrencyConverterView.swift b/phoenix-ios/phoenix-ios/views/tools/CurrencyConverterView.swift index 9622012b9..8e40a2dfc 100644 --- a/phoenix-ios/phoenix-ios/views/tools/CurrencyConverterView.swift +++ b/phoenix-ios/phoenix-ios/views/tools/CurrencyConverterView.swift @@ -1,14 +1,11 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "CurrencyConverterView" #if DEBUG && false -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "CurrencyConverterView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct ParsedRow: Equatable { diff --git a/phoenix-ios/phoenix-ios/views/tools/MergeChannelsView.swift b/phoenix-ios/phoenix-ios/views/tools/MergeChannelsView.swift index 8758d1e61..0da09b98b 100644 --- a/phoenix-ios/phoenix-ios/views/tools/MergeChannelsView.swift +++ b/phoenix-ios/phoenix-ios/views/tools/MergeChannelsView.swift @@ -1,15 +1,12 @@ import SwiftUI import PhoenixShared import EffectsLibrary -import os.log +fileprivate let filename = "MergeChannelsView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "MergeChannelsView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif struct MergeChannelsView: View { diff --git a/phoenix-ios/phoenix-ios/views/tools/UnlockErrorView.swift b/phoenix-ios/phoenix-ios/views/tools/UnlockErrorView.swift index bcb7f90cb..980847f33 100644 --- a/phoenix-ios/phoenix-ios/views/tools/UnlockErrorView.swift +++ b/phoenix-ios/phoenix-ios/views/tools/UnlockErrorView.swift @@ -1,16 +1,12 @@ import SwiftUI -import os.log +fileprivate let filename = "UnlockErrorView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "UnlockErrorView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct UnlockErrorView: View { let danger: UnlockError diff --git a/phoenix-ios/phoenix-ios/views/transactions/PaymentCell.swift b/phoenix-ios/phoenix-ios/views/transactions/PaymentCell.swift index 8b99b09b7..7e5ba51b7 100644 --- a/phoenix-ios/phoenix-ios/views/transactions/PaymentCell.swift +++ b/phoenix-ios/phoenix-ios/views/transactions/PaymentCell.swift @@ -1,17 +1,13 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "PaymentCell" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "PaymentCell" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct PaymentCell : View { static let fetchOptions = WalletPaymentFetchOptions.companion.Descriptions.plus( diff --git a/phoenix-ios/phoenix-ios/views/transactions/TransactionsView.swift b/phoenix-ios/phoenix-ios/views/transactions/TransactionsView.swift index b1af78523..128ca171b 100644 --- a/phoenix-ios/phoenix-ios/views/transactions/TransactionsView.swift +++ b/phoenix-ios/phoenix-ios/views/transactions/TransactionsView.swift @@ -1,15 +1,12 @@ import SwiftUI import Combine import PhoenixShared -import os.log +fileprivate let filename = "TransactionsView" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "TransactionsView" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif fileprivate let PAGE_COUNT_START = 30 diff --git a/phoenix-ios/phoenix-ios/views/transactions/TxHistoryExporter.swift b/phoenix-ios/phoenix-ios/views/transactions/TxHistoryExporter.swift index 99678fd2e..5e97b9d7b 100644 --- a/phoenix-ios/phoenix-ios/views/transactions/TxHistoryExporter.swift +++ b/phoenix-ios/phoenix-ios/views/transactions/TxHistoryExporter.swift @@ -1,17 +1,13 @@ import SwiftUI import PhoenixShared -import os.log +fileprivate let filename = "TxHistoryExporter" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "TxHistoryExporter" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct TxHistoryExporter: View { @State var startDate = Date() @@ -291,6 +287,7 @@ struct TxHistoryExporter: View { set: { if !$0 { if let tmpFileUrl = shareUrl { + shareUrl = nil DispatchQueue.global(qos: .utility).asyncAfter(deadline: .now() + 5.0) { do { try FileManager.default.removeItem(at: tmpFileUrl) @@ -299,7 +296,6 @@ struct TxHistoryExporter: View { log.error("Error deleting tmp file: \(error)") } } - shareUrl = nil } } } diff --git a/phoenix-ios/phoenix-ios/views/widgets/HorizontalActivity.swift b/phoenix-ios/phoenix-ios/views/widgets/HorizontalActivity.swift index 69c42bafe..ef5e74bbe 100644 --- a/phoenix-ios/phoenix-ios/views/widgets/HorizontalActivity.swift +++ b/phoenix-ios/phoenix-ios/views/widgets/HorizontalActivity.swift @@ -5,18 +5,14 @@ import SwiftUI import Combine -import os.log +fileprivate let filename = "HorizontalActivity" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "HorizontalActivity" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct HorizontalActivity: View { init(color: Color, diameter: CGFloat, speed: TimeInterval = 1.6) { diff --git a/phoenix-ios/phoenix-ios/views/widgets/QRCodeScanner.swift b/phoenix-ios/phoenix-ios/views/widgets/QRCodeScanner.swift index f4d4c589c..2721987e6 100644 --- a/phoenix-ios/phoenix-ios/views/widgets/QRCodeScanner.swift +++ b/phoenix-ios/phoenix-ios/views/widgets/QRCodeScanner.swift @@ -2,18 +2,14 @@ import Foundation import AVFoundation import UIKit import SwiftUI -import os.log +fileprivate let filename = "QRCodeScanner" #if DEBUG && false -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "QRCodeScanner" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif - struct QrCodeScannerView: UIViewControllerRepresentable { let resultCallback: (String) -> Void diff --git a/phoenix-ios/phoenix-ios/xpc/CrossProcessCommunication.swift b/phoenix-ios/phoenix-ios/xpc/CrossProcessCommunication.swift index bb274e1c3..30f68008c 100644 --- a/phoenix-ios/phoenix-ios/xpc/CrossProcessCommunication.swift +++ b/phoenix-ios/phoenix-ios/xpc/CrossProcessCommunication.swift @@ -1,14 +1,11 @@ import Foundation -import os.log import notify +fileprivate let filename = "XPC" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "XPC" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif enum XpcActor { diff --git a/phoenix-ios/phoenix-notifySrvExt/NotificationService.swift b/phoenix-ios/phoenix-notifySrvExt/NotificationService.swift index aa0d0a148..0b6ea886d 100644 --- a/phoenix-ios/phoenix-notifySrvExt/NotificationService.swift +++ b/phoenix-ios/phoenix-notifySrvExt/NotificationService.swift @@ -1,16 +1,13 @@ import UserNotifications import PhoenixShared import Combine -import os.log import notify +fileprivate let filename = "NotificationService" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "NotificationService" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif /** diff --git a/phoenix-ios/phoenix-notifySrvExt/PhoenixManager.swift b/phoenix-ios/phoenix-notifySrvExt/PhoenixManager.swift index 748f23318..89a6646e7 100644 --- a/phoenix-ios/phoenix-notifySrvExt/PhoenixManager.swift +++ b/phoenix-ios/phoenix-notifySrvExt/PhoenixManager.swift @@ -1,15 +1,12 @@ import Foundation import PhoenixShared import Combine -import os.log +fileprivate let filename = "PhoenixManager" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "PhoenixManager" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif typealias ConnectionsListener = (Connections) -> Void @@ -51,18 +48,18 @@ typealias PaymentListener = (Lightning_kmpIncomingPayment) -> Void class PhoenixManager { public static let shared = PhoenixManager() - + private var connectionsListener: ConnectionsListener? = nil private var paymentListener: PaymentListener? = nil private var business: PhoenixBusiness? = nil private var oldBusiness: PhoenixBusiness? = nil - + private var cancellables = Set() private var oldCancellables = Set() - + private var fiatExchangeRates: [ExchangeRate] = [] - + private init() {} // Must use shared instance // -------------------------------------------------- @@ -75,7 +72,7 @@ class PhoenixManager { ) { log.trace("register(::)") assertMainThread() - + self.connectionsListener = connectionsListener self.paymentListener = paymentListener @@ -86,7 +83,7 @@ class PhoenixManager { public func unregister() { log.trace("unregister()") assertMainThread() - + self.connectionsListener = nil self.paymentListener = nil @@ -105,17 +102,17 @@ class PhoenixManager { private func setupBusiness() { log.trace("setupBusiness()") assertMainThread() - + guard business == nil else { log.warning("ignoring: business != nil") return } - + let newBusiness = PhoenixBusiness(ctx: PlatformContext()) - + newBusiness.networkMonitor.disable() newBusiness.currencyManager.disableAutoRefresh() - + let electrumConfig = GroupPrefs.shared.electrumConfig newBusiness.appConfigurationManager.updateElectrumConfig(server: electrumConfig?.serverAddress) @@ -127,7 +124,7 @@ class PhoenixManager { newBusiness.appConfigurationManager.updatePreferredFiatCurrencies( current: preferredFiatCurrencies ) - + let startupParams = StartupParams( requestCheckLegacyChannels: false, isTorEnabled: GroupPrefs.shared.isTorEnabled, @@ -135,20 +132,20 @@ class PhoenixManager { trustedSwapInTxs: Set() ) newBusiness.start(startupParams: startupParams) - + newBusiness.currencyManager.refreshAll(targets: [primaryFiatCurrency], force: false) - + newBusiness.connectionsManager.connectionsPublisher().sink { [weak self](connections: Connections) in - + self?.connectionsChanged(connections) } .store(in: &cancellables) - + let pushReceivedAt = Date() newBusiness.paymentsManager.lastIncomingPaymentPublisher().sink { [weak self](payment: Lightning_kmpIncomingPayment) in - + guard let paymentReceivedAt = payment.received?.receivedAtDate, paymentReceivedAt > pushReceivedAt @@ -156,62 +153,62 @@ class PhoenixManager { // Ignoring - this is the most recently received incomingPayment, but not a new one return } - + self?.didReceivePayment(payment) } .store(in: &cancellables) - + newBusiness.currencyManager.ratesPubliser().sink { [weak self](rates: [ExchangeRate]) in - + assertMainThread() // var `fiatExchangeRates` should be accessed/updated only on main thread self?.fiatExchangeRates = rates } .store(in: &cancellables) - + // Setup complete business = newBusiness } - + private func teardownBusiness() { log.trace("teardownBusiness()") assertMainThread() - + guard let currentBusiness = business else { log.warning("ignoring: business == nil") return } - + if let prvBusiness = oldBusiness { prvBusiness.stop() oldBusiness = nil oldCancellables.removeAll() } - + oldBusiness = currentBusiness business = nil cancellables.removeAll() - + currentBusiness.connectionsManager.connectionsPublisher().sink { [weak self](connections: Connections) in - + self?.oldConnectionsChanged(connections) } .store(in: &oldCancellables) - + currentBusiness.appConnectionsDaemon?.incrementDisconnectCount( target: AppConnectionsDaemon.ControlTarget.companion.All ) - + // Safety mechanism: To make sure nothing falls between the cracks, // and the oldBusiness doesn't get properly cleaned up. oldConnectionsChanged(currentBusiness.connectionsManager.currentValue) } - + // -------------------------------------------------- // MARK: Flow // -------------------------------------------------- - + private func unlock() { log.trace("unlock()") @@ -266,22 +263,22 @@ class PhoenixManager { log.warning("ignoring: business == nil") return } - + let seed = business.walletManager.mnemonicsToSeed( mnemonics: recoveryPhrase.mnemonicsArray, passphrase: "" ) business.walletManager.loadWallet(seed: seed) } - + // -------------------------------------------------- // MARK: Notifications // -------------------------------------------------- - + private func connectionsChanged(_ connections: Connections) { log.trace("connectionsChanged(_)") assertMainThread() - + if let listener = self.connectionsListener { listener(connections) } @@ -290,19 +287,19 @@ class PhoenixManager { private func didReceivePayment(_ payment: Lightning_kmpIncomingPayment) { log.trace("didReceivePayment(_)") assertMainThread() - + if let listener = self.paymentListener { listener(payment) } } - + // -------------------------------------------------- // MARK: Cleanup // -------------------------------------------------- - + private func oldConnectionsChanged(_ connections: Connections) { log.trace("oldConnectionsChanged(_)") - + switch connections.peer { case is Lightning_kmpConnection.ESTABLISHED : log.debug("oldConnections.peer = ESTABLISHED") case is Lightning_kmpConnection.ESTABLISHING : log.debug("oldConnections.peer = ESTABLISHING") @@ -315,7 +312,7 @@ class PhoenixManager { case is Lightning_kmpConnection.CLOSED : log.debug("oldConnections.electrum = CLOSED") default : log.debug("oldConnections.electrum = UNKNOWN") } - + if connections.peer is Lightning_kmpConnection.CLOSED && connections.electrum is Lightning_kmpConnection.CLOSED { diff --git a/phoenix-ios/phoenix-notifySrvExt/XpcManager.swift b/phoenix-ios/phoenix-notifySrvExt/XpcManager.swift index 5ae1b29b6..0ad92c22e 100644 --- a/phoenix-ios/phoenix-notifySrvExt/XpcManager.swift +++ b/phoenix-ios/phoenix-notifySrvExt/XpcManager.swift @@ -1,13 +1,10 @@ import Foundation -import os.log +fileprivate let filename = "XpcManager" #if DEBUG && true -fileprivate var log = Logger( - subsystem: Bundle.main.bundleIdentifier!, - category: "XpcManager" -) +fileprivate var log = LoggerFactory.shared.logger(filename, .trace) #else -fileprivate var log = Logger(OSLog.disabled) +fileprivate var log = LoggerFactory.shared.logger(filename, .warning) #endif typealias XpcListener = () -> Void diff --git a/phoenix-shared/src/androidMain/kotlin/fr/acinq/phoenix/managers/NetworkMonitorAndroid.kt b/phoenix-shared/src/androidMain/kotlin/fr/acinq/phoenix/managers/NetworkMonitorAndroid.kt index fd5d4b55d..2e9ffc569 100644 --- a/phoenix-shared/src/androidMain/kotlin/fr/acinq/phoenix/managers/NetworkMonitorAndroid.kt +++ b/phoenix-shared/src/androidMain/kotlin/fr/acinq/phoenix/managers/NetworkMonitorAndroid.kt @@ -2,17 +2,18 @@ package fr.acinq.phoenix.managers import android.content.Context import android.net.* +import fr.acinq.lightning.logging.LoggerFactory import fr.acinq.phoenix.utils.PlatformContext +import fr.acinq.lightning.logging.debug +import fr.acinq.lightning.logging.info import kotlinx.coroutines.* import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow -import org.kodein.log.LoggerFactory -import org.kodein.log.newLogger actual class NetworkMonitor actual constructor(loggerFactory: LoggerFactory, val ctx: PlatformContext) : CoroutineScope by CoroutineScope(SupervisorJob() + Dispatchers.Default) { - val logger = newLogger(loggerFactory) + val logger = loggerFactory.newLogger(this::class) private val _networkState = MutableStateFlow(NetworkState.NotAvailable) actual val networkState: StateFlow = _networkState diff --git a/phoenix-shared/src/androidMain/kotlin/fr/acinq/phoenix/utils/logger/PhoenixLogWriters.kt b/phoenix-shared/src/androidMain/kotlin/fr/acinq/phoenix/utils/logger/PhoenixLogWriters.kt new file mode 100644 index 000000000..02994939d --- /dev/null +++ b/phoenix-shared/src/androidMain/kotlin/fr/acinq/phoenix/utils/logger/PhoenixLogWriters.kt @@ -0,0 +1,49 @@ +/* + * Copyright 2024 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package fr.acinq.phoenix.utils.logger + +import co.touchlab.kermit.LogWriter +import co.touchlab.kermit.Severity +import co.touchlab.kermit.Severity.Assert +import co.touchlab.kermit.Severity.Debug +import co.touchlab.kermit.Severity.Error +import co.touchlab.kermit.Severity.Info +import co.touchlab.kermit.Severity.Verbose +import co.touchlab.kermit.Severity.Warn +import fr.acinq.phoenix.utils.PlatformContext +import org.slf4j.LoggerFactory + + +/** + * Use SLF4J writer on Android. Note that writing logs to Logcat is already done in + * phoenix-android SLF4J configuration. + */ +actual fun phoenixLogWriters(ctx: PlatformContext): List = listOf(Slf4jLogWriter()) + +class Slf4jLogWriter : LogWriter() { + override fun log(severity: Severity, message: String, tag: String, throwable: Throwable?) { + val logger = LoggerFactory.getLogger(tag) + when (severity) { + Verbose -> logger.trace(message, throwable) + Debug -> logger.debug(message, throwable) + Info -> logger.info(message, throwable) + Warn -> logger.warn(message, throwable) + Error -> logger.error(message, throwable) + Assert -> logger.error(message, throwable) + } + } +} diff --git a/phoenix-shared/src/androidTest/kotlin/fr/acinq/phoenix/data/ElectrumServersTest.kt b/phoenix-shared/src/androidTest/kotlin/fr/acinq/phoenix/data/ElectrumServersTest.kt index 53ca7d406..9c644042d 100644 --- a/phoenix-shared/src/androidTest/kotlin/fr/acinq/phoenix/data/ElectrumServersTest.kt +++ b/phoenix-shared/src/androidTest/kotlin/fr/acinq/phoenix/data/ElectrumServersTest.kt @@ -1,14 +1,17 @@ package fr.acinq.phoenix.data +import co.touchlab.kermit.CommonWriter +import co.touchlab.kermit.NoTagFormatter +import co.touchlab.kermit.Severity +import co.touchlab.kermit.loggerConfigInit import fr.acinq.lightning.io.JvmTcpSocket import fr.acinq.lightning.io.TcpSocket +import fr.acinq.lightning.logging.LoggerFactory import fr.acinq.lightning.utils.ServerAddress import io.ktor.network.selector.* import io.ktor.network.sockets.* import io.ktor.network.tls.* import kotlinx.coroutines.Dispatchers -import org.kodein.log.LoggerFactory -import org.kodein.log.newLogger import java.security.KeyStore import java.security.cert.CertificateException import java.security.cert.X509Certificate @@ -18,7 +21,10 @@ import javax.net.ssl.X509TrustManager private object ElectrumServersTestHelper { val selectorManager = ActorSelectorManager(Dispatchers.IO) - val loggerFactory = LoggerFactory.default + val loggerFactory = LoggerFactory(loggerConfigInit( + logWriters = arrayOf(CommonWriter(NoTagFormatter)), + minSeverity = Severity.Info + )) } actual suspend fun connect(server: ServerAddress) { diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/PhoenixBusiness.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/PhoenixBusiness.kt index 84c5af0a3..4fdae994c 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/PhoenixBusiness.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/PhoenixBusiness.kt @@ -20,6 +20,8 @@ import fr.acinq.lightning.NodeParams import fr.acinq.lightning.blockchain.electrum.ElectrumClient import fr.acinq.lightning.blockchain.electrum.ElectrumWatcher import fr.acinq.lightning.io.TcpSocket +import fr.acinq.lightning.logging.LoggerFactory +import fr.acinq.lightning.logging.debug import fr.acinq.phoenix.controllers.* import fr.acinq.phoenix.controllers.config.* import fr.acinq.phoenix.controllers.init.AppInitController @@ -34,6 +36,7 @@ import fr.acinq.phoenix.db.SqliteAppDb import fr.acinq.phoenix.db.createAppDbDriver import fr.acinq.phoenix.managers.* import fr.acinq.phoenix.utils.* +import fr.acinq.phoenix.utils.logger.PhoenixLoggerConfig import fr.acinq.tor.Tor import io.ktor.client.* import io.ktor.client.plugins.contentnegotiation.* @@ -43,20 +46,14 @@ import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.first import kotlinx.coroutines.cancel import kotlinx.serialization.json.Json -import org.kodein.log.LoggerFactory -import org.kodein.log.frontend.defaultLogFrontend -import org.kodein.log.newLogger -import org.kodein.log.withShortPackageKeepLast import kotlin.time.Duration.Companion.seconds class PhoenixBusiness( internal val ctx: PlatformContext ) { - - val loggerFactory = LoggerFactory( - defaultLogFrontend.withShortPackageKeepLast(1), - ) - + // this logger factory will be used throughout the project (including dependencies like lightning-kmp) to + // create new [Logger] instances, and output logs to platform dependent writers. + val loggerFactory = LoggerFactory(PhoenixLoggerConfig(ctx)) private val logger = loggerFactory.newLogger(this::class) private val tcpSocketBuilder = TcpSocket.Builder() @@ -167,9 +164,6 @@ class PhoenixBusiness( override fun electrumConfiguration(): ElectrumConfigurationController = AppElectrumConfigurationController(_this) - override fun logsConfiguration(): LogsConfigurationController = - AppLogsConfigurationController(_this) - override fun closeChannelsConfiguration(): CloseChannelsConfigurationController = AppCloseChannelsConfigurationController(_this, isForceClose = false) diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/AppController.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/AppController.kt index 3c17cc59d..b507576ec 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/AppController.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/AppController.kt @@ -1,15 +1,17 @@ package fr.acinq.phoenix.controllers +import fr.acinq.lightning.logging.LoggerFactory +import fr.acinq.lightning.logging.debug import kotlinx.coroutines.* import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.consumeEach import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.collect -import org.kodein.log.LoggerFactory -import org.kodein.log.newLogger -abstract class AppController(loggerFactory: LoggerFactory, firstModel: M) : MVI.Controller(firstModel), CoroutineScope { +abstract class AppController( + loggerFactory: LoggerFactory, + firstModel: M +) : MVI.Controller(firstModel), CoroutineScope { private val job = Job() diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/ControllerFactory.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/ControllerFactory.kt index 1b512827f..ab9f8966a 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/ControllerFactory.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/ControllerFactory.kt @@ -18,7 +18,6 @@ typealias RestoreWalletController = MVI.Controller typealias ConfigurationController = MVI.Controller typealias ElectrumConfigurationController = MVI.Controller -typealias LogsConfigurationController = MVI.Controller /** Lets us define different implementation for the controllers, which is useful for mocks. */ interface ControllerFactory { @@ -30,7 +29,6 @@ interface ControllerFactory { fun restoreWallet(): RestoreWalletController fun configuration(): ConfigurationController fun electrumConfiguration(): ElectrumConfigurationController - fun logsConfiguration(): LogsConfigurationController fun closeChannelsConfiguration(): CloseChannelsConfigurationController fun forceCloseChannelsConfiguration(): CloseChannelsConfigurationController } diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/config/CloseChannelsConfigurationController.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/config/CloseChannelsConfigurationController.kt index 3385f0d62..a8ffc459d 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/config/CloseChannelsConfigurationController.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/config/CloseChannelsConfigurationController.kt @@ -6,14 +6,15 @@ import fr.acinq.lightning.NodeParams import fr.acinq.lightning.channel.* import fr.acinq.lightning.channel.states.* import fr.acinq.lightning.io.WrappedChannelCommand +import fr.acinq.lightning.logging.LoggerFactory import fr.acinq.phoenix.PhoenixBusiness import fr.acinq.phoenix.managers.PeerManager import fr.acinq.phoenix.controllers.AppController import fr.acinq.phoenix.controllers.config.CloseChannelsConfiguration.Model.ChannelInfoStatus import fr.acinq.phoenix.utils.Parser import fr.acinq.phoenix.utils.extensions.localBalance +import fr.acinq.lightning.logging.info import kotlinx.coroutines.launch -import org.kodein.log.LoggerFactory class AppCloseChannelsConfigurationController( loggerFactory: LoggerFactory, diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/config/ConfigurationController.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/config/ConfigurationController.kt index dd16d3382..1f0a5d355 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/config/ConfigurationController.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/config/ConfigurationController.kt @@ -1,10 +1,11 @@ package fr.acinq.phoenix.controllers.config +import co.touchlab.kermit.Logger +import fr.acinq.lightning.logging.LoggerFactory import fr.acinq.phoenix.PhoenixBusiness import fr.acinq.phoenix.managers.WalletManager import fr.acinq.phoenix.controllers.AppController import kotlinx.coroutines.launch -import org.kodein.log.LoggerFactory class AppConfigurationController( diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/config/ElectrumConfigurationController.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/config/ElectrumConfigurationController.kt index d3fde5aa8..23edda027 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/config/ElectrumConfigurationController.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/config/ElectrumConfigurationController.kt @@ -1,15 +1,15 @@ package fr.acinq.phoenix.controllers.config +import co.touchlab.kermit.Logger import fr.acinq.lightning.blockchain.electrum.ElectrumClient import fr.acinq.phoenix.PhoenixBusiness import fr.acinq.phoenix.managers.AppConfigurationManager import fr.acinq.phoenix.managers.AppConnectionsDaemon import fr.acinq.phoenix.controllers.AppController -import kotlinx.coroutines.flow.collect +import fr.acinq.lightning.logging.LoggerFactory import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.flow import kotlinx.coroutines.launch -import org.kodein.log.LoggerFactory class AppElectrumConfigurationController( diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/config/LogsConfiguration.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/config/LogsConfiguration.kt deleted file mode 100644 index 3aeb4c56b..000000000 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/config/LogsConfiguration.kt +++ /dev/null @@ -1,16 +0,0 @@ -package fr.acinq.phoenix.controllers.config - -import fr.acinq.phoenix.controllers.MVI - -object LogsConfiguration { - - sealed class Model : MVI.Model() { - object Awaiting : Model() - object Exporting : Model() - data class Ready(val path: String) : Model() - } - - sealed class Intent : MVI.Intent() { - object Export : Intent() - } -} diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/config/LogsConfigurationController.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/config/LogsConfigurationController.kt deleted file mode 100644 index 782c8ad28..000000000 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/config/LogsConfigurationController.kt +++ /dev/null @@ -1,25 +0,0 @@ -package fr.acinq.phoenix.controllers.config - -import fr.acinq.phoenix.PhoenixBusiness -import fr.acinq.phoenix.controllers.AppController -import fr.acinq.phoenix.utils.PlatformContext -import kotlinx.coroutines.launch -import org.kodein.log.LoggerFactory - - -class AppLogsConfigurationController( - loggerFactory: LoggerFactory, - private val ctx: PlatformContext, -) : AppController( - loggerFactory = loggerFactory, - firstModel = LogsConfiguration.Model.Awaiting -) { - constructor(business: PhoenixBusiness): this( - loggerFactory = business.loggerFactory, - ctx = business.ctx, - ) - - - override fun process(intent: LogsConfiguration.Intent) { - } -} diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/init/InitController.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/init/InitController.kt index cdb2195ae..cbc90f326 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/init/InitController.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/init/InitController.kt @@ -1,10 +1,10 @@ package fr.acinq.phoenix.controllers.init import fr.acinq.bitcoin.MnemonicCode +import fr.acinq.lightning.logging.LoggerFactory import fr.acinq.phoenix.PhoenixBusiness import fr.acinq.phoenix.controllers.AppController import kotlinx.coroutines.launch -import org.kodein.log.LoggerFactory class AppInitController( diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/init/RestoreWalletController.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/init/RestoreWalletController.kt index 6c780e0b1..b4df6a295 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/init/RestoreWalletController.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/init/RestoreWalletController.kt @@ -1,10 +1,11 @@ package fr.acinq.phoenix.controllers.init +import co.touchlab.kermit.Logger import fr.acinq.bitcoin.MnemonicCode +import fr.acinq.lightning.logging.LoggerFactory import fr.acinq.phoenix.PhoenixBusiness import fr.acinq.phoenix.controllers.AppController import kotlinx.coroutines.launch -import org.kodein.log.LoggerFactory class AppRestoreWalletController( diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/main/ContentController.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/main/ContentController.kt index 3d2aedced..7917a3985 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/main/ContentController.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/main/ContentController.kt @@ -1,12 +1,13 @@ package fr.acinq.phoenix.controllers.main +import co.touchlab.kermit.Logger +import fr.acinq.lightning.logging.LoggerFactory import fr.acinq.phoenix.PhoenixBusiness import fr.acinq.phoenix.controllers.AppController import fr.acinq.phoenix.managers.WalletManager import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch -import org.kodein.log.LoggerFactory class AppContentController( diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/main/HomeController.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/main/HomeController.kt index bac96df57..7762b1569 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/main/HomeController.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/main/HomeController.kt @@ -1,11 +1,12 @@ package fr.acinq.phoenix.controllers.main +import co.touchlab.kermit.Logger +import fr.acinq.lightning.logging.LoggerFactory import fr.acinq.phoenix.PhoenixBusiness import fr.acinq.phoenix.controllers.AppController import fr.acinq.phoenix.managers.BalanceManager import fr.acinq.phoenix.managers.PaymentsManager import kotlinx.coroutines.launch -import org.kodein.log.LoggerFactory class AppHomeController( diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/payments/ReceiveController.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/payments/ReceiveController.kt index e03cf1dd1..4cc33d6ac 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/payments/ReceiveController.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/payments/ReceiveController.kt @@ -16,13 +16,14 @@ package fr.acinq.phoenix.controllers.payments +import co.touchlab.kermit.Logger import fr.acinq.lightning.Lightning.randomBytes32 +import fr.acinq.lightning.logging.LoggerFactory import fr.acinq.lightning.utils.Either import fr.acinq.phoenix.PhoenixBusiness import fr.acinq.phoenix.controllers.AppController import fr.acinq.phoenix.managers.PeerManager import kotlinx.coroutines.launch -import org.kodein.log.LoggerFactory class AppReceiveController( diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/payments/ScanController.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/payments/ScanController.kt index 1789dd77c..8f0ce0103 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/payments/ScanController.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/payments/ScanController.kt @@ -16,10 +16,12 @@ package fr.acinq.phoenix.controllers.payments +import co.touchlab.kermit.Logger import fr.acinq.bitcoin.utils.Either import fr.acinq.lightning.* import fr.acinq.lightning.db.LightningOutgoingPayment import fr.acinq.lightning.io.SendPayment +import fr.acinq.lightning.logging.LoggerFactory import fr.acinq.lightning.payment.PaymentRequest import fr.acinq.lightning.utils.* import fr.acinq.phoenix.PhoenixBusiness @@ -30,12 +32,13 @@ import fr.acinq.phoenix.db.payments.WalletPaymentMetadataRow import fr.acinq.phoenix.managers.* import fr.acinq.phoenix.utils.Parser import fr.acinq.phoenix.utils.extensions.chain +import fr.acinq.lightning.logging.error +import fr.acinq.lightning.logging.info import io.ktor.http.Url import kotlinx.coroutines.* import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.first import kotlinx.serialization.json.JsonObject -import org.kodein.log.LoggerFactory import kotlin.time.Duration import kotlin.time.Duration.Companion.seconds import kotlin.time.ExperimentalTime @@ -481,7 +484,7 @@ class AppScanController( /** Reads a lnurl and return either a lnurl-auth (i.e. a http query that must not be called automatically), or the actual url embedded in the lnurl (that can be called afterwards). */ private fun readLnurl(input: String): Lnurl? = try { - Lnurl.extractLnurl(input) + Lnurl.extractLnurl(input, logger) } catch (t: Throwable) { null } @@ -508,7 +511,7 @@ class AppScanController( private fun readLNURLFallback(input: String): Lnurl? = try { val url = Url(input) url.parameters["lightning"]?.let { fallback -> - Lnurl.extractLnurl(fallback) + Lnurl.extractLnurl(fallback, logger) } } catch (t: Throwable) { null diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/data/lnurl/Lnurl.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/data/lnurl/Lnurl.kt index cadc11cdb..488f25006 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/data/lnurl/Lnurl.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/data/lnurl/Lnurl.kt @@ -16,15 +16,17 @@ package fr.acinq.phoenix.data.lnurl +import co.touchlab.kermit.Logger import fr.acinq.bitcoin.Bech32 import fr.acinq.lightning.utils.msat import fr.acinq.phoenix.utils.Parser +import fr.acinq.lightning.logging.debug +import fr.acinq.lightning.logging.error +import fr.acinq.lightning.logging.info import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.utils.io.charsets.* import kotlinx.serialization.json.* -import org.kodein.log.LoggerFactory -import org.kodein.log.newLogger /** * This class describes the various types of Lnurls supported by phoenix: @@ -62,7 +64,6 @@ sealed interface Lnurl { } companion object { - internal val log = newLogger(LoggerFactory.default) internal val format: Json = Json { ignoreUnknownKeys = true } /** @@ -73,22 +74,22 @@ sealed interface Lnurl { * * Throws an exception if the source is malformed or invalid. */ - fun extractLnurl(source: String): Lnurl { + fun extractLnurl(source: String, logger: Logger): Lnurl { val input = Parser.trimMatchingPrefix(source, Parser.lightningPrefixes + Parser.bitcoinPrefixes + Parser.lnurlPrefixes) val url: Url = try { - log.debug { "parsing as lnurl source=$source" } + logger.debug { "parsing as lnurl source=$source" } parseBech32Url(input) } catch (bech32Ex: Exception) { try { if (lud17Schemes.any { input.startsWith(it, ignoreCase = true) }) { - parseNonBech32Lud17(input) + parseNonBech32Lud17(input, logger) } else if (input.contains('@')) { parseInternetIdentifier(input) } else { parseNonBech32Http(input) } } catch (nonBech32Ex: Exception) { - log.info { "cannot parse source as non-bech32 lnurl: ${nonBech32Ex.message ?: nonBech32Ex::class} or as a bech32 lnurl: ${bech32Ex.message ?: bech32Ex::class}" } + logger.info { "cannot parse source as non-bech32 lnurl: ${nonBech32Ex.message ?: nonBech32Ex::class} or as a bech32 lnurl: ${bech32Ex.message ?: bech32Ex::class}" } throw LnurlError.Invalid(cause = nonBech32Ex) } } @@ -145,14 +146,14 @@ sealed interface Lnurl { ) /** Converts LUD-17 lnurls (using a custom lnurl scheme like lnurlc, lnurlp, keyauth) into a regular http url. */ - private fun parseNonBech32Lud17(source: String): Url { + private fun parseNonBech32Lud17(source: String, logger: Logger): Url { val matchingPrefix = lud17Schemes.firstOrNull { source.startsWith(it, ignoreCase = true) } val stripped = if (matchingPrefix != null) { source.drop(matchingPrefix.length) } else { throw IllegalArgumentException("source does not use a lud17 scheme: $source") } - log.debug { "lud-17 scheme found - transforming input into an http request" } + logger.debug { "lud-17 scheme found - transforming input into an http request" } return URLBuilder(stripped).apply { encodedPath.split("/", ignoreCase = true, limit = 2).let { this.host = it.first() @@ -201,7 +202,7 @@ sealed interface Lnurl { * - [LnurlError.RemoteFailure.Unreadable] if response is not valid JSON * - [LnurlError.RemoteFailure.Detailed] if service reports an internal error message (`{ status: "error", reason: "..." }`) */ - suspend fun processLnurlResponse(response: HttpResponse): JsonObject { + suspend fun processLnurlResponse(response: HttpResponse, logger: Logger): JsonObject { val url = response.request.url val json: JsonObject = try { // From the LUD-01 specs: @@ -211,15 +212,15 @@ sealed interface Lnurl { // > response body as JSON, then interpret it accordingly. Json.decodeFromString(response.bodyAsText(Charsets.UTF_8)) } catch (e: Exception) { - log.error(e) { "unhandled response from url=$url: " } + logger.error(e) { "unhandled response from url=$url: " } throw LnurlError.RemoteFailure.Unreadable(url.host) } - log.debug { "lnurl service=${url.host} returned response=${json.toString().take(100)}" } + logger.debug { "lnurl service=${url.host} returned response=${json.toString().take(100)}" } return if (json["status"]?.jsonPrimitive?.content?.trim()?.equals("error", true) == true) { val errorMessage = json["reason"]?.jsonPrimitive?.content?.trim() ?: "" if (errorMessage.isNotEmpty()) { - log.error { "lnurl service=${url.host} returned error=$errorMessage" } + logger.error { "lnurl service=${url.host} returned error=$errorMessage" } throw LnurlError.RemoteFailure.Detailed(url.host, errorMessage.take(90).replace("<", "")) } else if (!response.status.isSuccess()) { throw LnurlError.RemoteFailure.Code(url.host, response.status) diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/data/lnurl/LnurlAuth.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/data/lnurl/LnurlAuth.kt index 9569c4983..ce4279165 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/data/lnurl/LnurlAuth.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/data/lnurl/LnurlAuth.kt @@ -21,7 +21,7 @@ import fr.acinq.bitcoin.crypto.Digest import fr.acinq.bitcoin.crypto.Pack import fr.acinq.bitcoin.crypto.hmac import fr.acinq.lightning.crypto.LocalKeyManager -import fr.acinq.phoenix.data.lnurl.Lnurl.Companion.log +import fr.acinq.lightning.logging.debug import io.ktor.http.* data class LnurlAuth( @@ -116,7 +116,6 @@ data class LnurlAuth( domain: String, hashingKey: ByteArray ): KeyPath { - log.debug { "creating auth derivation path for domain=$domain" } val fullHash = Digest.sha256().hmac( key = hashingKey, data = domain.encodeToByteArray(), diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/data/lnurl/LnurlPay.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/data/lnurl/LnurlPay.kt index eeb356032..74c5b40e7 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/data/lnurl/LnurlPay.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/data/lnurl/LnurlPay.kt @@ -16,13 +16,12 @@ package fr.acinq.phoenix.data.lnurl +import co.touchlab.kermit.Logger import fr.acinq.bitcoin.ByteVector -import fr.acinq.bitcoin.Crypto import fr.acinq.lightning.MilliSatoshi import fr.acinq.lightning.payment.PaymentRequest import fr.acinq.lightning.utils.Try import fr.acinq.phoenix.data.lnurl.Lnurl.Companion.format -import fr.acinq.phoenix.data.lnurl.Lnurl.Companion.log import fr.acinq.phoenix.db.cloud.b64Decode import io.ktor.http.* import kotlinx.serialization.json.* @@ -197,7 +196,7 @@ sealed class LnurlPay : Lnurl.Qualified { else -> unknown.add(it) } } catch (e: Exception) { - log.warning { "could not decode raw meta=$it: ${e.message}" } + Logger.w("LnurlPay") { "could not decode raw lnurlpay-meta=$it: ${e.message}" } } } LnurlPay.Intent.Metadata( @@ -213,7 +212,7 @@ sealed class LnurlPay : Lnurl.Qualified { } ) } catch (e: Exception) { - log.error(e) { "could not decode raw meta=$raw: " } + Logger.e("LnurlPay") { "could not decode raw lnurlpay-meta=$raw: ${e.message}" } throw LnurlError.Pay.Intent.InvalidMetadata(raw) } } diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/db/SqlitePaymentsDb.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/db/SqlitePaymentsDb.kt index fd33a8c6b..001f45f3f 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/db/SqlitePaymentsDb.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/db/SqlitePaymentsDb.kt @@ -16,17 +16,16 @@ package fr.acinq.phoenix.db +import co.touchlab.kermit.Logger import com.squareup.sqldelight.EnumColumnAdapter import com.squareup.sqldelight.db.SqlDriver import com.squareup.sqldelight.runtime.coroutines.asFlow -import com.squareup.sqldelight.runtime.coroutines.mapToList -import com.squareup.sqldelight.runtime.coroutines.mapToOne import fr.acinq.bitcoin.ByteVector32 import fr.acinq.bitcoin.Crypto import fr.acinq.bitcoin.TxId -import fr.acinq.lightning.MilliSatoshi import fr.acinq.lightning.channel.ChannelException import fr.acinq.lightning.db.* +import fr.acinq.lightning.logging.LoggerFactory import fr.acinq.lightning.payment.FinalFailure import fr.acinq.lightning.utils.* import fr.acinq.lightning.wire.FailureMessage @@ -43,8 +42,6 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.map import kotlinx.coroutines.withContext -import org.kodein.log.LoggerFactory -import org.kodein.log.newLogger class SqlitePaymentsDb( loggerFactory: LoggerFactory, @@ -52,7 +49,7 @@ class SqlitePaymentsDb( private val currencyManager: CurrencyManager? = null ) : PaymentsDb { - private val log = newLogger(loggerFactory) + private val log = loggerFactory.newLogger(this::class) private val database = PaymentsDatabase( driver = driver, diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/AppConfigurationManager.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/AppConfigurationManager.kt index 4bd0e5086..3a76dc35c 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/AppConfigurationManager.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/AppConfigurationManager.kt @@ -5,12 +5,15 @@ import fr.acinq.lightning.blockchain.electrum.ElectrumWatcher import fr.acinq.lightning.blockchain.electrum.HeaderSubscriptionResponse import fr.acinq.lightning.blockchain.fee.FeeratePerByte import fr.acinq.lightning.io.TcpSocket +import fr.acinq.lightning.logging.LoggerFactory import fr.acinq.lightning.utils.ServerAddress import fr.acinq.lightning.utils.currentTimestampMillis import fr.acinq.lightning.utils.sat import fr.acinq.phoenix.PhoenixBusiness import fr.acinq.phoenix.data.* import fr.acinq.phoenix.db.SqliteAppDb +import fr.acinq.lightning.logging.debug +import fr.acinq.lightning.logging.error import io.ktor.client.* import io.ktor.client.request.* import io.ktor.client.statement.* @@ -20,8 +23,6 @@ import io.ktor.utils.io.core.* import kotlinx.coroutines.* import kotlinx.coroutines.flow.* import kotlinx.serialization.json.* -import org.kodein.log.LoggerFactory -import org.kodein.log.newLogger import kotlin.math.* import kotlin.time.* import kotlin.time.Duration.Companion.minutes @@ -43,7 +44,7 @@ class AppConfigurationManager( electrumWatcher = business.electrumWatcher, ) - private val logger = newLogger(loggerFactory) + private val logger = loggerFactory.newLogger(this::class) init { watchElectrumMessages() diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/AppConnectionsDaemon.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/AppConnectionsDaemon.kt index 6b2b5e989..c66cc20cc 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/AppConnectionsDaemon.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/AppConnectionsDaemon.kt @@ -2,11 +2,15 @@ package fr.acinq.phoenix.managers import fr.acinq.lightning.blockchain.electrum.ElectrumClient import fr.acinq.lightning.io.TcpSocket +import fr.acinq.lightning.logging.LoggerFactory import fr.acinq.lightning.utils.Connection import fr.acinq.lightning.utils.ServerAddress import fr.acinq.phoenix.PhoenixBusiness import fr.acinq.phoenix.data.ElectrumConfig import fr.acinq.phoenix.utils.TorHelper.connectionState +import fr.acinq.lightning.logging.debug +import fr.acinq.lightning.logging.error +import fr.acinq.lightning.logging.info import fr.acinq.tor.Tor import fr.acinq.tor.TorState import kotlinx.coroutines.* @@ -19,8 +23,6 @@ import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn -import org.kodein.log.LoggerFactory -import org.kodein.log.newLogger import kotlin.time.Duration import kotlin.time.Duration.Companion.seconds @@ -49,7 +51,7 @@ class AppConnectionsDaemon( electrumClient = business.electrumClient ) - private val logger = newLogger(loggerFactory) + private val logger = loggerFactory.newLogger(this::class) private var peerConnectionJob: Job? = null private var electrumConnectionJob: Job? = null diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/BalanceManager.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/BalanceManager.kt index 3ee27e509..91d87393c 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/BalanceManager.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/BalanceManager.kt @@ -8,17 +8,17 @@ import fr.acinq.lightning.blockchain.electrum.balance import fr.acinq.lightning.channel.states.ChannelState import fr.acinq.lightning.channel.states.PersistedChannelState import fr.acinq.lightning.io.Peer +import fr.acinq.lightning.logging.LoggerFactory import fr.acinq.lightning.utils.msat import fr.acinq.lightning.utils.sat import fr.acinq.lightning.utils.sum import fr.acinq.phoenix.PhoenixBusiness import fr.acinq.phoenix.utils.extensions.localBalance +import fr.acinq.lightning.logging.debug import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.MainScope import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch -import org.kodein.log.LoggerFactory -import org.kodein.log.newLogger class BalanceManager( loggerFactory: LoggerFactory, @@ -32,7 +32,7 @@ class BalanceManager( databaseManager = business.databaseManager ) - private val log = newLogger(loggerFactory) + private val log = loggerFactory.newLogger(this::class) /** The aggregated channels' balance. This is the user's LN funds in the wallet. See [ChannelState.localBalance] */ private val _balance = MutableStateFlow(null) diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/CurrencyManager.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/CurrencyManager.kt index f457d155b..833e72fa4 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/CurrencyManager.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/CurrencyManager.kt @@ -1,8 +1,12 @@ package fr.acinq.phoenix.managers +import fr.acinq.lightning.logging.LoggerFactory import fr.acinq.phoenix.PhoenixBusiness import fr.acinq.phoenix.data.* import fr.acinq.phoenix.db.SqliteAppDb +import fr.acinq.lightning.logging.debug +import fr.acinq.lightning.logging.error +import fr.acinq.lightning.logging.info import io.ktor.client.* import io.ktor.client.call.* import io.ktor.client.request.* @@ -11,10 +15,7 @@ import kotlinx.coroutines.* import kotlinx.coroutines.flow.* import kotlinx.datetime.Clock import kotlinx.datetime.Instant -import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json -import org.kodein.log.LoggerFactory -import org.kodein.log.newLogger import kotlin.time.Duration import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.seconds @@ -54,7 +55,7 @@ class CurrencyManager( httpClient = business.httpClient ) - private val log = newLogger(loggerFactory) + private val log = loggerFactory.newLogger(this::class) private val json = Json { ignoreUnknownKeys = true diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/DatabaseManager.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/DatabaseManager.kt index cb4858b9a..ab6563f47 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/DatabaseManager.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/DatabaseManager.kt @@ -1,22 +1,25 @@ package fr.acinq.phoenix.managers +import co.touchlab.kermit.Logger +import co.touchlab.kermit.Severity +import co.touchlab.kermit.StaticConfig import fr.acinq.bitcoin.byteVector import fr.acinq.lightning.NodeParams import fr.acinq.lightning.db.ChannelsDb import fr.acinq.lightning.db.Databases import fr.acinq.lightning.db.PaymentsDb +import fr.acinq.lightning.logging.LoggerFactory import fr.acinq.phoenix.PhoenixBusiness import fr.acinq.phoenix.db.SqliteChannelsDb import fr.acinq.phoenix.db.SqlitePaymentsDb import fr.acinq.phoenix.db.createChannelsDbDriver import fr.acinq.phoenix.db.createPaymentsDbDriver import fr.acinq.phoenix.utils.PlatformContext +import fr.acinq.lightning.logging.debug import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.MainScope import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch -import org.kodein.log.LoggerFactory -import org.kodein.log.newLogger class DatabaseManager( loggerFactory: LoggerFactory, @@ -34,8 +37,7 @@ class DatabaseManager( currencyManager = business.currencyManager ) - private val log = newLogger(loggerFactory) - + private val log = loggerFactory.newLogger(this::class) private val _databases = MutableStateFlow(null) val databases: StateFlow = _databases @@ -50,7 +52,7 @@ class DatabaseManager( driver = createChannelsDbDriver(ctx, chain, nodeIdHash) ) val paymentsDb = SqlitePaymentsDb( - loggerFactory, + loggerFactory = loggerFactory, driver = createPaymentsDbDriver(ctx, chain, nodeIdHash), currencyManager = currencyManager ) diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/LnurlManager.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/LnurlManager.kt index 9ee2f8f96..08aaa625b 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/LnurlManager.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/LnurlManager.kt @@ -17,9 +17,11 @@ package fr.acinq.phoenix.managers import fr.acinq.lightning.MilliSatoshi +import fr.acinq.lightning.logging.LoggerFactory import fr.acinq.lightning.payment.PaymentRequest import fr.acinq.phoenix.PhoenixBusiness import fr.acinq.phoenix.data.lnurl.* +import fr.acinq.lightning.logging.error import io.ktor.client.* import io.ktor.client.plugins.contentnegotiation.* import io.ktor.client.request.* @@ -34,8 +36,7 @@ import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.first import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonObject -import org.kodein.log.LoggerFactory -import org.kodein.log.newLogger + class LnurlManager( loggerFactory: LoggerFactory, @@ -57,7 +58,7 @@ class LnurlManager( walletManager = business.walletManager ) - private val log = newLogger(loggerFactory) + private val log = loggerFactory.newLogger(this::class) /** Executes an HTTP GET request on the provided url and parses the JSON response into an [Lnurl] object. */ fun executeLnurl(url: Url): Deferred = async { @@ -67,7 +68,7 @@ class LnurlManager( throw LnurlError.RemoteFailure.CouldNotConnect(origin = url.host) } try { - val json = Lnurl.processLnurlResponse(response) + val json = Lnurl.processLnurlResponse(response, log) return@async Lnurl.parseLnurlJson(url, json) } catch (e: Exception) { when (e) { @@ -105,7 +106,7 @@ class LnurlManager( throw LnurlError.RemoteFailure.CouldNotConnect(origin) } - val json = Lnurl.processLnurlResponse(response) + val json = Lnurl.processLnurlResponse(response, log) val invoice = LnurlPay.parseLnurlPayInvoice(intent, origin, json) // SPECS: LN WALLET verifies that the amount in the provided invoice equals the amount previously specified by user. @@ -140,7 +141,7 @@ class LnurlManager( // SPECS: even if the response is an error, the invoice may still be paid by the service // we still parse the response to see what's up. - Lnurl.processLnurlResponse(response) + Lnurl.processLnurlResponse(response, log) } suspend fun signAndSendAuthRequest( @@ -165,7 +166,7 @@ class LnurlManager( throw LnurlError.RemoteFailure.CouldNotConnect(origin = url.host) } - Lnurl.processLnurlResponse(response) // throws on any/all non-success + Lnurl.processLnurlResponse(response, log) // throws on any/all non-success } } diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/NetworkMonitor.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/NetworkMonitor.kt index 60ee1f934..1263fe2f0 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/NetworkMonitor.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/NetworkMonitor.kt @@ -2,7 +2,7 @@ package fr.acinq.phoenix.managers import fr.acinq.phoenix.utils.PlatformContext import kotlinx.coroutines.flow.StateFlow -import org.kodein.log.LoggerFactory +import fr.acinq.lightning.logging.LoggerFactory enum class NetworkState { Available, diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/NodeParamsManager.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/NodeParamsManager.kt index f4ee63591..e8fd40784 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/NodeParamsManager.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/NodeParamsManager.kt @@ -20,18 +20,19 @@ import fr.acinq.bitcoin.PublicKey import fr.acinq.bitcoin.Satoshi import fr.acinq.lightning.NodeParams import fr.acinq.lightning.NodeUri +import fr.acinq.lightning.logging.LoggerFactory import fr.acinq.lightning.payment.LiquidityPolicy import fr.acinq.lightning.utils.msat import fr.acinq.lightning.utils.sat import fr.acinq.lightning.wire.LiquidityAds import fr.acinq.phoenix.PhoenixBusiness import fr.acinq.phoenix.shared.BuildVersions +import fr.acinq.lightning.logging.info import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.MainScope import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch -import org.kodein.log.LoggerFactory -import org.kodein.log.newLogger + class NodeParamsManager( loggerFactory: LoggerFactory, @@ -47,7 +48,7 @@ class NodeParamsManager( appConfigurationManager = business.appConfigurationManager, ) - private val log = newLogger(loggerFactory) + private val log = loggerFactory.newLogger(this::class) private val _nodeParams = MutableStateFlow(null) val nodeParams: StateFlow = _nodeParams diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/NotificationsManager.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/NotificationsManager.kt index 0a7ef1143..e13f7b53b 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/NotificationsManager.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/NotificationsManager.kt @@ -17,19 +17,19 @@ package fr.acinq.phoenix.managers import fr.acinq.lightning.LiquidityEvents +import fr.acinq.lightning.logging.LoggerFactory import fr.acinq.lightning.utils.UUID import fr.acinq.lightning.utils.currentTimestampMillis import fr.acinq.phoenix.PhoenixBusiness import fr.acinq.phoenix.data.Notification import fr.acinq.phoenix.data.WatchTowerOutcome import fr.acinq.phoenix.db.SqliteAppDb +import fr.acinq.lightning.logging.debug import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.MainScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch -import org.kodein.log.LoggerFactory -import org.kodein.log.newLogger class NotificationsManager( private val loggerFactory: LoggerFactory, @@ -41,7 +41,7 @@ class NotificationsManager( appDb = business.appDb, ) - private val log = newLogger(loggerFactory) + private val log = loggerFactory.newLogger(this::class) private val _notifications = MutableStateFlow, Notification>>>(emptyList()) /** diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/PaymentsFetcher.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/PaymentsFetcher.kt index 3686e7c35..f2068f455 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/PaymentsFetcher.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/PaymentsFetcher.kt @@ -1,14 +1,14 @@ package fr.acinq.phoenix.managers +import fr.acinq.lightning.logging.LoggerFactory import fr.acinq.phoenix.data.WalletPaymentFetchOptions import fr.acinq.phoenix.data.WalletPaymentInfo import fr.acinq.phoenix.db.WalletPaymentOrderRow import fr.acinq.phoenix.utils.Cache +import fr.acinq.lightning.logging.debug import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.MainScope import kotlinx.coroutines.launch -import org.kodein.log.LoggerFactory -import org.kodein.log.newLogger import kotlin.coroutines.Continuation import kotlin.coroutines.suspendCoroutine @@ -39,7 +39,7 @@ class PaymentsFetcher( val info: WalletPaymentInfo? ) - private val log = newLogger(loggerFactory) + private val log = loggerFactory.newLogger(this::class) // Using a strict cache to ensure eviction based on actual usage private var cache = Cache(sizeLimit = cacheSizeLimit) diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/PaymentsManager.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/PaymentsManager.kt index 2e0b4b7e9..b4e2497d1 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/PaymentsManager.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/PaymentsManager.kt @@ -1,20 +1,17 @@ package fr.acinq.phoenix.managers -import fr.acinq.bitcoin.ByteVector32 import fr.acinq.bitcoin.TxId -import fr.acinq.bitcoin.byteVector32 import fr.acinq.lightning.blockchain.electrum.ElectrumClient import fr.acinq.lightning.blockchain.electrum.getConfirmations import fr.acinq.lightning.db.InboundLiquidityOutgoingPayment import fr.acinq.lightning.db.SpliceCpfpOutgoingPayment import fr.acinq.lightning.db.WalletPayment -import fr.acinq.lightning.io.PaymentNotSent -import fr.acinq.lightning.io.PaymentProgress -import fr.acinq.lightning.io.PaymentSent +import fr.acinq.lightning.logging.LoggerFactory import fr.acinq.lightning.utils.* import fr.acinq.phoenix.PhoenixBusiness import fr.acinq.phoenix.data.* import fr.acinq.phoenix.db.SqlitePaymentsDb +import fr.acinq.lightning.logging.debug import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.MainScope import kotlinx.coroutines.flow.MutableStateFlow @@ -22,8 +19,6 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.collectIndexed import kotlinx.coroutines.flow.combine import kotlinx.coroutines.launch -import org.kodein.log.LoggerFactory -import org.kodein.log.newLogger class PaymentsManager( @@ -42,7 +37,7 @@ class PaymentsManager( electrumClient = business.electrumClient ) - private val log = newLogger(loggerFactory) + private val log = loggerFactory.newLogger(this::class) /** * A flow containing the total number of payments in the database, diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/PaymentsPageFetcher.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/PaymentsPageFetcher.kt index e1e2c010a..7eb479b13 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/PaymentsPageFetcher.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/PaymentsPageFetcher.kt @@ -1,13 +1,13 @@ package fr.acinq.phoenix.managers +import fr.acinq.lightning.logging.LoggerFactory import fr.acinq.phoenix.db.WalletPaymentOrderRow +import fr.acinq.lightning.logging.debug import kotlinx.coroutines.* import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.datetime.Clock import kotlinx.datetime.Instant -import org.kodein.log.LoggerFactory -import org.kodein.log.newLogger import kotlin.time.Duration.Companion.seconds data class PaymentsPage( @@ -32,7 +32,7 @@ class PaymentsPageFetcher( private val databaseManager: DatabaseManager ): CoroutineScope by MainScope() { - private val log = newLogger(loggerFactory) + private val log = loggerFactory.newLogger(this::class) private var offset: Int = 0 private var count: Int = 0 diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/PeerManager.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/PeerManager.kt index 2fe8661fb..168bd8af0 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/PeerManager.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/PeerManager.kt @@ -18,6 +18,7 @@ import fr.acinq.lightning.channel.states.ChannelStateWithCommitments import fr.acinq.lightning.channel.states.Normal import fr.acinq.lightning.channel.states.Offline import fr.acinq.lightning.io.Peer +import fr.acinq.lightning.logging.LoggerFactory import fr.acinq.lightning.payment.LiquidityPolicy import fr.acinq.lightning.utils.Connection import fr.acinq.lightning.utils.msat @@ -28,11 +29,12 @@ import fr.acinq.phoenix.PhoenixBusiness import fr.acinq.phoenix.data.LocalChannelInfo import fr.acinq.phoenix.utils.extensions.isTerminated import fr.acinq.phoenix.utils.extensions.nextTimeout +import fr.acinq.lightning.logging.debug +import fr.acinq.lightning.logging.error +import fr.acinq.lightning.logging.info import kotlinx.coroutines.* import kotlinx.coroutines.flow.* -import org.kodein.log.Logger -import org.kodein.log.LoggerFactory -import org.kodein.log.newLogger + class PeerManager( loggerFactory: LoggerFactory, @@ -43,7 +45,7 @@ class PeerManager( private val electrumWatcher: ElectrumWatcher, ) : CoroutineScope by CoroutineScope(CoroutineName("peer") + SupervisorJob() + Dispatchers.Main + CoroutineExceptionHandler { _, e -> println("error in Peer coroutine scope: ${e.message}") - val logger = loggerFactory.newLogger(Logger.Tag(PeerManager::class)) + val logger = loggerFactory.newLogger("PeerManager") logger.error(e) { "error in Peer scope: " } }) { @@ -56,7 +58,7 @@ class PeerManager( electrumWatcher = business.electrumWatcher, ) - private val logger = newLogger(loggerFactory) + private val logger = loggerFactory.newLogger(this::class) private val _peer = MutableStateFlow(null) val peerState: StateFlow = _peer diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/Socks5Proxy.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/Socks5Proxy.kt index cdf0b1015..43dfc592c 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/Socks5Proxy.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/Socks5Proxy.kt @@ -17,10 +17,10 @@ package fr.acinq.phoenix.utils import fr.acinq.lightning.io.TcpSocket +import fr.acinq.lightning.logging.LoggerFactory +import fr.acinq.lightning.logging.info import fr.acinq.tor.Tor import fr.acinq.tor.socks.socks5Handshake -import org.kodein.log.LoggerFactory -import org.kodein.log.newLogger class Socks5Proxy( private val socketBuilder: TcpSocket.Builder, @@ -29,9 +29,14 @@ class Socks5Proxy( private val proxyPort: Int ): TcpSocket.Builder { - val logger = newLogger(loggerFactory) + val logger = loggerFactory.newLogger(this::class) - override suspend fun connect(host: String, port: Int, tls: TcpSocket.TLS, loggerFactory: LoggerFactory): TcpSocket { + override suspend fun connect( + host: String, + port: Int, + tls: TcpSocket.TLS, + loggerFactory: LoggerFactory, + ): TcpSocket { val socket = socketBuilder.connect(proxyHost, proxyPort, TcpSocket.TLS.DISABLED, loggerFactory) val (cHost, cPort) = socks5Handshake( destinationHost = host, @@ -49,4 +54,11 @@ class Socks5Proxy( } } -fun TcpSocket.Builder.torProxy(loggerFactory: LoggerFactory) = Socks5Proxy(this, loggerFactory, Tor.SOCKS_ADDRESS, Tor.SOCKS_PORT) +fun TcpSocket.Builder.torProxy( + loggerFactory: LoggerFactory +) = Socks5Proxy( + socketBuilder = this, + loggerFactory = loggerFactory, + proxyHost = Tor.SOCKS_ADDRESS, + proxyPort = Tor.SOCKS_PORT +) diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/TorHelper.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/TorHelper.kt index 9cfdd06dc..d87d3254e 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/TorHelper.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/TorHelper.kt @@ -1,19 +1,22 @@ package fr.acinq.phoenix.utils import fr.acinq.lightning.utils.Connection +import fr.acinq.lightning.logging.LoggerFactory +import fr.acinq.lightning.logging.debug +import fr.acinq.lightning.logging.error +import fr.acinq.lightning.logging.info +import fr.acinq.lightning.logging.warning import fr.acinq.tor.Tor import fr.acinq.tor.TorState import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.stateIn -import org.kodein.log.LoggerFactory -import org.kodein.log.newLogger + object TorHelper { fun torLogger(loggerFactory: LoggerFactory): (Tor.LogLevel, String) -> Unit { - val logger = loggerFactory.newLogger(Tor::class) + val logger = loggerFactory.newLogger("Tor") return { level, message -> when (level) { Tor.LogLevel.DEBUG -> logger.debug { message } diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/import/ChannelsImportHelper.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/import/ChannelsImportHelper.kt index cb1a73784..29121004a 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/import/ChannelsImportHelper.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/import/ChannelsImportHelper.kt @@ -6,10 +6,10 @@ import fr.acinq.lightning.serialization.Encryption.from import fr.acinq.lightning.serialization.Serialization import fr.acinq.lightning.wire.EncryptedChannelData import fr.acinq.phoenix.PhoenixBusiness +import fr.acinq.lightning.logging.error import fr.acinq.secp256k1.Hex import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.first -import org.kodein.log.newLogger object ChannelsImportHelper { diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/logger/LoggerConfig.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/logger/LoggerConfig.kt new file mode 100644 index 000000000..dc75c5e05 --- /dev/null +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/logger/LoggerConfig.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2024 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package fr.acinq.phoenix.utils.logger + +import co.touchlab.kermit.LogWriter +import co.touchlab.kermit.LoggerConfig +import co.touchlab.kermit.Severity +import co.touchlab.kermit.StaticConfig +import fr.acinq.phoenix.utils.PlatformContext + +/** + * Contains a logging configuration. + * Not an object, because the platform context is required for the log writers, which are platform dependent. + * + * Would have used [StaticConfig] but it cannot be extended. + */ +data class PhoenixLoggerConfig(private val platformContext: PlatformContext): LoggerConfig { + override val logWriterList: List = phoenixLogWriters(platformContext) + override val minSeverity: Severity = Severity.Debug +} + +/** + * Factory function to return a default list of LogWriters for each platform. The LogWriter is targeted at local development. + * For production implementations, you may need to directly initialize your Logger config. + */ +expect fun phoenixLogWriters(ctx: PlatformContext): List \ No newline at end of file diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/migrations/IosMigrationHelper.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/migrations/IosMigrationHelper.kt index 0f782dd3d..f7d2ae17f 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/migrations/IosMigrationHelper.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/migrations/IosMigrationHelper.kt @@ -27,17 +27,16 @@ import fr.acinq.lightning.channel.states.* import fr.acinq.lightning.io.WrappedChannelCommand import fr.acinq.lightning.utils.msat import fr.acinq.lightning.utils.sum -import fr.acinq.lightning.utils.toMilliSatoshi import fr.acinq.phoenix.PhoenixBusiness import fr.acinq.phoenix.data.LocalChannelInfo import fr.acinq.phoenix.utils.Parser import fr.acinq.phoenix.utils.extensions.isBeingCreated -import fr.acinq.phoenix.utils.extensions.localBalance +import fr.acinq.lightning.logging.info +import fr.acinq.lightning.logging.warning import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map -import org.kodein.log.newLogger object IosMigrationHelper { diff --git a/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/TestConstants.kt b/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/TestConstants.kt index 063a35c20..d32d3ee28 100644 --- a/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/TestConstants.kt +++ b/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/TestConstants.kt @@ -26,11 +26,11 @@ import fr.acinq.lightning.crypto.LocalKeyManager import fr.acinq.lightning.utils.msat import fr.acinq.lightning.utils.sat import fr.acinq.lightning.utils.toByteVector32 +import fr.acinq.phoenix.utils.testLoggerFactory import fr.acinq.secp256k1.Hex import kotlinx.coroutines.* import kotlin.time.Duration import kotlin.time.Duration.Companion.seconds -import org.kodein.log.LoggerFactory object TestConstants { @@ -42,7 +42,7 @@ object TestConstants { val keyManager = LocalKeyManager(seed, NodeParams.Chain.Regtest, swapInServerXpub) val nodeParams = NodeParams( chain = NodeParams.Chain.Regtest, - loggerFactory = LoggerFactory.default, + loggerFactory = testLoggerFactory, keyManager = keyManager, ).copy( alias = "bob", diff --git a/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/data/ElectrumServersTest.kt b/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/data/ElectrumServersTest.kt index 4c1c30ad0..61c249409 100644 --- a/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/data/ElectrumServersTest.kt +++ b/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/data/ElectrumServersTest.kt @@ -5,10 +5,10 @@ import fr.acinq.lightning.blockchain.electrum.ElectrumConnectionStatus import fr.acinq.lightning.blockchain.fee.FeeratePerByte import fr.acinq.lightning.io.TcpSocket import fr.acinq.lightning.utils.ServerAddress +import fr.acinq.phoenix.utils.testLoggerFactory import kotlinx.coroutines.* import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.first -import org.kodein.log.LoggerFactory import kotlin.test.Ignore import kotlin.test.Test import kotlin.test.assertTrue @@ -48,7 +48,7 @@ class ElectrumServersTest { fun connect_and_get_fee_mainnet() = runBlocking { val res = mainnetElectrumServers.map { server -> try { - val client = ElectrumClient(scope = this, loggerFactory = LoggerFactory.default, pingInterval = 30.seconds, rpcTimeout = 5.seconds) + val client = ElectrumClient(scope = this, loggerFactory = testLoggerFactory, pingInterval = 30.seconds, rpcTimeout = 5.seconds) client.connect(socketBuilder = TcpSocket.Builder(), serverAddress = server) withTimeout(5.seconds) { client.connectionStatus.filterIsInstance().first() diff --git a/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/data/lnurl/LnurlPayTest.kt b/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/data/lnurl/LnurlPayTest.kt index cea108db4..4e5fa6df8 100644 --- a/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/data/lnurl/LnurlPayTest.kt +++ b/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/data/lnurl/LnurlPayTest.kt @@ -1,6 +1,7 @@ package fr.acinq.phoenix.data.lnurl import fr.acinq.lightning.utils.msat +import fr.acinq.phoenix.utils.testLoggerFactory import io.ktor.client.* import io.ktor.client.engine.mock.* import io.ktor.client.plugins.contentnegotiation.* @@ -19,6 +20,8 @@ import kotlin.test.assertTrue class LnurlPayTest { + val logger = testLoggerFactory.newLogger(this::class) + private val validContent = """ { "callback":"https://lnurl.fiatjaf.com/lnurl-pay/callback/0abd4cdb7b0b62e50d5a3e8704287049b3a6dff50f40ff5db821955cca00791b", @@ -55,7 +58,7 @@ class LnurlPayTest { ) } val response: HttpResponse = fakeClient(engine).get("https://acinq.co") - val json = Lnurl.processLnurlResponse(response) + val json = Lnurl.processLnurlResponse(response, logger) assertEquals("payRequest", json.get("tag")!!.jsonPrimitive.content) val lnurl = Lnurl.parseLnurlJson(Url("https://acinq.co"), json) @@ -79,7 +82,7 @@ class LnurlPayTest { ) } val response: HttpResponse = fakeClient(engine).get("https://acinq.co") - val json = Lnurl.processLnurlResponse(response) + val json = Lnurl.processLnurlResponse(response, logger) assertEquals("payRequest", json.get("tag")!!.jsonPrimitive.content) val lnurl = Lnurl.parseLnurlJson(Url("https://acinq.co"), json) @@ -114,10 +117,10 @@ class LnurlPayTest { ) } val client = fakeClient(engine) - val lnurl = Lnurl.extractLnurl("acinq@zbd.gg") + val lnurl = Lnurl.extractLnurl("acinq@zbd.gg", logger) assertIs(lnurl) val response: HttpResponse = client.get(lnurl.initialUrl) - val json = Lnurl.processLnurlResponse(response) + val json = Lnurl.processLnurlResponse(response, logger) assertEquals("payRequest", json.get("tag")!!.jsonPrimitive.content) } } @@ -126,30 +129,30 @@ class LnurlPayTest { @Test fun bech32() { - assertIs(Lnurl.extractLnurl(validBech32Lnurl)) - assertIs(Lnurl.extractLnurl("lightning://$validBech32Lnurl")) - assertIs(Lnurl.extractLnurl("lightning:$validBech32Lnurl")) - assertIs(Lnurl.extractLnurl("lnurl://$validBech32Lnurl")) - assertIs(Lnurl.extractLnurl("lnurl:$validBech32Lnurl")) + assertIs(Lnurl.extractLnurl(validBech32Lnurl, logger)) + assertIs(Lnurl.extractLnurl("lightning://$validBech32Lnurl", logger)) + assertIs(Lnurl.extractLnurl("lightning:$validBech32Lnurl", logger)) + assertIs(Lnurl.extractLnurl("lnurl://$validBech32Lnurl", logger)) + assertIs(Lnurl.extractLnurl("lnurl:$validBech32Lnurl", logger)) } @Test fun lud17() { val validClearLud17 = "acinq.co/lnurlpay/token123-abc?some-parameter=USD" - assertIs(Lnurl.extractLnurl("phoenix:lnurlp://$validClearLud17")) - assertIs(Lnurl.extractLnurl("lnurlp://$validClearLud17")) - assertIs(Lnurl.extractLnurl("lnurlp:$validClearLud17")) - assertTrue { Lnurl.extractLnurl("lnurlp:$validClearLud17").initialUrl.protocol.isSecure() } + assertIs(Lnurl.extractLnurl("phoenix:lnurlp://$validClearLud17", logger)) + assertIs(Lnurl.extractLnurl("lnurlp://$validClearLud17", logger)) + assertIs(Lnurl.extractLnurl("lnurlp:$validClearLud17", logger)) + assertTrue { Lnurl.extractLnurl("lnurlp:$validClearLud17", logger).initialUrl.protocol.isSecure() } val validOnionLud17 = "lnurlp://acinq.onion/lnurlpay/token123-abc?some-parameter=USD" - assertIs(Lnurl.extractLnurl(validOnionLud17)) - assertTrue { !Lnurl.extractLnurl(validOnionLud17).initialUrl.protocol.isSecure() } + assertIs(Lnurl.extractLnurl(validOnionLud17, logger)) + assertTrue { !Lnurl.extractLnurl(validOnionLud17, logger).initialUrl.protocol.isSecure() } } @Test fun lnurl_in_http_param() { - assertIs(Lnurl.extractLnurl("https://acinq.co?param1=123&lightning=$validBech32Lnurl")) - assertIs(Lnurl.extractLnurl("http://service.com/api/test?lightning=$validBech32Lnurl")) - assertIs(Lnurl.extractLnurl("test://whatever/token?lightning=$validBech32Lnurl")) + assertIs(Lnurl.extractLnurl("https://acinq.co?param1=123&lightning=$validBech32Lnurl", logger)) + assertIs(Lnurl.extractLnurl("http://service.com/api/test?lightning=$validBech32Lnurl", logger)) + assertIs(Lnurl.extractLnurl("test://whatever/token?lightning=$validBech32Lnurl", logger)) } } \ No newline at end of file diff --git a/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/data/lnurl/LnurlWithdrawTest.kt b/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/data/lnurl/LnurlWithdrawTest.kt index 854d95865..d723462ed 100644 --- a/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/data/lnurl/LnurlWithdrawTest.kt +++ b/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/data/lnurl/LnurlWithdrawTest.kt @@ -1,11 +1,14 @@ package fr.acinq.phoenix.data.lnurl import fr.acinq.lightning.utils.msat +import fr.acinq.phoenix.utils.testLoggerFactory import io.ktor.http.* import kotlinx.serialization.json.* import kotlin.test.* class LnurlWithdrawTest { + val logger = testLoggerFactory.newLogger(this::class) + private val defaultLnurl = URLBuilder("https://lnurl.service.com/withdraw/token12345").build() @Test @@ -139,19 +142,19 @@ class LnurlWithdrawTest { @Test fun test_extractLnurl_ignores_unknown_tag() { - val lnurl = Lnurl.extractLnurl("$defaultLnurl?tag=withdraw") + val lnurl = Lnurl.extractLnurl("$defaultLnurl?tag=withdraw", logger) assertIs(lnurl) } @Test fun lud17() { val validClearLud17 = "acinq.co/lnurlwithdraw/token123-abc?some-parameter=USD" - assertIs(Lnurl.extractLnurl("lnurlw://$validClearLud17")) - assertIs(Lnurl.extractLnurl("lnurlw:$validClearLud17")) - assertTrue { Lnurl.extractLnurl("lnurlw:$validClearLud17").initialUrl.protocol.isSecure() } + assertIs(Lnurl.extractLnurl("lnurlw://$validClearLud17", logger)) + assertIs(Lnurl.extractLnurl("lnurlw:$validClearLud17", logger)) + assertTrue { Lnurl.extractLnurl("lnurlw:$validClearLud17", logger).initialUrl.protocol.isSecure() } val validOnionLud17 = "lnurlw://acinq.onion/lnurlwithdraw/token123-abc?some-parameter=USD" - assertIs(Lnurl.extractLnurl(validOnionLud17)) - assertTrue { !Lnurl.extractLnurl(validOnionLud17).initialUrl.protocol.isSecure() } + assertIs(Lnurl.extractLnurl(validOnionLud17, logger)) + assertTrue { !Lnurl.extractLnurl(validOnionLud17, logger).initialUrl.protocol.isSecure() } } } diff --git a/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/db/SqlitePaymentsDatabaseTest.kt b/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/db/SqlitePaymentsDatabaseTest.kt index 5bd084017..7481789c6 100644 --- a/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/db/SqlitePaymentsDatabaseTest.kt +++ b/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/db/SqlitePaymentsDatabaseTest.kt @@ -30,12 +30,12 @@ import fr.acinq.lightning.wire.TemporaryNodeFailure import fr.acinq.phoenix.data.WalletPaymentFetchOptions import fr.acinq.phoenix.runTest import fr.acinq.phoenix.utils.migrations.LegacyChannelCloseHelper +import fr.acinq.phoenix.utils.testLoggerFactory import fr.acinq.secp256k1.Hex -import org.kodein.log.LoggerFactory import kotlin.test.* class SqlitePaymentsDatabaseTest { - private val db = SqlitePaymentsDb(LoggerFactory.default, testPaymentsDriver()) + private val db = SqlitePaymentsDb(testLoggerFactory, testPaymentsDriver()) private val preimage1 = randomBytes32() private val paymentHash1 = Crypto.sha256(preimage1).toByteVector32() diff --git a/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/utils/TestLoggerFactory.kt b/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/utils/TestLoggerFactory.kt new file mode 100644 index 000000000..22ccf1a3a --- /dev/null +++ b/phoenix-shared/src/commonTest/kotlin/fr/acinq/phoenix/utils/TestLoggerFactory.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2024 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package fr.acinq.phoenix.utils + +import co.touchlab.kermit.CommonWriter +import co.touchlab.kermit.NoTagFormatter +import co.touchlab.kermit.Severity +import co.touchlab.kermit.loggerConfigInit +import fr.acinq.lightning.logging.LoggerFactory + +val testLoggerFactory: LoggerFactory by lazy { + LoggerFactory( + config = loggerConfigInit( + logWriters = arrayOf(CommonWriter(NoTagFormatter)), + minSeverity = Severity.Info + ) + ) +} diff --git a/phoenix-shared/src/iosMain/kotlin/fr/acinq/phoenix/managers/NetworkMonitorIos.kt b/phoenix-shared/src/iosMain/kotlin/fr/acinq/phoenix/managers/NetworkMonitorIos.kt index c7b3850de..d4ef90cf6 100644 --- a/phoenix-shared/src/iosMain/kotlin/fr/acinq/phoenix/managers/NetworkMonitorIos.kt +++ b/phoenix-shared/src/iosMain/kotlin/fr/acinq/phoenix/managers/NetworkMonitorIos.kt @@ -1,13 +1,13 @@ package fr.acinq.phoenix.managers import fr.acinq.phoenix.utils.PlatformContext +import fr.acinq.lightning.logging.LoggerFactory +import fr.acinq.lightning.logging.debug import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.MainScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch -import org.kodein.log.LoggerFactory -import org.kodein.log.newLogger import platform.Network.* import platform.darwin.dispatch_get_main_queue @@ -17,7 +17,7 @@ actual class NetworkMonitor actual constructor( ctx: PlatformContext ) : CoroutineScope by MainScope() { - private val logger = newLogger(loggerFactory) + private val logger = loggerFactory.newLogger(this::class) private val _networkState = MutableStateFlow(NetworkState.NotAvailable) actual val networkState: StateFlow = _networkState diff --git a/phoenix-shared/src/iosMain/kotlin/fr/acinq/phoenix/utils/OSLogWriter.kt b/phoenix-shared/src/iosMain/kotlin/fr/acinq/phoenix/utils/OSLogWriter.kt new file mode 100644 index 000000000..ed57bdc1f --- /dev/null +++ b/phoenix-shared/src/iosMain/kotlin/fr/acinq/phoenix/utils/OSLogWriter.kt @@ -0,0 +1,121 @@ + +// This file is commented as it requires a patch on kermit that fixes the OSLogWriter. +// As of kermit 2.0.2, log entries sent to the OSLogWriter result in a error. +// see https://github.com/touchlab/Kermit/issues/339 +// proposed fix: https://github.com/touchlab/Kermit/pull/381 +// +// Also: +// +// OSLog is currently broken anyway, due to a bug in the version released by Apple. +// Using is now (even with the patch above ^) would be pointless. In the meantime, +// we use swift-log with logs written to files (see FileLogger). + + + + +//@file:OptIn(ExperimentalForeignApi::class, ExperimentalNativeApi::class) +// +//package fr.acinq.phoenix.utils +// +//import co.touchlab.kermit.DefaultFormatter +//import co.touchlab.kermit.LogWriter +//import co.touchlab.kermit.Message +//import co.touchlab.kermit.MessageStringFormatter +//import co.touchlab.kermit.Severity +//import co.touchlab.kermit.Tag +//import co.touchlab.kermit.darwin.* +//import kotlinx.cinterop.ExperimentalForeignApi +//import kotlin.concurrent.AtomicReference +//import platform.darwin.OS_LOG_TYPE_DEBUG +//import platform.darwin.OS_LOG_TYPE_DEFAULT +//import platform.darwin.OS_LOG_TYPE_ERROR +//import platform.darwin.OS_LOG_TYPE_FAULT +//import platform.darwin.OS_LOG_TYPE_INFO +//import platform.darwin.os_log_type_t +//import kotlin.experimental.ExperimentalNativeApi +// +///** +// * This is based off the implementation in Kermit. +// * Except their implementation is broken: +// * https://github.com/touchlab/Kermit/pull/381 +// */ +//@OptIn(ExperimentalNativeApi::class) +//open class OSLogWriter internal constructor( +// private val messageStringFormatter: MessageStringFormatter, +// private val darwinLogger: DarwinLogger +//) : LogWriter() { +// +// constructor( +// messageStringFormatter: MessageStringFormatter = DefaultFormatter +// ) : this(messageStringFormatter, DarwinLoggerActual) +// +// override fun log(severity: Severity, message: String, tag: String, throwable: Throwable?) { +// callLog( +// severity, formatMessage( +// severity = severity, +// message = Message(message), +// tag = Tag(tag) +// ), throwable +// ) +// } +// +// // Added to do some testing on log format. https://github.com/touchlab/Kermit/issues/243 +// open fun callLog(severity: Severity, message: String, throwable: Throwable?) { +// val tag = "PhoenixShared.FooBar" +// val type = kermitSeverityToOsLogType(severity) +// darwinLogger.log(tag, type, message) +// if (throwable != null) { +// logThrowable(tag, type, throwable) +// } +// } +// +// open fun logThrowable(tag: String, type: os_log_type_t, throwable: Throwable){ +// darwinLogger.log(tag, type, throwable.getStackTrace().joinToString("\n")) +// } +// +// private fun kermitSeverityToOsLogType(severity: Severity): os_log_type_t = when (severity) { +// Severity.Verbose, Severity.Debug -> OS_LOG_TYPE_DEBUG +// Severity.Info -> OS_LOG_TYPE_INFO +// Severity.Warn -> OS_LOG_TYPE_DEFAULT +// Severity.Error -> OS_LOG_TYPE_ERROR +// Severity.Assert -> OS_LOG_TYPE_FAULT +// } +// +// open fun formatMessage(severity: Severity, tag: Tag, message: Message): String = +// messageStringFormatter.formatMessage(null, tag, message) +//} +// +// +//internal interface DarwinLogger { +// fun log(tag: String, type: os_log_type_t, message: String) +//} +// +//@OptIn(ExperimentalForeignApi::class) +//private object DarwinLoggerActual : DarwinLogger { +// private val _logMap = AtomicReference(mapOf()) +// fun splitTag(tag: String): Pair { +// return when (val idx = tag.lastIndexOf(".")) { +// -1 -> Pair("", tag) +// else -> Pair(tag.substring(0, idx), tag.substring(idx+1)) +// } +// } +// fun getLog(tag: String): darwin_os_log_t { +// var currentLogMap = _logMap.value +// currentLogMap[tag]?.let { return it } +// val (subsystem, category) = splitTag(tag) +// val log = darwin_log_create(subsystem, category)!! +// while (true) { +// val newPair: Pair = Pair(tag, log) +// val updatedLogMap: Map = currentLogMap.plus(newPair) +// if (_logMap.compareAndSet(currentLogMap, updatedLogMap)) { +// return log +// } else { +// currentLogMap = _logMap.value +// currentLogMap[tag]?.let { return it } +// } +// } +// } +// override fun log(tag: String, type: os_log_type_t, message: String) { +// darwin_log_with_type(getLog(tag), type, message) +// } +//} \ No newline at end of file diff --git a/phoenix-shared/src/iosMain/kotlin/fr/acinq/phoenix/utils/PassthruLogWriter.kt b/phoenix-shared/src/iosMain/kotlin/fr/acinq/phoenix/utils/PassthruLogWriter.kt new file mode 100644 index 000000000..ab877546e --- /dev/null +++ b/phoenix-shared/src/iosMain/kotlin/fr/acinq/phoenix/utils/PassthruLogWriter.kt @@ -0,0 +1,17 @@ +package fr.acinq.phoenix.utils + +import co.touchlab.kermit.LogWriter +import co.touchlab.kermit.Severity + +class PassthruLogWriter( + val logger: (Severity, String, String) -> Unit +) : LogWriter() { + + constructor(ctx: PlatformContext) : this( + logger = ctx.logger!! + ) + + override fun log(severity: Severity, message: String, tag: String, throwable: Throwable?) { + logger(severity, message, tag) + } +} \ No newline at end of file diff --git a/phoenix-shared/src/iosMain/kotlin/fr/acinq/phoenix/utils/logger/PhoenixLogWriters.kt b/phoenix-shared/src/iosMain/kotlin/fr/acinq/phoenix/utils/logger/PhoenixLogWriters.kt new file mode 100644 index 000000000..8b9134c1f --- /dev/null +++ b/phoenix-shared/src/iosMain/kotlin/fr/acinq/phoenix/utils/logger/PhoenixLogWriters.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2024 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package fr.acinq.phoenix.utils.logger + +import co.touchlab.kermit.LogWriter +import co.touchlab.kermit.OSLogWriter +import fr.acinq.phoenix.utils.PassthruLogWriter +import fr.acinq.phoenix.utils.PlatformContext + +actual fun phoenixLogWriters(ctx: PlatformContext): List { + return if (ctx.logger != null) { + listOf(PassthruLogWriter(ctx)) + } else { + // OSLogWriter is disabled for now, as the current version of OSLogStore is buggy + // listOf(OSLogWriter()) + throw IllegalArgumentException("A valid logger must be provided. OSLogWriter is disabled.") + } +} \ No newline at end of file diff --git a/phoenix-shared/src/iosMain/kotlin/fr/acinq/phoenix/utils/platformIos.kt b/phoenix-shared/src/iosMain/kotlin/fr/acinq/phoenix/utils/platformIos.kt index 839d4ad07..7303c4888 100644 --- a/phoenix-shared/src/iosMain/kotlin/fr/acinq/phoenix/utils/platformIos.kt +++ b/phoenix-shared/src/iosMain/kotlin/fr/acinq/phoenix/utils/platformIos.kt @@ -1,8 +1,11 @@ package fr.acinq.phoenix.utils +import co.touchlab.kermit.Severity import platform.Foundation.* -actual class PlatformContext +actual class PlatformContext( + val logger: ((Severity, String, String) -> Unit)? = null +) actual fun getApplicationFilesDirectoryPath(ctx: PlatformContext): String = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true)[0] as String