mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-19 12:39:11 +08:00
[console/logging] Introduce LoggerControlState
for optimize performance
This commit is contained in:
parent
4962f1907e
commit
8a07308a56
@ -270,6 +270,9 @@ ___ ____ _ _____ _
|
||||
consoleDataScope.addAndReloadConfig(loggerController.loggerConfig)
|
||||
}
|
||||
consoleDataScope.reloadAll()
|
||||
if (loggerController is LoggerControllerImpl) {
|
||||
loggerController.onReload()
|
||||
}
|
||||
}
|
||||
|
||||
phase("initialize all plugins") {
|
||||
|
@ -18,6 +18,11 @@ internal class LoggerControllerImpl : AbstractLoggerController.PathBased() {
|
||||
internal val loggerConfig: LoggerConfig by lazy {
|
||||
LoggerConfig()
|
||||
}
|
||||
override val isLoggerControlStateSupported: Boolean get() = true
|
||||
|
||||
internal fun onReload() {
|
||||
this.loggerConfigUpdateTime++
|
||||
}
|
||||
|
||||
override fun findPriority(identity: String?): LogPriority? {
|
||||
return if (identity == null) {
|
||||
|
@ -15,45 +15,47 @@ import net.mamoe.mirai.utils.MiraiLoggerPlatformBase
|
||||
import net.mamoe.mirai.utils.SimpleLogger
|
||||
|
||||
internal class MiraiConsoleLogger(
|
||||
private val controller: LoggerController,
|
||||
controller: LoggerController,
|
||||
val logger: MiraiLogger
|
||||
) : MiraiLoggerPlatformBase() {
|
||||
override val identity: String? get() = logger.identity
|
||||
override val isEnabled: Boolean get() = logger.isEnabled
|
||||
|
||||
private val logState = controller.getLoggerControlState(identity)
|
||||
|
||||
override val isInfoEnabled: Boolean
|
||||
get() = controller.shouldLog(identity, SimpleLogger.LogPriority.INFO)
|
||||
get() = logState.shouldLog(SimpleLogger.LogPriority.INFO)
|
||||
override val isWarningEnabled: Boolean
|
||||
get() = controller.shouldLog(identity, SimpleLogger.LogPriority.WARNING)
|
||||
get() = logState.shouldLog(SimpleLogger.LogPriority.WARNING)
|
||||
override val isDebugEnabled: Boolean
|
||||
get() = controller.shouldLog(identity, SimpleLogger.LogPriority.DEBUG)
|
||||
get() = logState.shouldLog(SimpleLogger.LogPriority.DEBUG)
|
||||
override val isErrorEnabled: Boolean
|
||||
get() = controller.shouldLog(identity, SimpleLogger.LogPriority.ERROR)
|
||||
get() = logState.shouldLog(SimpleLogger.LogPriority.ERROR)
|
||||
override val isVerboseEnabled: Boolean
|
||||
get() = controller.shouldLog(identity, SimpleLogger.LogPriority.VERBOSE)
|
||||
get() = logState.shouldLog(SimpleLogger.LogPriority.VERBOSE)
|
||||
|
||||
override fun info0(message: String?, e: Throwable?) {
|
||||
if (controller.shouldLog(identity, SimpleLogger.LogPriority.INFO))
|
||||
if (logState.shouldLog(SimpleLogger.LogPriority.INFO))
|
||||
logger.info(message, e)
|
||||
}
|
||||
|
||||
override fun warning0(message: String?, e: Throwable?) {
|
||||
if (controller.shouldLog(identity, SimpleLogger.LogPriority.WARNING))
|
||||
if (logState.shouldLog(SimpleLogger.LogPriority.WARNING))
|
||||
logger.warning(message, e)
|
||||
}
|
||||
|
||||
override fun debug0(message: String?, e: Throwable?) {
|
||||
if (controller.shouldLog(identity, SimpleLogger.LogPriority.DEBUG))
|
||||
if (logState.shouldLog(SimpleLogger.LogPriority.DEBUG))
|
||||
logger.debug(message, e)
|
||||
}
|
||||
|
||||
override fun error0(message: String?, e: Throwable?) {
|
||||
if (controller.shouldLog(identity, SimpleLogger.LogPriority.ERROR))
|
||||
if (logState.shouldLog(SimpleLogger.LogPriority.ERROR))
|
||||
logger.error(message, e)
|
||||
}
|
||||
|
||||
override fun verbose0(message: String?, e: Throwable?) {
|
||||
if (controller.shouldLog(identity, SimpleLogger.LogPriority.VERBOSE))
|
||||
if (logState.shouldLog(SimpleLogger.LogPriority.VERBOSE))
|
||||
logger.verbose(message, e)
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,44 @@ public abstract class AbstractLoggerController : LoggerController {
|
||||
override fun shouldLog(identity: String?, priority: SimpleLogger.LogPriority): Boolean =
|
||||
shouldLog(LogPriority.by(priority), getPriority(identity))
|
||||
|
||||
// region LoggerControlState support
|
||||
protected open val isLoggerControlStateSupported: Boolean get() = false
|
||||
|
||||
@Volatile
|
||||
@Transient
|
||||
@JvmField
|
||||
protected var loggerConfigUpdateTime: Long = 0L
|
||||
|
||||
override fun getLoggerControlState(identity: String?): LoggerController.LoggerControlState {
|
||||
if (isLoggerControlStateSupported) {
|
||||
return object : LoggerController.LoggerControlState {
|
||||
private val status = BitSet(SimpleLogger.LogPriority.values().size)
|
||||
|
||||
@Volatile
|
||||
@Transient
|
||||
private var lastUpdateTime = -1L
|
||||
|
||||
override fun shouldLog(priority: SimpleLogger.LogPriority): Boolean {
|
||||
if (lastUpdateTime != loggerConfigUpdateTime) {
|
||||
updateProperties()
|
||||
}
|
||||
return status[priority.ordinal]
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun updateProperties() {
|
||||
lastUpdateTime = loggerConfigUpdateTime
|
||||
SimpleLogger.LogPriority.values().forEach { prio ->
|
||||
status.set(prio.ordinal, shouldLog(identity, prio))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return super.getLoggerControlState(identity)
|
||||
}
|
||||
// endregion
|
||||
|
||||
/**
|
||||
* 便于进行配置存储的 [LogPriority],
|
||||
* 等级优先级与 [SimpleLogger.LogPriority] 对应
|
||||
|
@ -12,6 +12,7 @@ package net.mamoe.mirai.console.logging
|
||||
import net.mamoe.mirai.console.MiraiConsoleImplementation
|
||||
import net.mamoe.mirai.console.internal.logging.MiraiConsoleLogger
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import net.mamoe.mirai.utils.SimpleLogger
|
||||
|
||||
/**
|
||||
@ -26,4 +27,23 @@ public interface LoggerController {
|
||||
/** 是否应该记录该等级的日志 */
|
||||
public fun shouldLog(identity: String?, priority: SimpleLogger.LogPriority): Boolean
|
||||
|
||||
public fun getLoggerControlState(identity: String?): LoggerControlState {
|
||||
return object : LoggerControlState {
|
||||
override fun shouldLog(priority: SimpleLogger.LogPriority): Boolean {
|
||||
return shouldLog(identity, priority)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 一个 [MiraiLogger] 的日志开关状态
|
||||
*
|
||||
* 这个类可以缓存 [LoggerController.shouldLog] 的结果, 避免多次查询
|
||||
*
|
||||
* 在需要的时候会自动更新, 所以不需要手动更换 [LoggerControlState]
|
||||
*/
|
||||
@ConsoleExperimentalApi
|
||||
public interface LoggerControlState {
|
||||
public fun shouldLog(priority: SimpleLogger.LogPriority): Boolean
|
||||
}
|
||||
}
|
||||
|
66
mirai-console/backend/mirai-console/test/logging/TestALC.kt
Normal file
66
mirai-console/backend/mirai-console/test/logging/TestALC.kt
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.logging
|
||||
|
||||
import net.mamoe.mirai.utils.SimpleLogger
|
||||
import org.junit.jupiter.api.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class TestALC {
|
||||
private class TestController(
|
||||
override val isLoggerControlStateSupported: Boolean,
|
||||
) : AbstractLoggerController() {
|
||||
var callcount = 0
|
||||
|
||||
|
||||
override fun getPriority(identity: String?): LogPriority {
|
||||
return LogPriority.ALL
|
||||
}
|
||||
|
||||
override fun shouldLog(identity: String?, priority: SimpleLogger.LogPriority): Boolean {
|
||||
if (priority == SimpleLogger.LogPriority.INFO) {
|
||||
callcount++
|
||||
}
|
||||
return super.shouldLog(identity, priority)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test logger control state caching`() {
|
||||
val controller = TestController(true)
|
||||
assertEquals(0, controller.callcount)
|
||||
val state = controller.getLoggerControlState("Test")
|
||||
assertEquals(0, controller.callcount) // lazy load
|
||||
|
||||
state.shouldLog(SimpleLogger.LogPriority.DEBUG)
|
||||
assertEquals(1, controller.callcount)
|
||||
|
||||
state.shouldLog(SimpleLogger.LogPriority.INFO)
|
||||
assertEquals(1, controller.callcount)
|
||||
|
||||
state.shouldLog(SimpleLogger.LogPriority.DEBUG)
|
||||
state.shouldLog(SimpleLogger.LogPriority.INFO)
|
||||
state.shouldLog(SimpleLogger.LogPriority.INFO)
|
||||
assertEquals(1, controller.callcount)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test keep binary compatibility`() {
|
||||
val controller = TestController(false)
|
||||
assertEquals(0, controller.callcount)
|
||||
val state = controller.getLoggerControlState("Test")
|
||||
assertEquals(0, controller.callcount)
|
||||
|
||||
repeat(50) { count ->
|
||||
state.shouldLog(SimpleLogger.LogPriority.INFO)
|
||||
assertEquals(count + 1, controller.callcount)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user