feat(logging): Replace Timber with Kermit for multiplatform logging (#4083)

Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
James Rich 2025-12-28 08:30:15 -06:00 committed by GitHub
parent a927481e4d
commit 0776e029f3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
92 changed files with 727 additions and 957 deletions

View file

@ -24,6 +24,7 @@ import android.os.RemoteException
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import co.touchlab.kermit.Logger
import com.geeksville.mesh.repository.bluetooth.BluetoothRepository
import com.geeksville.mesh.repository.network.NetworkRepository
import com.geeksville.mesh.repository.network.NetworkRepository.Companion.toAddressString
@ -49,7 +50,6 @@ import org.meshtastic.core.service.ServiceRepository
import org.meshtastic.core.strings.Res
import org.meshtastic.core.strings.meshtastic
import org.meshtastic.core.ui.viewmodel.stateInWhileSubscribed
import timber.log.Timber
import javax.inject.Inject
// ... (DeviceListEntry sealed class remains the same) ...
@ -164,13 +164,13 @@ constructor(
init {
serviceRepository.statusMessage.onEach { errorText.value = it }.launchIn(viewModelScope)
Timber.d("BTScanModel created")
Logger.d { "BTScanModel created" }
}
override fun onCleared() {
super.onCleared()
bluetoothRepository.stopScan()
Timber.d("BTScanModel cleared")
Logger.d { "BTScanModel cleared" }
}
fun setErrorText(text: String) {
@ -178,7 +178,7 @@ constructor(
}
fun stopScan() {
Timber.d("stopping scan")
Logger.d { "stopping scan" }
bluetoothRepository.stopScan()
}
@ -187,7 +187,7 @@ constructor(
}
fun startScan() {
Timber.d("starting ble scan")
Logger.d { "starting ble scan" }
bluetoothRepository.startScan()
}
@ -195,24 +195,24 @@ constructor(
try {
serviceRepository.meshService?.let { service -> MeshService.changeDeviceAddress(context, service, address) }
} catch (ex: RemoteException) {
Timber.e(ex, "changeDeviceSelection failed, probably it is shutting down")
Logger.e(ex) { "changeDeviceSelection failed, probably it is shutting down" }
}
}
/** Initiates the bonding process and connects to the device upon success. */
private fun requestBonding(entry: DeviceListEntry.Ble) {
Timber.i("Starting bonding for ${entry.peripheral.address.anonymize}")
Logger.i { "Starting bonding for ${entry.peripheral.address.anonymize}" }
viewModelScope.launch {
@Suppress("TooGenericExceptionCaught")
try {
bluetoothRepository.bond(entry.peripheral)
Timber.i("Bonding complete for ${entry.peripheral.address.anonymize}, selecting device...")
Logger.i { "Bonding complete for ${entry.peripheral.address.anonymize}, selecting device..." }
changeDeviceAddress(entry.fullAddress)
} catch (ex: SecurityException) {
Timber.e(ex, "Bonding failed for ${entry.peripheral.address.anonymize} Permissions not granted")
Logger.e(ex) { "Bonding failed for ${entry.peripheral.address.anonymize} Permissions not granted" }
serviceRepository.setErrorMessage("Bonding failed: ${ex.message} Permissions not granted")
} catch (ex: Exception) {
Timber.e(ex, "Bonding failed for ${entry.peripheral.address.anonymize}")
Logger.e(ex) { "Bonding failed for ${entry.peripheral.address.anonymize}" }
serviceRepository.setErrorMessage("Bonding failed: ${ex.message}")
}
}
@ -223,10 +223,10 @@ constructor(
.requestPermission(it.driver.device)
.onEach { granted ->
if (granted) {
Timber.i("User approved USB access")
Logger.i { "User approved USB access" }
changeDeviceAddress(it.fullAddress)
} else {
Timber.e("USB permission denied for device ${it.address}")
Logger.e { "USB permission denied for device ${it.address}" }
}
}
.launchIn(viewModelScope)

View file

@ -25,6 +25,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.asLiveData
import androidx.lifecycle.viewModelScope
import androidx.navigation.NavHostController
import co.touchlab.kermit.Logger
import com.geeksville.mesh.repository.radio.MeshActivity
import com.geeksville.mesh.repository.radio.RadioInterfaceService
import dagger.hilt.android.lifecycle.HiltViewModel
@ -67,7 +68,6 @@ import org.meshtastic.core.ui.viewmodel.stateInWhileSubscribed
import org.meshtastic.proto.AdminProtos
import org.meshtastic.proto.AppOnlyProtos
import org.meshtastic.proto.MeshProtos
import timber.log.Timber
import javax.inject.Inject
// Given a human name, strip out the first letter of the first three words and return that as the
@ -212,7 +212,7 @@ constructor(
}
.launchIn(viewModelScope)
Timber.d("ViewModel created")
Logger.d { "ViewModel created" }
}
private val _sharedContactRequested: MutableStateFlow<AdminProtos.SharedContact?> = MutableStateFlow(null)
@ -222,7 +222,7 @@ constructor(
fun setSharedContactRequested(url: Uri, onFailure: () -> Unit) {
runCatching { _sharedContactRequested.value = url.toSharedContact() }
.onFailure { ex ->
Timber.e(ex, "Shared contact error")
Logger.e(ex) { "Shared contact error" }
onFailure()
}
}
@ -243,7 +243,7 @@ constructor(
fun requestChannelUrl(url: Uri, onFailure: () -> Unit) =
runCatching { _requestChannelSet.value = url.toChannelSet() }
.onFailure { ex ->
Timber.e(ex, "Channel url error")
Logger.e(ex) { "Channel url error" }
onFailure()
}
@ -256,7 +256,7 @@ constructor(
override fun onCleared() {
super.onCleared()
Timber.d("ViewModel cleared")
Logger.d { "ViewModel cleared" }
}
val tracerouteResponse: LiveData<TracerouteResponse?>