Skip to content

Commit

Permalink
feat: database logger
Browse files Browse the repository at this point in the history
  • Loading branch information
MohamadJaara committed Jan 13, 2025
1 parent 5788184 commit 22ca967
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package com.wire.kalium.logic.feature.debug

import com.wire.kalium.logic.di.UserStorage
import com.wire.kalium.persistence.db.DBProfile

class ChangeProfilingUseCase(
private val userStorage: UserStorage,
Expand All @@ -26,7 +27,11 @@ class ChangeProfilingUseCase(
* Changes the profiling of the database (cipher_profile) if the profile is specified and the database is encrypted
* @param enabled true to enable profiling, false to disable
*/
operator fun invoke(enabled: Boolean) {
userStorage.database.changeProfiling(enabled)
suspend operator fun invoke(status: DBProfile) {
userStorage.database.debugExtension.changeProfiling(status)
}

suspend operator fun invoke(enabled: Boolean) {
userStorage.database.debugExtension.changeProfiling(if (enabled) DBProfile.ON.Device else DBProfile.Off)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ class DebugScope internal constructor(
private val legalHoldHandler: LegalHoldHandler,
private val notificationTokenRepository: NotificationTokenRepository,
private val scope: CoroutineScope,
userStorage: UserStorage,
private val userStorage: UserStorage,
logger: KaliumLogger,
internal val dispatcher: KaliumDispatcher = KaliumDispatcherImpl,
) {
Expand Down Expand Up @@ -227,5 +227,7 @@ class DebugScope internal constructor(
notificationTokenRepository,
)

val changeProfiling: ChangeProfilingUseCase = ChangeProfilingUseCase(userStorage)
val changeProfiling: ChangeProfilingUseCase get() = ChangeProfilingUseCase(userStorage)

val observeDatabaseLoggerState get() = ObserveDatabaseLoggerStateUseCase(userStorage)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Wire
* Copyright (C) 2025 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.wire.kalium.logic.feature.debug

import com.wire.kalium.logic.di.UserStorage
import com.wire.kalium.persistence.db.DBProfile
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

class ObserveDatabaseLoggerStateUseCase(
private val userStorage: UserStorage,
) {
suspend operator fun invoke(): Flow<Boolean> = userStorage.database.debugExtension.getProfilingState().map {
it is DBProfile.ON
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ actual fun userDatabaseBuilder(
dispatcher = dispatcher,
platformDatabaseData = platformDatabaseData,
isEncrypted = isEncryptionEnabled,
cipherProfile = "logcat",
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Wire
* Copyright (C) 2025 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.wire.kalium.persistence.db

import app.cash.sqldelight.db.QueryResult
import app.cash.sqldelight.db.SqlDriver
import com.wire.kalium.persistence.dao.MetadataDAO
import com.wire.kalium.persistence.kaliumLogger
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

class DebugExtension(
private val sqlDriver: SqlDriver,
private val isEncrypted: Boolean,
private val metaDataDao: MetadataDAO,
) {

suspend fun getProfilingState(): Flow<DBProfile?> =
metaDataDao.valueByKeyFlow(KEY_CIPHER_PROFILE)
.map {
it?.let { DBProfile.fromString(it) }
}

/**
* Changes the profiling of the database (cipher_profile) if the profile is specified and the database is encrypted
* @param enabled true to enable profiling, false to disable
*/
suspend fun changeProfiling(state: DBProfile): Long? =
if (isEncrypted) {
sqlDriver.executeQuery(
identifier = null,
sql = """PRAGMA cipher_profile= '${state.logTarget}';""",
mapper = { cursor ->
cursor.next()
cursor.getLong(0).let { QueryResult.Value<Long?>(it) }
},
parameters = 0,
).value.also {
updateMetadata(state)
}

} else {
error("Cannot change profiling on unencrypted database")
}

private suspend fun updateMetadata(state: DBProfile) {
metaDataDao.insertValue(
value = state.logTarget,
key = KEY_CIPHER_PROFILE
)
}

private companion object {
const val KEY_CIPHER_PROFILE = "cipher_profile"
}
}

sealed interface DBProfile {
val logTarget: String

data object Off : DBProfile {
override val logTarget: String = "off"

override fun toString(): String {
return "off"
}
}

sealed interface ON : DBProfile {
data object Device : ON {
override val logTarget: String = "logcat"

override fun toString(): String {
return "logcat"
}
}

data class CustomFile(override val logTarget: String) : ON {
override fun toString(): String {
return logTarget
}
}
}

companion object {
fun fromString(value: String): DBProfile = when (value) {
"off" -> Off
"logcat" -> ON.Device
else -> ON.CustomFile(value)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ class UserDatabaseBuilder internal constructor(
private val platformDatabaseData: PlatformDatabaseData,
private val isEncrypted: Boolean,
private val queriesContext: CoroutineContext = KaliumDispatcherImpl.io,
private val cipherProfile: String? = null,
) {

internal val database: UserDatabase = UserDatabase(
Expand Down Expand Up @@ -314,30 +313,18 @@ class UserDatabaseBuilder internal constructor(
queriesContext
)

val debugExtension: DebugExtension
get() = DebugExtension(
sqlDriver = sqlDriver,
metaDataDao = metadataDAO,
isEncrypted = isEncrypted
)

/**
* @return the absolute path of the DB file or null if the DB file does not exist
*/
fun dbFileLocation(): String? = getDatabaseAbsoluteFileLocation(platformDatabaseData, userId)

/**
* Changes the profiling of the database (cipher_profile) if the profile is specified and the database is encrypted
* @param enabled true to enable profiling, false to disable
*/
fun changeProfiling(enabled: Boolean) {
if (isEncrypted && cipherProfile != null) {
val cipherProfileValue = if (enabled) cipherProfile else "off"
sqlDriver.executeQuery(
identifier = null,
sql = "PRAGMA cipher_profile='$cipherProfileValue'",
mapper = {
it.next()
it.getLong(0).let { QueryResult.Value<Long?>(it) }
},
parameters = 0,
)
}
}

/**
* drops DB connection and delete the DB file
*/
Expand Down

0 comments on commit 22ca967

Please sign in to comment.