Skip to content

Commit

Permalink
📈 Add time-consuming logging method (#824)
Browse files Browse the repository at this point in the history
guiyanakuang authored Apr 29, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 2147f9c commit 6abd2a4
Showing 4 changed files with 142 additions and 85 deletions.
28 changes: 28 additions & 0 deletions composeApp/src/commonMain/kotlin/com/clipevery/utils/ToolUtils.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.clipevery.utils

import io.github.oshai.kotlinlogging.KLogger
import io.github.oshai.kotlinlogging.KotlinLogging

class OnceFunction<T>(private val function: () -> T) {
@@ -50,3 +51,30 @@ object Retry {
throw lastException ?: IllegalStateException("Unknown retry failure.")
}
}

object LoggerExtension {

fun <T> logExecutionTime(
logger: KLogger,
message: String,
func: () -> T,
): T {
val startTime = System.currentTimeMillis()
val result = func()
val endTime = System.currentTimeMillis()
logger.info { "$message Execution Time: ${endTime - startTime} ms" }
return result
}

suspend fun <T> logSuspendExecutionTime(
logger: KLogger,
message: String,
func: suspend () -> T,
): T {
val startTime = System.currentTimeMillis()
val result = func()
val endTime = System.currentTimeMillis()
logger.info { "$message Execution Time: ${endTime - startTime} ms" }
return result
}
}
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@ import com.clipevery.dao.clip.ClipDao
import com.clipevery.dao.clip.ClipData
import com.clipevery.dao.clip.ClipState
import com.clipevery.dao.clip.ClipType
import com.clipevery.utils.LoggerExtension.logSuspendExecutionTime
import io.github.oshai.kotlinlogging.KotlinLogging
import io.realm.kotlin.MutableRealm
import io.realm.kotlin.ext.toRealmList
@@ -83,51 +84,55 @@ class ClipCollector(
clipId: Long,
remote: Boolean,
): ObjectId? {
val collector = preCollectors.filter { it.isNotEmpty() }
if (collector.isEmpty()) {
return null
}
val clipAppearItems: List<ClipAppearItem> = preCollectors.flatMap { it.values }

val clipContent =
ClipContent().apply {
this.clipAppearItems = clipAppearItems.map { RealmAny.create(it as RealmObject) }.toRealmList()
return logSuspendExecutionTime(logger, "createPreClipData") {
val collector = preCollectors.filter { it.isNotEmpty() }
if (collector.isEmpty()) {
return@logSuspendExecutionTime null
}
val clipAppearItems: List<ClipAppearItem> = preCollectors.flatMap { it.values }

val clipData =
ClipData().apply {
this.clipId = clipId
this.clipContent = clipContent
this.clipType = ClipType.INVALID
this.md5 = ""
this.appInstanceId = appInfo.appInstanceId
this.createTime = RealmInstant.now()
this.clipState = ClipState.LOADING
this.remote = remote
}
return clipDao.createClipData(clipData)
val clipContent =
ClipContent().apply {
this.clipAppearItems = clipAppearItems.map { RealmAny.create(it as RealmObject) }.toRealmList()
}

val clipData =
ClipData().apply {
this.clipId = clipId
this.clipContent = clipContent
this.clipType = ClipType.INVALID
this.md5 = ""
this.appInstanceId = appInfo.appInstanceId
this.createTime = RealmInstant.now()
this.clipState = ClipState.LOADING
this.remote = remote
}
return@logSuspendExecutionTime clipDao.createClipData(clipData)
}
}

suspend fun completeCollect(id: ObjectId) {
if (preCollectors.isEmpty() || (existError && updateErrors.all { it != null })) {
try {
clipDao.markDeleteClipData(id)
} catch (e: Exception) {
logger.error(e) { "Failed to mark delete clip $id" }
}
} else {
try {
clipDao.releaseLocalClipData(id, clipPlugins)
} catch (e: Exception) {
logger.error(e) { "Failed to release clip $id" }
// The following errors will be sent next
// [RLM_ERR_WRONG_TRANSACTION_STATE]: The Realm is already in a write transaction
// https://github.com/realm/realm-kotlin/pull/1621 wait new version release
logSuspendExecutionTime(logger, "completeCollect") {
if (preCollectors.isEmpty() || (existError && updateErrors.all { it != null })) {
try {
clipDao.markDeleteClipData(id)
} catch (e: Exception) {
logger.error(e) { "Failed to mark delete clip $id" }
}
} else {
try {
clipDao.releaseLocalClipData(id, clipPlugins)
} catch (e: Exception) {
logger.error(e) { "Failed to release clip $id" }
// The following errors will be sent next
// [RLM_ERR_WRONG_TRANSACTION_STATE]: The Realm is already in a write transaction
// https://github.com/realm/realm-kotlin/pull/1621 wait new version release
try {
clipDao.markDeleteClipData(id)
} catch (e: Exception) {
logger.error(e) { "Failed to mark delete clip $id" }
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -3,6 +3,8 @@ package com.clipevery.clip
import com.clipevery.app.AppInfo
import com.clipevery.dao.clip.ClipDao
import com.clipevery.utils.IDGenerator
import com.clipevery.utils.LoggerExtension.logExecutionTime
import com.clipevery.utils.LoggerExtension.logSuspendExecutionTime
import io.github.oshai.kotlinlogging.KotlinLogging
import java.awt.datatransfer.DataFlavor
import java.awt.datatransfer.Transferable
@@ -39,25 +41,27 @@ open class DesktopTransferableConsumer(
transferable: Transferable,
remote: Boolean,
) {
val clipId = idGenerator.nextID()
logSuspendExecutionTime(logger, "consume") {
val clipId = idGenerator.nextID()

val dataFlavorMap: Map<String, List<DataFlavor>> = createDataFlavorMap(transferable)
val dataFlavorMap: Map<String, List<DataFlavor>> = createDataFlavorMap(transferable)

dataFlavorMap[LocalOnlyFlavor.humanPresentableName]?.let {
logger.info { "Ignoring local only flavor" }
return
}
dataFlavorMap[LocalOnlyFlavor.humanPresentableName]?.let {
logger.info { "Ignoring local only flavor" }
return@logSuspendExecutionTime
}

val clipCollector = ClipCollector(dataFlavorMap.size, appInfo, clipDao, clipPlugins)
val clipCollector = ClipCollector(dataFlavorMap.size, appInfo, clipDao, clipPlugins)

try {
preCollect(clipId, dataFlavorMap, transferable, clipCollector)
clipCollector.createPreClipData(clipId, remote = remote)?.let {
updateClipData(clipId, dataFlavorMap, transferable, clipCollector)
clipCollector.completeCollect(it)
try {
preCollect(clipId, dataFlavorMap, transferable, clipCollector)
clipCollector.createPreClipData(clipId, remote = remote)?.let {
updateClipData(clipId, dataFlavorMap, transferable, clipCollector)
clipCollector.completeCollect(it)
}
} catch (e: Exception) {
logger.error(e) { "Failed to consume transferable" }
}
} catch (e: Exception) {
logger.error(e) { "Failed to consume transferable" }
}
}

@@ -67,25 +71,33 @@ open class DesktopTransferableConsumer(
transferable: Transferable,
clipCollector: ClipCollector,
) {
var itemIndex = 0
for (entry in dataFlavorMap) {
val identifier = entry.key
val flavors = entry.value
logger.info { "itemIndex: $itemIndex Transferable flavor: $identifier" }
for (flavor in flavors) {
if (clipItemServiceMap[identifier]?.let { clipItemService ->
if (clipCollector.needPreCollectionItem(itemIndex, clipItemService::class)) {
clipItemService.createPreClipItem(clipId, itemIndex, identifier, transferable, clipCollector)
false
} else {
true
}
} == true
) {
break
logExecutionTime(logger, "preCollect") {
var itemIndex = 0
for (entry in dataFlavorMap) {
val identifier = entry.key
val flavors = entry.value
logger.info { "itemIndex: $itemIndex Transferable flavor: $identifier" }
for (flavor in flavors) {
if (clipItemServiceMap[identifier]?.let { clipItemService ->
if (clipCollector.needPreCollectionItem(itemIndex, clipItemService::class)) {
clipItemService.createPreClipItem(
clipId,
itemIndex,
identifier,
transferable,
clipCollector,
)
false
} else {
true
}
} == true
) {
break
}
}
itemIndex++
}
itemIndex++
}
}

@@ -95,24 +107,33 @@ open class DesktopTransferableConsumer(
transferable: Transferable,
clipCollector: ClipCollector,
) {
var itemIndex = 0
for (entry in dataFlavorMap) {
val identifier = entry.key
val flavors = entry.value
for (flavor in flavors) {
if (clipItemServiceMap[identifier]?.let { clipItemService ->
if (clipCollector.needUpdateCollectItem(itemIndex, clipItemService::class)) {
clipItemService.loadRepresentation(clipId, itemIndex, flavor, dataFlavorMap, transferable, clipCollector)
false
} else {
true
}
} == true
) {
break
logExecutionTime(logger, "updateClipData") {
var itemIndex = 0
for (entry in dataFlavorMap) {
val identifier = entry.key
val flavors = entry.value
for (flavor in flavors) {
if (clipItemServiceMap[identifier]?.let { clipItemService ->
if (clipCollector.needUpdateCollectItem(itemIndex, clipItemService::class)) {
clipItemService.loadRepresentation(
clipId,
itemIndex,
flavor,
dataFlavorMap,
transferable,
clipCollector,
)
false
} else {
true
}
} == true
) {
break
}
}
itemIndex++
}
itemIndex++
}
}
}
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@ import com.clipevery.clip.item.UrlClipItem
import com.clipevery.dao.task.TaskType
import com.clipevery.task.TaskExecutor
import com.clipevery.task.extra.SyncExtraInfo
import com.clipevery.utils.LoggerExtension.logSuspendExecutionTime
import com.clipevery.utils.TaskUtils.createTask
import com.clipevery.utils.getDateUtils
import io.github.oshai.kotlinlogging.KotlinLogging
@@ -53,10 +54,12 @@ class ClipRealm(
}

override suspend fun createClipData(clipData: ClipData): ObjectId {
realm.write {
copyToRealm(clipData)
return logSuspendExecutionTime(logger, "createClipData") {
realm.write {
copyToRealm(clipData)
}
return@logSuspendExecutionTime clipData.id
}
return clipData.id
}

override suspend fun markDeleteClipData(id: ObjectId) {

0 comments on commit 6abd2a4

Please sign in to comment.