mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-26 16:10:11 +08:00
[core+console] Improve logging hierarchy: (#2196)
- always use factory API from mirai-core - Terminal is still overriding standard outputs - plugins are forbidden to override logging framework (this was allowed but not working before)
This commit is contained in:
parent
2d393ee0b0
commit
f0651c81c6
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* 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.
|
||||
@ -7,6 +7,8 @@
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
|
||||
package net.mamoe.mirai.utils.logging
|
||||
|
||||
import io.ktor.client.*
|
||||
@ -20,18 +22,6 @@ import kotlin.test.assertFalse
|
||||
import kotlin.test.assertIs
|
||||
|
||||
internal class MiraiLog4JAdapterTest {
|
||||
|
||||
@Suppress("DEPRECATION_ERROR")
|
||||
@Test
|
||||
fun `services prevail than legacy overrides`() {
|
||||
MiraiLogger.setDefaultLoggerCreator {
|
||||
net.mamoe.mirai.utils.SimpleLogger("my logger") { _: String?, _: Throwable? -> }
|
||||
}
|
||||
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
assertIs<net.mamoe.mirai.internal.utils.Log4jLoggerAdapter>(MiraiLogger.Factory.create(this::class))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `using log4j`() {
|
||||
assertIs<MiraiLog4JFactory>(loadService(MiraiLogger.Factory::class))
|
||||
|
@ -128,8 +128,17 @@ public interface MiraiConsole : CoroutineScope {
|
||||
get() = throw UnsupportedOperationException("PluginCenter is not supported yet")
|
||||
|
||||
/**
|
||||
* 创建一个 logger
|
||||
* 创建一个 logger. 已弃用. 请使用 [MiraiLogger.Factory.create].
|
||||
*/
|
||||
@Deprecated(
|
||||
"Please use the standard way in mirai-core to create loggers, i.e. MiraiLogger.Factory.INSTANCE.create()",
|
||||
level = DeprecationLevel.WARNING,
|
||||
replaceWith = ReplaceWith(
|
||||
"MiraiLogger.Factory.create(yourClass::class, identity)",
|
||||
"net.mamoe.mirai.utils.MiraiLogger"
|
||||
),
|
||||
)
|
||||
@DeprecatedSinceMirai(warningSince = "2.13")
|
||||
@ConsoleExperimentalApi
|
||||
public fun createLogger(identity: String?): MiraiLogger
|
||||
|
||||
@ -204,6 +213,7 @@ public interface MiraiConsole : CoroutineScope {
|
||||
mainLogger.verbose { "Renaming $deviceInfoInWorkingDir to $deviceInWorkingDir" }
|
||||
deviceInfoInWorkingDir.renameTo(deviceInWorkingDir)
|
||||
}
|
||||
|
||||
deviceInRoot.exists() -> {
|
||||
// copy root/device.json to bots/id/device.json
|
||||
mainLogger.verbose { "Coping $deviceInRoot to $deviceInWorkingDir" }
|
||||
|
@ -37,10 +37,7 @@ import net.mamoe.mirai.console.plugin.loader.PluginLoader
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||
import net.mamoe.mirai.console.util.ConsoleInput
|
||||
import net.mamoe.mirai.message.data.Message
|
||||
import net.mamoe.mirai.utils.BotConfiguration
|
||||
import net.mamoe.mirai.utils.LoginSolver
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import net.mamoe.mirai.utils.NotStableForInheritance
|
||||
import net.mamoe.mirai.utils.*
|
||||
import java.nio.file.Path
|
||||
import java.util.*
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
@ -216,9 +213,14 @@ public interface MiraiConsoleImplementation : CoroutineScope {
|
||||
/**
|
||||
* 创建一个 [MiraiLogger].
|
||||
*
|
||||
* **注意**: [MiraiConsole] 会将 [net.mamoe.mirai.utils.MiraiLogger.setDefaultLoggerCreator] 设置为 `MiraiConsole::createLogger`.
|
||||
* **注意**: [MiraiConsole] 会将 [net.mamoe.mirai.utils.MiraiLogger.Factory] 设置为 `MiraiConsole::createLogger`.
|
||||
* 因此不要在 [createLogger] 中调用 [net.mamoe.mirai.utils.MiraiLogger.create]
|
||||
*/
|
||||
@Deprecated(
|
||||
"Deprecated for removal. Implement the other overload, or use MiraiConsole.createLogger instead.",
|
||||
level = DeprecationLevel.ERROR
|
||||
)
|
||||
@DeprecatedSinceMirai(errorSince = "2.13")
|
||||
public fun createLogger(identity: String?): MiraiLogger
|
||||
|
||||
/** @see [MiraiConsole.newProcessProgress] */
|
||||
@ -226,6 +228,16 @@ public interface MiraiConsoleImplementation : CoroutineScope {
|
||||
return DefaultLoggingProcessProgress()
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个 [MiraiLogger.Factory]. 在返回的实例中必须调用 [platformImplementation] 来适配平台日志实现.
|
||||
*
|
||||
* @param platformImplementation 平台的日志实现, 这可能是使用 SLF4J 等日志框架转接的实例.
|
||||
*
|
||||
* @since 2.13
|
||||
*/
|
||||
public fun createLoggerFactory(platformImplementation: MiraiLogger.Factory): MiraiLogger.Factory
|
||||
|
||||
|
||||
/**
|
||||
* 该前端是否支持使用 Ansi 输出彩色信息
|
||||
*
|
||||
|
@ -59,9 +59,9 @@ import net.mamoe.mirai.utils.*
|
||||
import java.time.Instant
|
||||
import java.time.ZoneId
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KProperty
|
||||
import kotlin.reflect.KProperty0
|
||||
|
||||
@ -100,22 +100,49 @@ internal class MiraiConsoleImplementationBridge(
|
||||
externalImplementation.loggerController
|
||||
}
|
||||
|
||||
override val mainLogger: MiraiLogger by lazy { createLogger("main") }
|
||||
override val mainLogger: MiraiLogger by lazy { MiraiLogger.Factory.create(MiraiConsole::class, "main") }
|
||||
|
||||
init {
|
||||
// TODO: Replace to standard api
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
DefaultFactoryOverrides.override { requester, identity ->
|
||||
return@override createLogger(
|
||||
identity ?: requester.kotlin.simpleName ?: requester.simpleName
|
||||
)
|
||||
/**
|
||||
* Delegates the [platformImplementation] with [loggerController].
|
||||
*/
|
||||
private inner class ControlledLoggerFactory(
|
||||
private val platformImplementation: MiraiLogger.Factory,
|
||||
) : MiraiLogger.Factory {
|
||||
override fun create(requester: KClass<*>, identity: String?): MiraiLogger {
|
||||
return MiraiConsoleLogger(loggerController, platformImplementation.create(requester, identity))
|
||||
}
|
||||
|
||||
override fun create(requester: Class<*>, identity: String?): MiraiLogger {
|
||||
return MiraiConsoleLogger(loggerController, platformImplementation.create(requester, identity))
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
// When writing a log:
|
||||
// 1. ControlledLoggerFactory checks if that log level is enabled
|
||||
// 2. ... if enabled, goto 3
|
||||
// ... if not, return
|
||||
// 3. [externalImplementation] decides how to log the message
|
||||
// 4. [externalImplementation] outputs by using [platform]
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
MiraiLoggerFactoryImplementationBridge.wrapCurrent { platform ->
|
||||
ControlledLoggerFactory(externalImplementation.createLoggerFactory(platform))
|
||||
}
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
MiraiLoggerFactoryImplementationBridge.freeze() // forbid any further overrides
|
||||
}
|
||||
|
||||
|
||||
@Deprecated(
|
||||
"Please use the standard way in mirai-core to create loggers, i.e. MiraiLogger.Factory.INSTANCE.create()",
|
||||
replaceWith = ReplaceWith(
|
||||
"MiraiLogger.Factory.create(yourClass::class, identity)",
|
||||
"net.mamoe.mirai.utils.MiraiLogger"
|
||||
),
|
||||
level = DeprecationLevel.WARNING
|
||||
)
|
||||
override fun createLogger(identity: String?): MiraiLogger {
|
||||
val controller = loggerController
|
||||
return MiraiConsoleLogger(controller, externalImplementation.createLogger(identity))
|
||||
return MiraiLogger.Factory.create(MiraiConsole::class, identity)
|
||||
}
|
||||
|
||||
@Suppress("RemoveRedundantBackticks")
|
||||
@ -286,6 +313,7 @@ internal class MiraiConsoleImplementationBridge(
|
||||
PLAIN -> {
|
||||
MiraiConsole.addBot(id, account.password.value, BotConfiguration::configBot)
|
||||
}
|
||||
|
||||
MD5 -> {
|
||||
val md5 = kotlin.runCatching {
|
||||
account.password.value.hexToBytes()
|
||||
@ -339,4 +367,5 @@ internal class MiraiConsoleImplementationBridge(
|
||||
override fun postPhase(phase: String) {
|
||||
externalImplementation.postPhase(phase)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,6 @@ package net.mamoe.mirai.console.internal.command
|
||||
|
||||
import kotlinx.atomicfu.locks.withLock
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.MiraiConsoleImplementation.ConsoleDataScope.Companion.get
|
||||
import net.mamoe.mirai.console.command.*
|
||||
import net.mamoe.mirai.console.command.Command.Companion.allNames
|
||||
@ -37,7 +36,7 @@ internal class CommandManagerImpl(
|
||||
parentCoroutineContext: CoroutineContext
|
||||
) : CommandManager, CoroutineScope by parentCoroutineContext.childScope("CommandManagerImpl") {
|
||||
private val logger: MiraiLogger by lazy {
|
||||
MiraiConsole.createLogger("command")
|
||||
MiraiLogger.Factory.create(CommandManager::class, "command")
|
||||
}
|
||||
|
||||
@Suppress("ObjectPropertyName")
|
||||
|
@ -41,7 +41,8 @@ internal class BuiltInJvmPluginLoaderImpl(
|
||||
JvmPluginLoader {
|
||||
|
||||
companion object {
|
||||
internal val logger: MiraiLogger = MiraiConsole.createLogger(JvmPluginLoader::class.simpleName!!)
|
||||
internal val logger: MiraiLogger =
|
||||
MiraiLogger.Factory.create(JvmPluginLoader::class)
|
||||
}
|
||||
|
||||
fun pluginsFilesSequence(
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
package net.mamoe.mirai.console.internal.plugin
|
||||
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.plugin.jvm.ExportManager
|
||||
import net.mamoe.mirai.console.plugin.jvm.JvmPluginClasspath
|
||||
import net.mamoe.mirai.utils.*
|
||||
@ -197,7 +196,12 @@ internal class JvmPluginClassLoaderN : URLClassLoader {
|
||||
private val file_: File
|
||||
get() = file
|
||||
|
||||
var linkedLogger by lateinitMutableProperty { MiraiConsole.createLogger("JvmPlugin[" + file_.name + "]") }
|
||||
var linkedLogger by lateinitMutableProperty {
|
||||
MiraiLogger.Factory.create(
|
||||
JvmPluginClassLoaderN::class,
|
||||
"JvmPlugin[" + file_.name + "]"
|
||||
)
|
||||
}
|
||||
val undefinedDependencies = mutableSetOf<String>()
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
|
@ -65,7 +65,7 @@ internal abstract class JvmPluginInternal(
|
||||
// region JvmPlugin
|
||||
final override val logger: MiraiLogger by lazy {
|
||||
BuiltInJvmPluginLoaderImpl.logger.runCatchingLog {
|
||||
MiraiConsole.createLogger(this.description.name)
|
||||
MiraiLogger.Factory.create(this@JvmPluginInternal::class, this.description.name)
|
||||
}.getOrThrow()
|
||||
}
|
||||
|
||||
|
@ -26,10 +26,7 @@ import net.mamoe.mirai.console.plugin.loader.PluginLoadException
|
||||
import net.mamoe.mirai.console.plugin.loader.PluginLoader
|
||||
import net.mamoe.mirai.console.plugin.name
|
||||
import net.mamoe.mirai.console.util.SemVersion
|
||||
import net.mamoe.mirai.utils.TestOnly
|
||||
import net.mamoe.mirai.utils.cast
|
||||
import net.mamoe.mirai.utils.childScope
|
||||
import net.mamoe.mirai.utils.info
|
||||
import net.mamoe.mirai.utils.*
|
||||
import java.io.File
|
||||
import java.nio.file.Path
|
||||
import java.util.concurrent.CopyOnWriteArrayList
|
||||
@ -60,7 +57,7 @@ internal class PluginManagerImpl(
|
||||
builtInLoaders.toMutableList()
|
||||
}
|
||||
|
||||
private val logger = MiraiConsole.createLogger("plugin")
|
||||
private val logger = MiraiLogger.Factory.create(PluginManager::class, "plugin")
|
||||
|
||||
@JvmField
|
||||
internal val resolvedPlugins: MutableList<Plugin> =
|
||||
|
@ -22,6 +22,11 @@ import org.junit.jupiter.api.AfterEach
|
||||
import kotlin.test.BeforeTest
|
||||
|
||||
abstract class AbstractConsoleInstanceTest {
|
||||
init {
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
net.mamoe.mirai.utils.MiraiLoggerFactoryImplementationBridge.reinit()
|
||||
}
|
||||
|
||||
val mockPlugin by lazy { mockKotlinPlugin() }
|
||||
private lateinit var implementation: MiraiConsoleImplementation
|
||||
val consoleImplementation: MiraiConsoleImplementation by ::implementation
|
||||
|
@ -76,10 +76,23 @@ open class MockConsoleImplementation : MiraiConsoleImplementation {
|
||||
override fun createLoginSolver(requesterBot: Long, configuration: BotConfiguration): LoginSolver =
|
||||
LoginSolver.Default!!
|
||||
|
||||
@Suppress("DeprecatedCallableAddReplaceWith")
|
||||
@Deprecated(
|
||||
"Deprecated for removal. Implement the other overload, or use MiraiConsole.createLogger instead.",
|
||||
level = DeprecationLevel.ERROR
|
||||
)
|
||||
override fun createLogger(identity: String?): MiraiLogger {
|
||||
return PlatformLogger(identity)
|
||||
}
|
||||
|
||||
override fun createLoggerFactory(platformImplementation: MiraiLogger.Factory): MiraiLogger.Factory {
|
||||
return object : MiraiLogger.Factory {
|
||||
override fun create(requester: Class<*>, identity: String?): MiraiLogger {
|
||||
return PlatformLogger(identity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override val consoleDataScope: MiraiConsoleImplementation.ConsoleDataScope by lazy {
|
||||
MiraiConsoleImplementation.ConsoleDataScope.createDefault(
|
||||
coroutineContext,
|
||||
|
@ -1,10 +1,10 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* 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.
|
||||
* 此源代码的使用受 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/master/LICENSE
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress(
|
||||
@ -55,6 +55,7 @@ import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
import kotlin.concurrent.withLock
|
||||
import kotlin.coroutines.Continuation
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
/**
|
||||
@ -102,14 +103,45 @@ open class MiraiConsoleImplementationTerminal
|
||||
return StandardCharImageLoginSolver(input = { requestInput("LOGIN> ") })
|
||||
}
|
||||
|
||||
@Suppress("DeprecatedCallableAddReplaceWith")
|
||||
@Deprecated(
|
||||
"Deprecated for removal. Implement the other overload, or use MiraiConsole.createLogger instead.",
|
||||
level = DeprecationLevel.ERROR
|
||||
)
|
||||
override fun createLogger(identity: String?): MiraiLogger {
|
||||
return PlatformLogger(identity = identity, output = { line ->
|
||||
val text = line + ANSI_RESET
|
||||
prePrintNewLog()
|
||||
lineReader.printAbove(text)
|
||||
postPrintNewLog()
|
||||
logService.pushLine(text)
|
||||
})
|
||||
return MiraiLogger.Factory.create(MiraiConsoleImplementationTerminal::class, identity)
|
||||
// return PlatformLogger(identity = identity, output = { line ->
|
||||
// val text = line + ANSI_RESET
|
||||
// lineReader.printAbove(text)
|
||||
// logService.pushLine(text)
|
||||
// })
|
||||
}
|
||||
|
||||
override fun createLoggerFactory(platformImplementation: MiraiLogger.Factory): MiraiLogger.Factory {
|
||||
// platformImplementation is not used by Terminal
|
||||
|
||||
return object : MiraiLogger.Factory {
|
||||
override fun create(requester: Class<*>, identity: String?): MiraiLogger {
|
||||
return PlatformLogger(identity = identity ?: requester.simpleName, output = { line ->
|
||||
val text = line + ANSI_RESET
|
||||
prePrintNewLog()
|
||||
lineReader.printAbove(text)
|
||||
postPrintNewLog()
|
||||
logService.pushLine(text)
|
||||
})
|
||||
}
|
||||
|
||||
override fun create(requester: KClass<*>, identity: String?): MiraiLogger {
|
||||
return PlatformLogger(identity = identity ?: requester.simpleName, output = { line ->
|
||||
val text = line + ANSI_RESET
|
||||
prePrintNewLog()
|
||||
lineReader.printAbove(text)
|
||||
postPrintNewLog()
|
||||
logService.pushLine(text)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
|
@ -1,10 +1,10 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* 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.
|
||||
* 此源代码的使用受 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/master/LICENSE
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress(
|
||||
@ -28,10 +28,7 @@ import net.mamoe.mirai.console.terminal.noconsole.SystemOutputPrintStream
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||
import net.mamoe.mirai.console.util.ConsoleInternalApi
|
||||
import net.mamoe.mirai.message.data.Message
|
||||
import net.mamoe.mirai.utils.childScope
|
||||
import net.mamoe.mirai.utils.debug
|
||||
import net.mamoe.mirai.utils.info
|
||||
import net.mamoe.mirai.utils.verbose
|
||||
import net.mamoe.mirai.utils.*
|
||||
import org.jline.utils.Signals
|
||||
import java.io.FileDescriptor
|
||||
import java.io.FileOutputStream
|
||||
@ -48,6 +45,9 @@ import kotlin.system.exitProcess
|
||||
* mirai-console-terminal CLI 入口点
|
||||
*/
|
||||
object MiraiConsoleTerminalLoader {
|
||||
|
||||
// Note: Do not run this in IDEA, as you will get invalid classpath and `java.lang.NoClassDefFoundError`.
|
||||
// Run `RunTerminal.kt` under `test` source set instead.
|
||||
@JvmStatic
|
||||
fun main(args: Array<String>) {
|
||||
parse(args, exitProcess = true)
|
||||
@ -123,19 +123,24 @@ object MiraiConsoleTerminalLoader {
|
||||
if (exitProcess) exitProcess(0)
|
||||
return
|
||||
}
|
||||
|
||||
"--no-console" -> {
|
||||
ConsoleTerminalSettings.noConsole = true
|
||||
}
|
||||
|
||||
"--dont-setup-terminal-ansi" -> {
|
||||
ConsoleTerminalSettings.setupAnsi = false
|
||||
}
|
||||
|
||||
"--no-logging" -> {
|
||||
ConsoleTerminalSettings.noLogging = true
|
||||
}
|
||||
|
||||
"--no-ansi" -> {
|
||||
ConsoleTerminalSettings.noAnsi = true
|
||||
ConsoleTerminalSettings.setupAnsi = false
|
||||
}
|
||||
|
||||
"--reading-replacement" -> {
|
||||
ConsoleTerminalSettings.noConsoleSafeReading = true
|
||||
if (iterator.hasNext()) {
|
||||
@ -148,9 +153,11 @@ object MiraiConsoleTerminalLoader {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
"--safe-reading" -> {
|
||||
ConsoleTerminalSettings.noConsoleSafeReading = true
|
||||
}
|
||||
|
||||
else -> {
|
||||
println("Unknown option `$option`")
|
||||
printHelpMessage()
|
||||
@ -287,7 +294,7 @@ internal fun overrideSTD(terminal: MiraiConsoleImplementation) {
|
||||
System.setOut(
|
||||
PrintStream(
|
||||
BufferedOutputStream(
|
||||
logger = terminal.createLogger("stdout")::info
|
||||
logger = MiraiLogger.Factory.create(terminal::class, "stdout")::info
|
||||
),
|
||||
false,
|
||||
"UTF-8"
|
||||
@ -296,7 +303,7 @@ internal fun overrideSTD(terminal: MiraiConsoleImplementation) {
|
||||
System.setErr(
|
||||
PrintStream(
|
||||
BufferedOutputStream(
|
||||
logger = terminal.createLogger("stderr")::warning
|
||||
logger = MiraiLogger.Factory.create(terminal::class, "stderr")::warning
|
||||
),
|
||||
false,
|
||||
"UTF-8"
|
||||
|
@ -6162,7 +6162,7 @@ public abstract interface class net/mamoe/mirai/utils/MiraiLogger {
|
||||
public fun isVerboseEnabled ()Z
|
||||
public fun isWarningEnabled ()Z
|
||||
public synthetic fun plus (Lnet/mamoe/mirai/utils/MiraiLogger;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public static fun setDefaultLoggerCreator (Lkotlin/jvm/functions/Function1;)V
|
||||
public static synthetic fun setDefaultLoggerCreator (Lkotlin/jvm/functions/Function1;)V
|
||||
public synthetic fun setFollower (Lnet/mamoe/mirai/utils/MiraiLogger;)V
|
||||
public abstract fun verbose (Ljava/lang/String;)V
|
||||
public abstract fun verbose (Ljava/lang/String;Ljava/lang/Throwable;)V
|
||||
@ -6175,7 +6175,7 @@ public abstract interface class net/mamoe/mirai/utils/MiraiLogger {
|
||||
public final class net/mamoe/mirai/utils/MiraiLogger$Companion {
|
||||
public final synthetic fun create (Ljava/lang/String;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public final synthetic fun getTopLevel ()Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public final fun setDefaultLoggerCreator (Lkotlin/jvm/functions/Function1;)V
|
||||
public final synthetic fun setDefaultLoggerCreator (Lkotlin/jvm/functions/Function1;)V
|
||||
}
|
||||
|
||||
public abstract interface class net/mamoe/mirai/utils/MiraiLogger$Factory {
|
||||
|
@ -6162,7 +6162,7 @@ public abstract interface class net/mamoe/mirai/utils/MiraiLogger {
|
||||
public fun isVerboseEnabled ()Z
|
||||
public fun isWarningEnabled ()Z
|
||||
public synthetic fun plus (Lnet/mamoe/mirai/utils/MiraiLogger;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public static fun setDefaultLoggerCreator (Lkotlin/jvm/functions/Function1;)V
|
||||
public static synthetic fun setDefaultLoggerCreator (Lkotlin/jvm/functions/Function1;)V
|
||||
public synthetic fun setFollower (Lnet/mamoe/mirai/utils/MiraiLogger;)V
|
||||
public abstract fun verbose (Ljava/lang/String;)V
|
||||
public abstract fun verbose (Ljava/lang/String;Ljava/lang/Throwable;)V
|
||||
@ -6175,7 +6175,7 @@ public abstract interface class net/mamoe/mirai/utils/MiraiLogger {
|
||||
public final class net/mamoe/mirai/utils/MiraiLogger$Companion {
|
||||
public final synthetic fun create (Ljava/lang/String;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public final synthetic fun getTopLevel ()Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public final fun setDefaultLoggerCreator (Lkotlin/jvm/functions/Function1;)V
|
||||
public final synthetic fun setDefaultLoggerCreator (Lkotlin/jvm/functions/Function1;)V
|
||||
}
|
||||
|
||||
public abstract interface class net/mamoe/mirai/utils/MiraiLogger$Factory {
|
||||
|
@ -32,9 +32,16 @@ public object LoggerAdapters {
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun useLog4j2() {
|
||||
DefaultFactoryOverrides.override { requester, identity ->
|
||||
val logger = LogManager.getLogger(requester)
|
||||
Log4jLoggerAdapter(logger, MarkerManager.getMarker(identity ?: logger.name).addParents(MARKER_MIRAI))
|
||||
MiraiLoggerFactoryImplementationBridge.wrapCurrent {
|
||||
object : MiraiLogger.Factory {
|
||||
override fun create(requester: Class<*>, identity: String?): MiraiLogger {
|
||||
val logger = LogManager.getLogger(requester)
|
||||
return Log4jLoggerAdapter(
|
||||
logger,
|
||||
MarkerManager.getMarker(identity ?: logger.name).addParents(MARKER_MIRAI)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,8 +12,13 @@
|
||||
|
||||
package net.mamoe.mirai.utils
|
||||
|
||||
import kotlinx.atomicfu.atomic
|
||||
import kotlinx.atomicfu.loop
|
||||
import me.him188.kotlin.dynamic.delegation.dynamicDelegation
|
||||
import net.mamoe.mirai.utils.*
|
||||
import java.util.*
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
@ -27,7 +32,7 @@ import kotlin.reflect.KClass
|
||||
*
|
||||
* ## 使用第三方日志库接管 Mirai 日志系统
|
||||
*
|
||||
* 使用 [LoggerAdapters], 将第三方日志 `Logger` 转为 [MiraiLogger]. 然后通过 [MiraiLogger.setDefaultLoggerCreator] 全局覆盖日志.
|
||||
* 使用 [LoggerAdapters], 将第三方日志 `Logger` 转为 [MiraiLogger]. 然后通过 [MiraiLogger.Factory] 提供实现.
|
||||
*
|
||||
* ## 实现或使用 [MiraiLogger]
|
||||
*
|
||||
@ -79,7 +84,8 @@ public actual interface MiraiLogger {
|
||||
*/
|
||||
public fun create(requester: Class<*>): MiraiLogger = create(requester, null)
|
||||
|
||||
public actual companion object INSTANCE : Factory by loadService(Factory::class, { DefaultFactory() })
|
||||
public actual companion object INSTANCE :
|
||||
Factory by dynamicDelegation({ MiraiLoggerFactoryImplementationBridge })
|
||||
}
|
||||
|
||||
public actual companion object {
|
||||
@ -95,21 +101,21 @@ public actual interface MiraiLogger {
|
||||
/**
|
||||
* 已弃用, 请实现 service [net.mamoe.mirai.utils.MiraiLogger.Factory] 并以 [ServiceLoader] 支持的方式提供.
|
||||
*/
|
||||
@Suppress("DeprecatedCallableAddReplaceWith")
|
||||
@Deprecated(
|
||||
"Please set factory by providing an service of type net.mamoe.mirai.utils.MiraiLogger.Factory",
|
||||
level = DeprecationLevel.ERROR
|
||||
level = DeprecationLevel.HIDDEN
|
||||
) // deprecated since 2.7
|
||||
@JvmStatic
|
||||
@DeprecatedSinceMirai(warningSince = "2.7", errorSince = "2.10") // left ERROR intentionally, for internal uses.
|
||||
public fun setDefaultLoggerCreator(creator: (identity: String?) -> MiraiLogger) {
|
||||
DefaultFactoryOverrides.override { _, identity -> creator(identity) }
|
||||
@DeprecatedSinceMirai(warningSince = "2.7", errorSince = "2.10", hiddenSince = "2.13")
|
||||
public fun setDefaultLoggerCreator(@Suppress("UNUSED_PARAMETER") creator: (identity: String?) -> MiraiLogger) {
|
||||
// nop
|
||||
|
||||
|
||||
// DefaultFactoryOverrides.override { _, identity -> creator(identity) }
|
||||
}
|
||||
|
||||
/**
|
||||
* 旧版本用于创建 [MiraiLogger]. 已弃用. 请使用 [MiraiLogger.Factory.INSTANCE.create].
|
||||
*
|
||||
* @see setDefaultLoggerCreator
|
||||
*/
|
||||
@Deprecated(
|
||||
"Please use MiraiLogger.Factory.create", ReplaceWith(
|
||||
@ -249,33 +255,75 @@ public actual interface MiraiLogger {
|
||||
public actual fun call(priority: SimpleLogger.LogPriority, message: String?, e: Throwable?): Unit =
|
||||
priority.correspondingFunction(this, message, e)
|
||||
|
||||
@Suppress("DeprecatedCallableAddReplaceWith")
|
||||
@Deprecated("plus 设计不佳, 请避免使用.", level = DeprecationLevel.HIDDEN) // deprecated since 2.7
|
||||
@DeprecatedSinceMirai(warningSince = "2.7", errorSince = "2.10", hiddenSince = "2.11")
|
||||
public operator fun <T : MiraiLogger> plus(follower: T): T = follower
|
||||
}
|
||||
|
||||
// used by Mirai Console
|
||||
/**
|
||||
* @since 2.13
|
||||
*/
|
||||
internal object MiraiLoggerFactoryImplementationBridge : MiraiLogger.Factory {
|
||||
@Volatile
|
||||
var instance: MiraiLogger.Factory = createPlatformInstance()
|
||||
private set
|
||||
|
||||
internal object DefaultFactoryOverrides {
|
||||
var override: ((requester: Class<*>, identity: String?) -> MiraiLogger)? =
|
||||
null // 支持 LoggerAdapters 以及兼容旧版本
|
||||
fun createPlatformInstance() = loadService(MiraiLogger.Factory::class) { DefaultFactory() }
|
||||
|
||||
@JvmStatic
|
||||
fun override(lambda: (requester: Class<*>, identity: String?) -> MiraiLogger) {
|
||||
override = lambda
|
||||
private val frozen = atomic(false)
|
||||
|
||||
fun freeze(): Boolean {
|
||||
return frozen.compareAndSet(expect = false, update = true)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun clearOverride() {
|
||||
override = null
|
||||
@TestOnly
|
||||
fun reinit() {
|
||||
frozen.loop { value ->
|
||||
instance = createPlatformInstance()
|
||||
if (frozen.compareAndSet(value, false)) return
|
||||
}
|
||||
}
|
||||
|
||||
fun setInstance(instance: MiraiLogger.Factory) {
|
||||
if (frozen.value) {
|
||||
error(
|
||||
"LoggerFactory instance had been frozen, so it's impossible to override it." +
|
||||
"If you are using Mirai Console and you want to override platform logging implementation, " +
|
||||
"please do so before initialization of MiraiConsole, that is, before `MiraiConsoleImplementation.start()`. " +
|
||||
"Plugins are not allowed to override logging implementation, and this is done in the very fundamental implementation of Mirai Console so there is no way to escape that." +
|
||||
"Normally it is only sensible for Mirai Console frontend implementor to do that." +
|
||||
"If you are just using mirai-core, this error should not happen. There should be no limitation in overriding logging implementation with mirai-core. " +
|
||||
"Check if you actually did use mirai-console somewhere, or please file an issue on https://github.com/mamoe/mirai/issues/new/choose"
|
||||
)
|
||||
}
|
||||
this.instance = instance
|
||||
}
|
||||
|
||||
inline fun wrapCurrent(mapper: (current: MiraiLogger.Factory) -> MiraiLogger.Factory) {
|
||||
contract { callsInPlace(mapper, InvocationKind.EXACTLY_ONCE) }
|
||||
setInstance(this.instance.let(mapper))
|
||||
}
|
||||
|
||||
override fun create(requester: KClass<*>, identity: String?): MiraiLogger {
|
||||
return instance.create(requester, identity)
|
||||
}
|
||||
}
|
||||
|
||||
internal class DefaultFactory : MiraiLogger.Factory {
|
||||
override fun create(requester: Class<*>, identity: String?): MiraiLogger {
|
||||
val override = DefaultFactoryOverrides.override
|
||||
return if (override != null) override(requester, identity) else PlatformLogger(
|
||||
identity ?: requester.kotlin.simpleName ?: requester.simpleName
|
||||
)
|
||||
return instance.create(requester, identity)
|
||||
}
|
||||
|
||||
override fun create(requester: KClass<*>): MiraiLogger {
|
||||
return instance.create(requester)
|
||||
}
|
||||
|
||||
override fun create(requester: Class<*>): MiraiLogger {
|
||||
return instance.create(requester)
|
||||
}
|
||||
}
|
||||
|
||||
private class DefaultFactory : MiraiLogger.Factory {
|
||||
override fun create(requester: Class<*>, identity: String?): MiraiLogger {
|
||||
return PlatformLogger(identity ?: requester.kotlin.simpleName ?: requester.simpleName)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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.logging
|
||||
|
||||
import net.mamoe.mirai.utils.MiraiLoggerFactoryImplementationBridge
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
|
||||
internal abstract class AbstractLoggingTest {
|
||||
@AfterEach
|
||||
fun cleanup() {
|
||||
MiraiLoggerFactoryImplementationBridge.run { setInstance(createPlatformInstance()) }
|
||||
}
|
||||
}
|
@ -11,26 +11,25 @@ package net.mamoe.mirai.logging
|
||||
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.internal.utils.*
|
||||
import net.mamoe.mirai.utils.DefaultFactoryOverrides
|
||||
import net.mamoe.mirai.utils.LoggerAdapters.asMiraiLogger
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import net.mamoe.mirai.utils.MiraiLoggerFactoryImplementationBridge
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import kotlin.test.*
|
||||
|
||||
internal class Log4j2LoggingTest {
|
||||
internal class Log4j2LoggingTest : AbstractLoggingTest() {
|
||||
@BeforeTest
|
||||
fun init() {
|
||||
DefaultFactoryOverrides.override { requester, identity ->
|
||||
LogManager.getLogger(requester).asMiraiLogger(Marker(identity ?: requester.simpleName, MARKER_MIRAI))
|
||||
MiraiLoggerFactoryImplementationBridge.wrapCurrent {
|
||||
object : MiraiLogger.Factory {
|
||||
override fun create(requester: Class<*>, identity: String?): MiraiLogger {
|
||||
return LogManager.getLogger(requester)
|
||||
.asMiraiLogger(Marker(identity ?: requester.simpleName, MARKER_MIRAI))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
fun cleanup() {
|
||||
DefaultFactoryOverrides.clearOverride()
|
||||
}
|
||||
|
||||
private fun MiraiLogger.cast(): Log4jLoggerAdapter = this as Log4jLoggerAdapter
|
||||
|
||||
@Test
|
||||
|
@ -10,20 +10,26 @@
|
||||
package net.mamoe.mirai.logging
|
||||
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import net.mamoe.mirai.utils.MiraiLoggerFactoryImplementationBridge
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertIs
|
||||
|
||||
internal class LoggingCompatibilityTest {
|
||||
internal class LoggingCompatibilityTest : AbstractLoggingTest() {
|
||||
|
||||
@Suppress("DEPRECATION_ERROR")
|
||||
@Test
|
||||
fun `legacy overrides are still working if no services are found`() {
|
||||
val messages = StringBuilder()
|
||||
|
||||
MiraiLogger.setDefaultLoggerCreator {
|
||||
net.mamoe.mirai.utils.SimpleLogger("my logger") { message: String?, _: Throwable? ->
|
||||
messages.append(message)
|
||||
MiraiLoggerFactoryImplementationBridge.wrapCurrent {
|
||||
object : MiraiLogger.Factory {
|
||||
override fun create(requester: Class<*>, identity: String?): MiraiLogger {
|
||||
return net.mamoe.mirai.utils.SimpleLogger("my logger") { message: String?, _: Throwable? ->
|
||||
messages.append(message)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ import net.mamoe.mirai.utils.MiraiLogger
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider
|
||||
import java.security.Security
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertTrue
|
||||
import kotlin.test.assertIs
|
||||
|
||||
internal actual fun initPlatform() {
|
||||
init
|
||||
@ -32,9 +32,7 @@ internal actual class PlatformInitializationTest : AbstractTest() {
|
||||
|
||||
@Test
|
||||
actual fun test() {
|
||||
assertTrue {
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
MiraiLogger.Factory.create(this::class, "1") is net.mamoe.mirai.internal.utils.StdoutLogger
|
||||
}
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
assertIs<net.mamoe.mirai.internal.utils.StdoutLogger>(MiraiLogger.Factory.create(this::class, "1"))
|
||||
}
|
||||
}
|
@ -51,9 +51,17 @@ internal actual abstract class AbstractTest actual constructor() : CommonAbstrac
|
||||
|
||||
DebugProbes.install()
|
||||
|
||||
@Suppress("DEPRECATION_ERROR")
|
||||
MiraiLogger.setDefaultLoggerCreator {
|
||||
SynchronizedStdoutLogger(it)
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
net.mamoe.mirai.utils.MiraiLoggerFactoryImplementationBridge.wrapCurrent {
|
||||
object : MiraiLogger.Factory {
|
||||
override fun create(requester: Class<*>, identity: String?): MiraiLogger {
|
||||
return SynchronizedStdoutLogger(identity ?: requester.simpleName)
|
||||
}
|
||||
|
||||
override fun create(requester: KClass<*>, identity: String?): MiraiLogger {
|
||||
return SynchronizedStdoutLogger(identity ?: requester.simpleName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setSystemProp("mirai.network.packet.logger", "true")
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Mamoe Technologies and contributors.
|
||||
* 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.
|
||||
@ -12,10 +12,7 @@
|
||||
package net.mamoe.mirai.internal.netinternalkit
|
||||
|
||||
import kotlinx.atomicfu.locks.withLock
|
||||
import net.mamoe.mirai.utils.DefaultFactoryOverrides
|
||||
import net.mamoe.mirai.utils.PlatformLogger
|
||||
import net.mamoe.mirai.utils.SizedCache
|
||||
import net.mamoe.mirai.utils.currentTimeMillis
|
||||
import net.mamoe.mirai.utils.*
|
||||
import java.io.File
|
||||
|
||||
internal object LogCapture {
|
||||
@ -28,12 +25,17 @@ internal object LogCapture {
|
||||
|
||||
fun setupCapture(maxLine: Int = 200) {
|
||||
logCache = SizedCache(maxLine)
|
||||
|
||||
@Suppress("INVISIBLE_MEMBER")
|
||||
DefaultFactoryOverrides.override { requester, identity ->
|
||||
PlatformLogger(
|
||||
identity ?: requester.kotlin.simpleName ?: requester.simpleName,
|
||||
output
|
||||
)
|
||||
MiraiLoggerFactoryImplementationBridge.wrapCurrent {
|
||||
object : MiraiLogger.Factory {
|
||||
override fun create(requester: Class<*>, identity: String?): MiraiLogger {
|
||||
return PlatformLogger(
|
||||
identity ?: requester.kotlin.simpleName ?: requester.simpleName,
|
||||
output
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NetReplayHelperSettings.logger_console = PlatformLogger(
|
||||
|
Loading…
Reference in New Issue
Block a user