mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-05 07:30:09 +08:00
Improve logging: use Log4j internally and support markers
Migrate usages of `MiraiLogger.create` to new API apiDump for new logging
This commit is contained in:
parent
2562099884
commit
5950e9e1e8
@ -5651,15 +5651,20 @@ public abstract interface class net/mamoe/mirai/utils/MiraiLogger {
|
||||
public abstract fun error (Ljava/lang/String;)V
|
||||
public abstract fun error (Ljava/lang/String;Ljava/lang/Throwable;)V
|
||||
public fun error (Ljava/lang/Throwable;)V
|
||||
public abstract fun getFollower ()Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public fun getFollower ()Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public abstract fun getIdentity ()Ljava/lang/String;
|
||||
public abstract fun info (Ljava/lang/String;)V
|
||||
public abstract fun info (Ljava/lang/String;Ljava/lang/Throwable;)V
|
||||
public fun info (Ljava/lang/Throwable;)V
|
||||
public fun isDebugEnabled ()Z
|
||||
public abstract fun isEnabled ()Z
|
||||
public abstract fun plus (Lnet/mamoe/mirai/utils/MiraiLogger;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public fun isErrorEnabled ()Z
|
||||
public fun isInfoEnabled ()Z
|
||||
public fun isVerboseEnabled ()Z
|
||||
public fun isWarningEnabled ()Z
|
||||
public fun plus (Lnet/mamoe/mirai/utils/MiraiLogger;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public static fun setDefaultLoggerCreator (Lkotlin/jvm/functions/Function1;)V
|
||||
public abstract fun setFollower (Lnet/mamoe/mirai/utils/MiraiLogger;)V
|
||||
public 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
|
||||
public fun verbose (Ljava/lang/Throwable;)V
|
||||
@ -5674,6 +5679,23 @@ public final class net/mamoe/mirai/utils/MiraiLogger$Companion {
|
||||
public final fun setDefaultLoggerCreator (Lkotlin/jvm/functions/Function1;)V
|
||||
}
|
||||
|
||||
public abstract interface class net/mamoe/mirai/utils/MiraiLogger$Factory {
|
||||
public static final field INSTANCE Lnet/mamoe/mirai/utils/MiraiLogger$Factory$INSTANCE;
|
||||
public fun create (Ljava/lang/Class;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public abstract fun create (Ljava/lang/Class;Ljava/lang/String;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public fun create (Lkotlin/reflect/KClass;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public fun create (Lkotlin/reflect/KClass;Ljava/lang/String;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public static synthetic fun create$default (Lnet/mamoe/mirai/utils/MiraiLogger$Factory;Ljava/lang/Class;Ljava/lang/String;ILjava/lang/Object;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public static synthetic fun create$default (Lnet/mamoe/mirai/utils/MiraiLogger$Factory;Lkotlin/reflect/KClass;Ljava/lang/String;ILjava/lang/Object;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/utils/MiraiLogger$Factory$INSTANCE : net/mamoe/mirai/utils/MiraiLogger$Factory {
|
||||
public fun create (Ljava/lang/Class;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public fun create (Ljava/lang/Class;Ljava/lang/String;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public fun create (Lkotlin/reflect/KClass;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public fun create (Lkotlin/reflect/KClass;Ljava/lang/String;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
}
|
||||
|
||||
public abstract class net/mamoe/mirai/utils/MiraiLoggerPlatformBase : net/mamoe/mirai/utils/MiraiLogger {
|
||||
public fun <init> ()V
|
||||
public final fun debug (Ljava/lang/String;)V
|
||||
@ -5939,7 +5961,12 @@ public final class net/mamoe/mirai/utils/SingleFileLogger : net/mamoe/mirai/util
|
||||
public fun info (Ljava/lang/String;)V
|
||||
public fun info (Ljava/lang/String;Ljava/lang/Throwable;)V
|
||||
public fun info (Ljava/lang/Throwable;)V
|
||||
public fun isDebugEnabled ()Z
|
||||
public fun isEnabled ()Z
|
||||
public fun isErrorEnabled ()Z
|
||||
public fun isInfoEnabled ()Z
|
||||
public fun isVerboseEnabled ()Z
|
||||
public fun isWarningEnabled ()Z
|
||||
public fun plus (Lnet/mamoe/mirai/utils/MiraiLogger;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public fun setFollower (Lnet/mamoe/mirai/utils/MiraiLogger;)V
|
||||
public fun verbose (Ljava/lang/String;)V
|
||||
|
@ -5651,15 +5651,20 @@ public abstract interface class net/mamoe/mirai/utils/MiraiLogger {
|
||||
public abstract fun error (Ljava/lang/String;)V
|
||||
public abstract fun error (Ljava/lang/String;Ljava/lang/Throwable;)V
|
||||
public fun error (Ljava/lang/Throwable;)V
|
||||
public abstract fun getFollower ()Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public fun getFollower ()Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public abstract fun getIdentity ()Ljava/lang/String;
|
||||
public abstract fun info (Ljava/lang/String;)V
|
||||
public abstract fun info (Ljava/lang/String;Ljava/lang/Throwable;)V
|
||||
public fun info (Ljava/lang/Throwable;)V
|
||||
public fun isDebugEnabled ()Z
|
||||
public abstract fun isEnabled ()Z
|
||||
public abstract fun plus (Lnet/mamoe/mirai/utils/MiraiLogger;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public fun isErrorEnabled ()Z
|
||||
public fun isInfoEnabled ()Z
|
||||
public fun isVerboseEnabled ()Z
|
||||
public fun isWarningEnabled ()Z
|
||||
public fun plus (Lnet/mamoe/mirai/utils/MiraiLogger;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public static fun setDefaultLoggerCreator (Lkotlin/jvm/functions/Function1;)V
|
||||
public abstract fun setFollower (Lnet/mamoe/mirai/utils/MiraiLogger;)V
|
||||
public 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
|
||||
public fun verbose (Ljava/lang/Throwable;)V
|
||||
@ -5674,6 +5679,23 @@ public final class net/mamoe/mirai/utils/MiraiLogger$Companion {
|
||||
public final fun setDefaultLoggerCreator (Lkotlin/jvm/functions/Function1;)V
|
||||
}
|
||||
|
||||
public abstract interface class net/mamoe/mirai/utils/MiraiLogger$Factory {
|
||||
public static final field INSTANCE Lnet/mamoe/mirai/utils/MiraiLogger$Factory$INSTANCE;
|
||||
public fun create (Ljava/lang/Class;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public abstract fun create (Ljava/lang/Class;Ljava/lang/String;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public fun create (Lkotlin/reflect/KClass;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public fun create (Lkotlin/reflect/KClass;Ljava/lang/String;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public static synthetic fun create$default (Lnet/mamoe/mirai/utils/MiraiLogger$Factory;Ljava/lang/Class;Ljava/lang/String;ILjava/lang/Object;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public static synthetic fun create$default (Lnet/mamoe/mirai/utils/MiraiLogger$Factory;Lkotlin/reflect/KClass;Ljava/lang/String;ILjava/lang/Object;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/utils/MiraiLogger$Factory$INSTANCE : net/mamoe/mirai/utils/MiraiLogger$Factory {
|
||||
public fun create (Ljava/lang/Class;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public fun create (Ljava/lang/Class;Ljava/lang/String;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public fun create (Lkotlin/reflect/KClass;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
public fun create (Lkotlin/reflect/KClass;Ljava/lang/String;)Lnet/mamoe/mirai/utils/MiraiLogger;
|
||||
}
|
||||
|
||||
public abstract class net/mamoe/mirai/utils/MiraiLoggerPlatformBase : net/mamoe/mirai/utils/MiraiLogger {
|
||||
public fun <init> ()V
|
||||
public final fun debug (Ljava/lang/String;)V
|
||||
|
@ -40,7 +40,7 @@ object Versions {
|
||||
const val shadow = "6.1.0"
|
||||
|
||||
const val slf4j = "1.7.30"
|
||||
const val log4j = "2.13.3"
|
||||
const val log4j = "2.14.1"
|
||||
const val asm = "9.1"
|
||||
const val difflib = "1.3.0"
|
||||
const val netty = "4.1.63.Final"
|
||||
@ -82,12 +82,15 @@ val `ktor-client-core` = ktor("client-core", Versions.ktor)
|
||||
val `ktor-client-cio` = ktor("client-cio", Versions.ktor)
|
||||
val `ktor-client-okhttp` = ktor("client-okhttp", Versions.ktor)
|
||||
val `ktor-client-android` = ktor("client-android", Versions.ktor)
|
||||
val `ktor-client-logging` = ktor("client-logging", Versions.ktor)
|
||||
val `ktor-network` = ktor("network", Versions.ktor)
|
||||
val `ktor-client-serialization-jvm` = ktor("client-serialization-jvm", Versions.ktor)
|
||||
|
||||
const val slf4j = "org.slf4j:slf4j-api:" + Versions.slf4j
|
||||
const val `slf4j-api` = "org.slf4j:slf4j-api:" + Versions.slf4j
|
||||
const val `slf4j-simple` = "org.slf4j:slf4j-simple:" + Versions.slf4j
|
||||
const val `log4j-api` = "org.apache.logging.log4j:log4j-api:" + Versions.log4j
|
||||
const val `log4j-core` = "org.apache.logging.log4j:log4j-core:" + Versions.log4j
|
||||
const val `log4j-slf4j-impl` = "org.apache.logging.log4j:log4j-slf4j-impl:" + Versions.log4j
|
||||
|
||||
val ATTRIBUTE_MIRAI_TARGET_PLATFORM: Attribute<String> = Attribute.of("mirai.target.platform", String::class.java)
|
||||
|
||||
|
@ -66,8 +66,8 @@ kotlin {
|
||||
api(`ktor-client-core`)
|
||||
api(`ktor-network`)
|
||||
|
||||
compileOnly(`log4j-api`)
|
||||
compileOnly(slf4j)
|
||||
implementation(`log4j-api`)
|
||||
compileOnly(`slf4j-api`)
|
||||
|
||||
|
||||
// they use Kotlin 1.3 so we need to ignore transitive dependencies
|
||||
@ -77,6 +77,12 @@ kotlin {
|
||||
}
|
||||
}
|
||||
|
||||
commonTest {
|
||||
dependencies {
|
||||
runtimeOnly(`log4j-core`)
|
||||
}
|
||||
}
|
||||
|
||||
if (isAndroidSDKAvailable) {
|
||||
val androidMain by getting {
|
||||
dependsOn(commonMain)
|
||||
|
@ -190,7 +190,7 @@ internal open class _EventBroadcast {
|
||||
}
|
||||
}
|
||||
|
||||
private val topLevelEventLogger by lazy { MiraiLogger.create("EventPipeline") }
|
||||
private val topLevelEventLogger by lazy { MiraiLogger.Factory.create(Event::class, "EventPipeline") }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -21,7 +21,7 @@ internal object ExternalResourceLeakObserver : Runnable {
|
||||
private val queue = ReferenceQueue<Any>()
|
||||
private val references = ConcurrentLinkedDeque<ERReference>()
|
||||
private val logger by lazy {
|
||||
MiraiLogger.create("ExternalResourceLeakObserver")
|
||||
MiraiLogger.Factory.create(ExternalResourceLeakObserver::class)
|
||||
}
|
||||
|
||||
internal class ERReference(
|
||||
|
@ -10,83 +10,127 @@
|
||||
package net.mamoe.mirai.internal.utils
|
||||
|
||||
import net.mamoe.mirai.utils.MiraiLoggerPlatformBase
|
||||
import org.slf4j.Logger
|
||||
import java.util.logging.Level
|
||||
import org.apache.logging.log4j.Marker
|
||||
import org.apache.logging.log4j.MarkerManager
|
||||
import java.util.logging.Level as JulLevel
|
||||
import java.util.logging.Logger as JulLogger
|
||||
|
||||
internal class Log4jLogger(private val logger: org.apache.logging.log4j.Logger) : MiraiLoggerPlatformBase() {
|
||||
internal class Log4jLoggerAdapter(
|
||||
private val logger: org.apache.logging.log4j.Logger,
|
||||
override val marker: Marker?,
|
||||
) : MiraiLoggerPlatformBase(), MarkedMiraiLogger {
|
||||
|
||||
override fun verbose0(message: String?, e: Throwable?) {
|
||||
logger.trace(message, e)
|
||||
val marker = marker
|
||||
if (marker != null) logger.trace(marker, message, e)
|
||||
else logger.trace(message, e)
|
||||
}
|
||||
|
||||
override fun debug0(message: String?, e: Throwable?) {
|
||||
logger.debug(message, e)
|
||||
val marker = marker
|
||||
if (marker != null) logger.debug(marker, message, e)
|
||||
else logger.debug(message, e)
|
||||
}
|
||||
|
||||
override fun info0(message: String?, e: Throwable?) {
|
||||
logger.info(message, e)
|
||||
val marker = marker
|
||||
if (marker != null) logger.info(marker, message, e)
|
||||
else logger.info(message, e)
|
||||
}
|
||||
|
||||
override fun warning0(message: String?, e: Throwable?) {
|
||||
logger.warn(message, e)
|
||||
val marker = marker
|
||||
if (marker != null) logger.warn(marker, message, e)
|
||||
else logger.warn(message, e)
|
||||
}
|
||||
|
||||
override fun error0(message: String?, e: Throwable?) {
|
||||
logger.error(message, e)
|
||||
val marker = marker
|
||||
if (marker != null) logger.error(marker, message, e)
|
||||
else logger.error(message, e)
|
||||
}
|
||||
|
||||
override val identity: String?
|
||||
get() = logger.name
|
||||
override val isVerboseEnabled: Boolean get() = logger.isTraceEnabled
|
||||
override val isDebugEnabled: Boolean get() = logger.isDebugEnabled
|
||||
override val isInfoEnabled: Boolean get() = logger.isInfoEnabled
|
||||
override val isWarningEnabled: Boolean get() = logger.isWarnEnabled
|
||||
override val isErrorEnabled: Boolean get() = logger.isErrorEnabled
|
||||
|
||||
override val identity: String? get() = logger.name
|
||||
|
||||
override fun subLogger(name: String): MarkedMiraiLogger {
|
||||
return Log4jLoggerAdapter(logger, Marker(name, marker))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal class Slf4jLogger(private val logger: Logger) : MiraiLoggerPlatformBase() {
|
||||
internal val MARKER_MIRAI by lazy { MarkerManager.getMarker("mirai") }
|
||||
|
||||
internal class Slf4jLoggerAdapter(private val logger: org.slf4j.Logger, private val marker: org.slf4j.Marker?) :
|
||||
MiraiLoggerPlatformBase() {
|
||||
override fun verbose0(message: String?, e: Throwable?) {
|
||||
logger.trace(message, e)
|
||||
if (marker == null) logger.trace(message, e)
|
||||
else logger.trace(marker, message, e)
|
||||
}
|
||||
|
||||
override fun debug0(message: String?, e: Throwable?) {
|
||||
logger.debug(message, e)
|
||||
if (marker == null) logger.debug(message, e)
|
||||
else logger.debug(marker, message, e)
|
||||
}
|
||||
|
||||
override fun info0(message: String?, e: Throwable?) {
|
||||
logger.info(message, e)
|
||||
if (marker == null) logger.info(message, e)
|
||||
else logger.info(marker, message, e)
|
||||
}
|
||||
|
||||
override fun warning0(message: String?, e: Throwable?) {
|
||||
logger.warn(message, e)
|
||||
if (marker == null) logger.warn(message, e)
|
||||
else logger.warn(marker, message, e)
|
||||
}
|
||||
|
||||
override fun error0(message: String?, e: Throwable?) {
|
||||
logger.error(message, e)
|
||||
if (marker == null) logger.error(message, e)
|
||||
else logger.error(marker, message, e)
|
||||
}
|
||||
|
||||
override val isVerboseEnabled: Boolean get() = logger.isTraceEnabled
|
||||
override val isDebugEnabled: Boolean get() = logger.isDebugEnabled
|
||||
override val isInfoEnabled: Boolean get() = logger.isInfoEnabled
|
||||
override val isWarningEnabled: Boolean get() = logger.isWarnEnabled
|
||||
override val isErrorEnabled: Boolean get() = logger.isErrorEnabled
|
||||
|
||||
override val identity: String?
|
||||
get() = logger.name
|
||||
}
|
||||
|
||||
internal class JdkLogger(private val logger: java.util.logging.Logger) : MiraiLoggerPlatformBase() {
|
||||
internal class JdkLoggerAdapter(private val logger: JulLogger) : MiraiLoggerPlatformBase() {
|
||||
override fun verbose0(message: String?, e: Throwable?) {
|
||||
logger.log(Level.FINER, message, e)
|
||||
logger.log(JulLevel.FINEST, message, e)
|
||||
}
|
||||
|
||||
override fun debug0(message: String?, e: Throwable?) {
|
||||
logger.log(Level.FINEST, message, e)
|
||||
logger.log(JulLevel.FINER, message, e)
|
||||
|
||||
}
|
||||
|
||||
override fun info0(message: String?, e: Throwable?) {
|
||||
logger.log(Level.INFO, message, e)
|
||||
logger.log(JulLevel.INFO, message, e)
|
||||
}
|
||||
|
||||
override fun warning0(message: String?, e: Throwable?) {
|
||||
logger.log(Level.WARNING, message, e)
|
||||
logger.log(JulLevel.WARNING, message, e)
|
||||
}
|
||||
|
||||
override fun error0(message: String?, e: Throwable?) {
|
||||
logger.log(Level.SEVERE, message, e)
|
||||
logger.log(JulLevel.SEVERE, message, e)
|
||||
}
|
||||
|
||||
override val isVerboseEnabled: Boolean get() = logger.isLoggable(JulLevel.FINE)
|
||||
override val isDebugEnabled: Boolean get() = logger.isLoggable(JulLevel.FINEST)
|
||||
override val isInfoEnabled: Boolean get() = logger.isLoggable(JulLevel.INFO)
|
||||
override val isWarningEnabled: Boolean get() = logger.isLoggable(JulLevel.WARNING)
|
||||
override val isErrorEnabled: Boolean get() = logger.isLoggable(JulLevel.SEVERE)
|
||||
|
||||
override val identity: String?
|
||||
get() = logger.name
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2019-2021 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.internal.utils
|
||||
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import org.apache.logging.log4j.Marker
|
||||
import org.apache.logging.log4j.MarkerManager
|
||||
|
||||
/**
|
||||
* 内部添加 [Marker] 支持, 并兼容旧 [MiraiLogger] API.
|
||||
*/
|
||||
internal interface MarkedMiraiLogger : MiraiLogger {
|
||||
val marker: Marker?
|
||||
|
||||
/**
|
||||
* Create an implementation-specific [MarkedMiraiLogger].
|
||||
*
|
||||
* Do not call the extension `MiraiLogger.subLogger` inside the function body.
|
||||
*/
|
||||
fun subLogger(name: String): MarkedMiraiLogger
|
||||
}
|
||||
|
||||
internal fun Marker(name: String, parents: Marker?): Marker {
|
||||
return MarkerManager.getMarker(name).apply { if (parents != null) addParents(parents) }
|
||||
}
|
||||
|
||||
internal fun Marker(name: String, vararg parents: Marker?): Marker {
|
||||
return MarkerManager.getMarker(name).apply {
|
||||
parents.forEach { if (it != null) addParents(it) }
|
||||
}
|
||||
}
|
||||
|
||||
internal val MiraiLogger.markerOrNull get() = (this as? MarkedMiraiLogger)?.marker
|
||||
|
||||
/**
|
||||
* Create a marked logger whose marker is a child of this' marker.
|
||||
*
|
||||
* Calling [MarkedMiraiLogger.subLogger] if possible, and creating [MiraiLoggerMarkedWrapper] otherwise.
|
||||
*/
|
||||
internal fun MiraiLogger.subLogger(name: String): MarkedMiraiLogger {
|
||||
return subLoggerImpl(this, name)
|
||||
}
|
||||
|
||||
// used by mirai-core
|
||||
internal fun subLoggerImpl(origin: MiraiLogger, name: String): MarkedMiraiLogger {
|
||||
return if (origin is MarkedMiraiLogger) {
|
||||
// origin can be Log4JAdapter or MiraiLoggerMarkedWrapper which delegates a non-Log4JAdapter.
|
||||
origin.subLogger(name) // Log4JAdapter natively supports Markers.
|
||||
} else {
|
||||
// origin does not support Markers, so we add a wrapper for it.
|
||||
MiraiLoggerMarkedWrapper(origin, Marker(name, origin.markerOrNull ?: MARKER_MIRAI))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 仅当日志系统使用的不是 Log4J 时才会构造 [MiraiLoggerMarkedWrapper].
|
||||
*/
|
||||
private class MiraiLoggerMarkedWrapper(
|
||||
val origin: MiraiLogger,
|
||||
override val marker: Marker
|
||||
) : MiraiLogger by origin, MarkedMiraiLogger {
|
||||
override fun subLogger(name: String): MarkedMiraiLogger = MiraiLoggerMarkedWrapper(origin, Marker(name, marker))
|
||||
}
|
@ -326,7 +326,9 @@ public open class BotConfiguration { // open for Java
|
||||
*
|
||||
* @see MiraiLogger
|
||||
*/
|
||||
public var botLoggerSupplier: ((Bot) -> MiraiLogger) = { MiraiLogger.create("Bot ${it.id}") }
|
||||
public var botLoggerSupplier: ((Bot) -> MiraiLogger) = {
|
||||
MiraiLogger.Factory.create(Bot::class, "Bot ${it.id}")
|
||||
}
|
||||
|
||||
/**
|
||||
* 网络层日志构造器
|
||||
@ -338,7 +340,9 @@ public open class BotConfiguration { // open for Java
|
||||
*
|
||||
* @see MiraiLogger
|
||||
*/
|
||||
public var networkLoggerSupplier: ((Bot) -> MiraiLogger) = { MiraiLogger.create("Net ${it.id}") }
|
||||
public var networkLoggerSupplier: ((Bot) -> MiraiLogger) = {
|
||||
MiraiLogger.Factory.create(Bot::class, "Net ${it.id}")
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
@ -60,6 +60,7 @@ public class DeviceInfo(
|
||||
)
|
||||
|
||||
public companion object {
|
||||
internal val logger = MiraiLogger.Factory.create(DeviceInfo::class, "DeviceInfo")
|
||||
|
||||
/**
|
||||
* 加载一个设备信息. 若文件不存在或为空则随机并创建一个设备信息保存.
|
||||
|
@ -7,25 +7,71 @@
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("unused")
|
||||
|
||||
package net.mamoe.mirai.utils
|
||||
|
||||
import net.mamoe.mirai.internal.utils.JdkLogger
|
||||
import net.mamoe.mirai.internal.utils.Log4jLogger
|
||||
import net.mamoe.mirai.internal.utils.Slf4jLogger
|
||||
import net.mamoe.mirai.internal.utils.JdkLoggerAdapter
|
||||
import net.mamoe.mirai.internal.utils.Log4jLoggerAdapter
|
||||
import net.mamoe.mirai.internal.utils.MARKER_MIRAI
|
||||
import net.mamoe.mirai.internal.utils.Slf4jLoggerAdapter
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import org.apache.logging.log4j.Marker
|
||||
import org.apache.logging.log4j.MarkerManager
|
||||
|
||||
/**
|
||||
* [SLF4J][org.slf4j.Logger], [LOG4J][org.apache.logging.log4j.Logger] 或 [JUL][java.util.logging.Logger] 到 [MiraiLogger] 的转换器.
|
||||
*/
|
||||
public object LoggerAdapters {
|
||||
/**
|
||||
* 使用 [LOG4J2][org.apache.logging.log4j.Logger] 接管全局 Mirai 日志系统. 请在调用 Mirai API 任何其他 API 前调用该方法.
|
||||
*
|
||||
* 注意, 若已经通过 service 方式提供 [MiraiLogger.Factory] 来接管日志系统, 则本方法无效.
|
||||
*
|
||||
* @since 2.7
|
||||
*/
|
||||
@JvmStatic
|
||||
@MiraiExperimentalApi
|
||||
public fun useLog4j2() {
|
||||
DefaultFactory.override { requester, identity ->
|
||||
val logger = LogManager.getLogger(requester)
|
||||
Log4jLoggerAdapter(logger, MarkerManager.getMarker(identity ?: logger.name).addParents(MARKER_MIRAI))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将 [java.util.logging.Logger] 转换作为 [MiraiLogger] 使用.
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun java.util.logging.Logger.asMiraiLogger(): MiraiLogger {
|
||||
return JdkLogger(this)
|
||||
return JdkLoggerAdapter(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 [org.apache.logging.log4j.Logger] 转换作为 [MiraiLogger] 使用.
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun org.apache.logging.log4j.Logger.asMiraiLogger(): MiraiLogger {
|
||||
return Log4jLogger(this)
|
||||
return Log4jLoggerAdapter(this, null)
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 [org.slf4j.Logger] 转换作为 [MiraiLogger] 使用.
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun org.slf4j.Logger.asMiraiLogger(): MiraiLogger {
|
||||
return Slf4jLogger(this)
|
||||
return Slf4jLoggerAdapter(this, null)
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 [org.apache.logging.log4j.Logger] 转换作为 [MiraiLogger] 使用.
|
||||
*
|
||||
* @since 2.7
|
||||
*/
|
||||
@MiraiExperimentalApi
|
||||
@JvmStatic
|
||||
public fun org.apache.logging.log4j.Logger.asMiraiLogger(marker: Marker): MiraiLogger {
|
||||
return Log4jLoggerAdapter(this, marker)
|
||||
}
|
||||
}
|
@ -13,7 +13,8 @@
|
||||
|
||||
package net.mamoe.mirai.utils
|
||||
|
||||
import net.mamoe.mirai.Bot
|
||||
import java.util.*
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
* 给这个 logger 添加一个开关, 用于控制是否记录 log
|
||||
@ -22,57 +23,106 @@ import net.mamoe.mirai.Bot
|
||||
public fun MiraiLogger.withSwitch(default: Boolean = true): MiraiLoggerWithSwitch = MiraiLoggerWithSwitch(this, default)
|
||||
|
||||
/**
|
||||
* 日志记录器. 所有的输出均依赖于它.
|
||||
* 不同的对象可拥有只属于自己的 logger. 通过 [identity] 来区分.
|
||||
* 日志记录器.
|
||||
*
|
||||
* 注意: 如果你需要重新实现日志, 请不要直接实现这个接口, 请继承 [MiraiLoggerPlatformBase]
|
||||
* ## Mirai 日志系统
|
||||
*
|
||||
* 在定义 logger 变量时, 请一直使用 [MiraiLogger] 或者 [MiraiLoggerWithSwitch].
|
||||
* Mirai 内建简单的日志系统, 即 [MiraiLogger]. [MiraiLogger] 的实现有 [SimpleLogger], [PlatformLogger], [SilentLogger].
|
||||
*
|
||||
* Mirai 内建三种日志实现, 分别是 [SimpleLogger], [PlatformLogger], [SilentLogger]
|
||||
* [MiraiLogger] 仅能处理简单的日志任务, 通常推荐使用 [SLF4J][org.slf4j.Logger], [LOG4J][org.apache.logging.log4j.Logger] 等日志库.
|
||||
*
|
||||
* ## 使用第三方日志库接管 Mirai 日志系统
|
||||
*
|
||||
* 使用 [LoggerAdapters], 将第三方日志 `Logger` 转为 [MiraiLogger]. 然后通过 [MiraiLogger.setDefaultLoggerCreator] 全局覆盖日志.
|
||||
*
|
||||
* ## 实现或使用 [MiraiLogger]
|
||||
*
|
||||
* 不建议实现或使用 [MiraiLogger]. 请优先考虑使用上述第三方框架. [MiraiLogger] 仅应用于兼容旧版本代码.
|
||||
*
|
||||
* @see SimpleLogger 简易 logger, 它将所有的日志记录操作都转移给 lambda `(String?, Throwable?) -> Unit`
|
||||
* @see PlatformLogger 各个平台下的默认日志记录实现.
|
||||
* @see SilentLogger 忽略任何日志记录操作的 logger 实例.
|
||||
* @see LoggerAdapters
|
||||
*
|
||||
* @see MiraiLoggerPlatformBase 平台通用基础实现. 若 Mirai 自带的日志系统无法满足需求, 请继承这个类并实现其抽象函数.
|
||||
*/
|
||||
public interface MiraiLogger {
|
||||
|
||||
/**
|
||||
* 可以 service 实现的方式覆盖.
|
||||
*
|
||||
* @since 2.7
|
||||
*/
|
||||
public interface Factory {
|
||||
/**
|
||||
* 创建 [MiraiLogger] 实例.
|
||||
*
|
||||
* @param requester 请求创建 [MiraiLogger] 的对象的 class
|
||||
* @param identity 对象标记 (备注)
|
||||
*/
|
||||
public fun create(requester: KClass<*>, identity: String? = null): MiraiLogger =
|
||||
this.create(requester.java, identity)
|
||||
|
||||
/**
|
||||
* 创建 [MiraiLogger] 实例.
|
||||
*
|
||||
* @param requester 请求创建 [MiraiLogger] 的对象的 class
|
||||
* @param identity 对象标记 (备注)
|
||||
*/
|
||||
public fun create(requester: Class<*>, identity: String? = null): MiraiLogger
|
||||
|
||||
/**
|
||||
* 创建 [MiraiLogger] 实例.
|
||||
*
|
||||
* @param requester 请求创建 [MiraiLogger] 的对象
|
||||
*/
|
||||
public fun create(requester: KClass<*>): MiraiLogger = create(requester, null)
|
||||
|
||||
/**
|
||||
* 创建 [MiraiLogger] 实例.
|
||||
*
|
||||
* @param requester 请求创建 [MiraiLogger] 的对象
|
||||
*/
|
||||
public fun create(requester: Class<*>): MiraiLogger = create(requester, null)
|
||||
|
||||
public companion object INSTANCE : Factory by loadService({ DefaultFactory() })
|
||||
}
|
||||
|
||||
public companion object {
|
||||
/**
|
||||
* 顶层日志, 仅供 Mirai 内部使用.
|
||||
*/
|
||||
@MiraiInternalApi
|
||||
@MiraiExperimentalApi
|
||||
public val TopLevel: MiraiLogger by lazy { create("Mirai") }
|
||||
|
||||
@Volatile
|
||||
private var defaultLogger: (identity: String?) -> MiraiLogger = { PlatformLogger(it) }
|
||||
@Deprecated("Deprecated.")
|
||||
public val TopLevel: MiraiLogger by lazy { Factory.create(MiraiLogger::class, "Mirai") }
|
||||
|
||||
/**
|
||||
* 可直接修改这个变量的值来重定向日志输出.
|
||||
* 已弃用, 请实现 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.WARNING
|
||||
)
|
||||
@JvmStatic
|
||||
public fun setDefaultLoggerCreator(creator: (identity: String?) -> MiraiLogger) {
|
||||
defaultLogger = creator
|
||||
DefaultFactory.override { _, identity -> creator(identity) }
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于创建默认的日志记录器. 在一些需要使用日志的 Mirai 的组件, 如 [Bot], 都会通过这个函数构造日志记录器.
|
||||
*
|
||||
* **注意:** 请务必将所有的输出定向到日志记录系统, 否则在某些情况下 (如 web 控制台中) 将无法接收到输出
|
||||
*
|
||||
* **注意:** 请为日志做好分类, 即不同的模块使用不同的 [MiraiLogger].
|
||||
* 如, [Bot] 中使用 `identity` 为 "Bot(qqId)" 的 [MiraiLogger]
|
||||
* 而 [Bot] 的网络处理中使用 `identity` 为 "BotNetworkHandler".
|
||||
* 旧版本用于创建 [MiraiLogger]. 已弃用. 请使用 [MiraiLogger.Factory.INSTANCE.create].
|
||||
*
|
||||
* @see setDefaultLoggerCreator
|
||||
*/
|
||||
@Deprecated(
|
||||
"Please use MiraiLogger.Factory.create", ReplaceWith(
|
||||
"MiraiLogger.Factory.create(YourClass::class, identity)",
|
||||
"net.mamoe.mirai.utils.MiraiLogger"
|
||||
), level = DeprecationLevel.WARNING
|
||||
)
|
||||
@JvmStatic
|
||||
public fun create(identity: String?): MiraiLogger {
|
||||
return defaultLogger.invoke(identity)
|
||||
}
|
||||
public fun create(identity: String?): MiraiLogger = Factory.create(MiraiLogger::class, identity)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -92,6 +142,61 @@ public interface MiraiLogger {
|
||||
*/
|
||||
public val isEnabled: Boolean
|
||||
|
||||
/**
|
||||
* 当 VERBOSE 级别的日志启用时返回 `true`.
|
||||
*
|
||||
* 若 [isEnabled] 为 `false`, 返回 `false`.
|
||||
* 在使用 [SLF4J][org.slf4j.Logger], [LOG4J][org.apache.logging.log4j.Logger] 或 [JUL][java.util.logging.Logger] 时返回真实配置值.
|
||||
* 其他情况下返回 [isEnabled] 的值.
|
||||
*
|
||||
* @since 2.7
|
||||
*/
|
||||
public val isVerboseEnabled: Boolean get() = isEnabled
|
||||
|
||||
/**
|
||||
* 当 DEBUG 级别的日志启用时返回 `true`
|
||||
*
|
||||
* 若 [isEnabled] 为 `false`, 返回 `false`.
|
||||
* 在使用 [SLF4J][org.slf4j.Logger], [LOG4J][org.apache.logging.log4j.Logger] 或 [JUL][java.util.logging.Logger] 时返回真实配置值.
|
||||
* 其他情况下返回 [isEnabled] 的值.
|
||||
*
|
||||
* @since 2.7
|
||||
*/
|
||||
public val isDebugEnabled: Boolean get() = isEnabled
|
||||
|
||||
/**
|
||||
* 当 INFO 级别的日志启用时返回 `true`
|
||||
*
|
||||
* 若 [isEnabled] 为 `false`, 返回 `false`.
|
||||
* 在使用 [SLF4J][org.slf4j.Logger], [LOG4J][org.apache.logging.log4j.Logger] 或 [JUL][java.util.logging.Logger] 时返回真实配置值.
|
||||
* 其他情况下返回 [isEnabled] 的值.
|
||||
*
|
||||
* @since 2.7
|
||||
*/
|
||||
public val isInfoEnabled: Boolean get() = isEnabled
|
||||
|
||||
/**
|
||||
* 当 WARNING 级别的日志启用时返回 `true`
|
||||
*
|
||||
* 若 [isEnabled] 为 `false`, 返回 `false`.
|
||||
* 在使用 [SLF4J][org.slf4j.Logger], [LOG4J][org.apache.logging.log4j.Logger] 或 [JUL][java.util.logging.Logger] 时返回真实配置值.
|
||||
* 其他情况下返回 [isEnabled] 的值.
|
||||
*
|
||||
* @since 2.7
|
||||
*/
|
||||
public val isWarningEnabled: Boolean get() = isEnabled
|
||||
|
||||
/**
|
||||
* 当 ERROR 级别的日志启用时返回 `true`
|
||||
*
|
||||
* 若 [isEnabled] 为 `false`, 返回 `false`.
|
||||
* 在使用 [SLF4J][org.slf4j.Logger], [LOG4J][org.apache.logging.log4j.Logger] 或 [JUL][java.util.logging.Logger] 时返回真实配置值.
|
||||
* 其他情况下返回 [isEnabled] 的值.
|
||||
*
|
||||
* @since 2.7
|
||||
*/
|
||||
public val isErrorEnabled: Boolean get() = isEnabled
|
||||
|
||||
/**
|
||||
* 随从. 在 this 中调用所有方法后都应继续往 [follower] 传递调用.
|
||||
* [follower] 的存在可以让一次日志被多个日志记录器记录.
|
||||
@ -102,7 +207,11 @@ public interface MiraiLogger {
|
||||
*
|
||||
* 当然, 多个 logger 也可以加在一起: `val logger = bot.logger + MynLogger() + MyLogger2()`
|
||||
*/
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
@Deprecated("follower 设计不佳, 请避免使用", level = DeprecationLevel.WARNING) // deprecated since 2.7
|
||||
public var follower: MiraiLogger?
|
||||
get() = null
|
||||
set(value) {}
|
||||
|
||||
/**
|
||||
* 记录一个 `verbose` 级别的日志.
|
||||
@ -164,48 +273,50 @@ public interface MiraiLogger {
|
||||
*
|
||||
* @return [follower]
|
||||
*/
|
||||
public operator fun <T : MiraiLogger> plus(follower: T): T
|
||||
@Suppress("DeprecatedCallableAddReplaceWith")
|
||||
@Deprecated("plus 设计不佳, 请避免使用.", level = DeprecationLevel.WARNING) // deprecated since 2.7
|
||||
public operator fun <T : MiraiLogger> plus(follower: T): T = follower
|
||||
}
|
||||
|
||||
|
||||
public inline fun MiraiLogger.verbose(message: () -> String) {
|
||||
if (isEnabled) verbose(message())
|
||||
if (isVerboseEnabled) verbose(message())
|
||||
}
|
||||
|
||||
public inline fun MiraiLogger.verbose(message: () -> String, e: Throwable?) {
|
||||
if (isEnabled) verbose(message(), e)
|
||||
if (isVerboseEnabled) verbose(message(), e)
|
||||
}
|
||||
|
||||
public inline fun MiraiLogger.debug(message: () -> String?) {
|
||||
if (isEnabled) debug(message())
|
||||
if (isDebugEnabled) debug(message())
|
||||
}
|
||||
|
||||
public inline fun MiraiLogger.debug(message: () -> String?, e: Throwable?) {
|
||||
if (isEnabled) debug(message(), e)
|
||||
if (isDebugEnabled) debug(message(), e)
|
||||
}
|
||||
|
||||
public inline fun MiraiLogger.info(message: () -> String?) {
|
||||
if (isEnabled) info(message())
|
||||
if (isInfoEnabled) info(message())
|
||||
}
|
||||
|
||||
public inline fun MiraiLogger.info(message: () -> String?, e: Throwable?) {
|
||||
if (isEnabled) info(message(), e)
|
||||
if (isInfoEnabled) info(message(), e)
|
||||
}
|
||||
|
||||
public inline fun MiraiLogger.warning(message: () -> String?) {
|
||||
if (isEnabled) warning(message())
|
||||
if (isWarningEnabled) warning(message())
|
||||
}
|
||||
|
||||
public inline fun MiraiLogger.warning(message: () -> String?, e: Throwable?) {
|
||||
if (isEnabled) warning(message(), e)
|
||||
if (isWarningEnabled) warning(message(), e)
|
||||
}
|
||||
|
||||
public inline fun MiraiLogger.error(message: () -> String?) {
|
||||
if (isEnabled) error(message())
|
||||
if (isErrorEnabled) error(message())
|
||||
}
|
||||
|
||||
public inline fun MiraiLogger.error(message: () -> String?, e: Throwable?) {
|
||||
if (isEnabled) error(message(), e)
|
||||
if (isErrorEnabled) error(message(), e)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -353,8 +464,12 @@ public class MiraiLoggerWithSwitch internal constructor(private val delegate: Mi
|
||||
* @see PlatformLogger
|
||||
* @see SimpleLogger
|
||||
*/
|
||||
@Suppress("DEPRECATION")
|
||||
public abstract class MiraiLoggerPlatformBase : MiraiLogger {
|
||||
public override val isEnabled: Boolean get() = true
|
||||
|
||||
@Suppress("OverridingDeprecatedMember")
|
||||
@Deprecated("follower 设计不佳, 请避免使用", level = DeprecationLevel.WARNING) // deprecated since 2.7
|
||||
public final override var follower: MiraiLogger? = null
|
||||
|
||||
public final override fun verbose(message: String?) {
|
||||
@ -428,8 +543,36 @@ public abstract class MiraiLoggerPlatformBase : MiraiLogger {
|
||||
protected open fun error0(message: String?): Unit = error0(message, null)
|
||||
protected abstract fun error0(message: String?, e: Throwable?)
|
||||
|
||||
@Suppress("OverridingDeprecatedMember")
|
||||
@Deprecated("plus 设计不佳, 请避免使用.", level = DeprecationLevel.WARNING) // deprecated since 2.7
|
||||
public override operator fun <T : MiraiLogger> plus(follower: T): T {
|
||||
this.follower = follower
|
||||
return follower
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal class DefaultFactory : MiraiLogger.Factory {
|
||||
init {
|
||||
INSTANCE = this
|
||||
}
|
||||
|
||||
companion object {
|
||||
lateinit var INSTANCE: DefaultFactory
|
||||
private set
|
||||
|
||||
fun override(lambda: (requester: Class<*>, identity: String?) -> MiraiLogger) {
|
||||
INSTANCE.override = lambda
|
||||
}
|
||||
}
|
||||
|
||||
private var override: ((requester: Class<*>, identity: String?) -> MiraiLogger)? =
|
||||
null // 支持 LoggerAdapters 以及兼容旧版本
|
||||
|
||||
override fun create(requester: Class<*>, identity: String?): MiraiLogger {
|
||||
val override = override
|
||||
return if (override != null) override(requester, identity) else PlatformLogger(
|
||||
identity ?: requester.kotlin.simpleName ?: requester.simpleName
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2019-2021 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.Bot
|
||||
import net.mamoe.mirai.internal.utils.Log4jLoggerAdapter
|
||||
import net.mamoe.mirai.internal.utils.MARKER_MIRAI
|
||||
import net.mamoe.mirai.internal.utils.Marker
|
||||
import net.mamoe.mirai.internal.utils.subLogger
|
||||
import net.mamoe.mirai.utils.DefaultFactory
|
||||
import net.mamoe.mirai.utils.LoggerAdapters.asMiraiLogger
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertIs
|
||||
import kotlin.test.assertSame
|
||||
|
||||
internal class Log4j2LoggingTest {
|
||||
@BeforeEach
|
||||
fun init() {
|
||||
DefaultFactory.override { requester, identity ->
|
||||
LogManager.getLogger(requester).asMiraiLogger(Marker(identity ?: requester.simpleName, MARKER_MIRAI))
|
||||
}
|
||||
}
|
||||
|
||||
private fun MiraiLogger.cast(): Log4jLoggerAdapter = this as Log4jLoggerAdapter
|
||||
|
||||
@Test
|
||||
fun `created is Log4jLoggerAdapter`() {
|
||||
val logger = MiraiLogger.Factory.create(Log4j2LoggingTest::class, "test1")
|
||||
assertIs<Log4jLoggerAdapter>(logger)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `identity is considered as marker`() {
|
||||
val logger = MiraiLogger.Factory.create(Log4j2LoggingTest::class, "test1")
|
||||
assertEquals("test1", logger.cast().marker!!.name)
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun `test subLogger Marker`() {
|
||||
val parent = MiraiLogger.Factory.create(Log4j2LoggingTest::class, "test1")
|
||||
val parentMarker = parent.cast().marker!!
|
||||
|
||||
val child = parent.subLogger("sub")
|
||||
val childMarker = child.marker!!
|
||||
|
||||
assertEquals("test1", parentMarker.name)
|
||||
assertEquals("sub", childMarker.name)
|
||||
|
||||
assertSame(parentMarker, childMarker.parents.single())
|
||||
assertSame("test1", childMarker.parents.single().name)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test subLogger Marker 2`() {
|
||||
val parent = MiraiLogger.Factory.create(Log4j2LoggingTest::class, "test1")
|
||||
val parentMarker = parent.cast().marker!!
|
||||
|
||||
val child = parent.subLogger("sub").subLogger("sub2")
|
||||
val childMarker = child.marker!!
|
||||
|
||||
assertEquals("test1", parentMarker.name)
|
||||
assertEquals("sub2", childMarker.name)
|
||||
|
||||
assertSame("sub", childMarker.parents.single().name)
|
||||
assertSame(parentMarker, childMarker.parents.single().parents.single())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `logging output test`() {
|
||||
val logger = LogManager.getLogger(Bot::class.java)
|
||||
logger.info("Test")
|
||||
MiraiLogger.Factory.create(Bot::class).run {
|
||||
info("InfoFF")
|
||||
}
|
||||
}
|
||||
}
|
13
mirai-core-api/src/commonTest/resources/log4j.properties
Normal file
13
mirai-core-api/src/commonTest/resources/log4j.properties
Normal file
@ -0,0 +1,13 @@
|
||||
#
|
||||
# Copyright 2019-2021 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
|
||||
#
|
||||
log4j.rootLogger=INFO,stdout
|
||||
log4j.logger.mirai=INFO
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=%p\t%d{ISO8601}\t%r\t%c\t%m%n
|
@ -47,12 +47,17 @@ public actual inline fun <reified E> Throwable.unwrap(): Throwable {
|
||||
public actual fun <T : Any> loadService(clazz: KClass<out T>, fallbackImplementation: String?): T {
|
||||
var suppressed: Throwable? = null
|
||||
return ServiceLoader.load(clazz.java).firstOrNull()
|
||||
?: runCatching {
|
||||
Class.forName(fallbackImplementation).cast<Class<out T>>().kotlin.run { objectInstance ?: createInstance() }
|
||||
}.onFailure {
|
||||
suppressed = it
|
||||
}.getOrNull()
|
||||
?: runCatching { findCreateInstance<T>(fallbackImplementation) }.onFailure { suppressed = it }.getOrNull()
|
||||
?: throw NoSuchElementException("Could not find an implementation for service class ${clazz.qualifiedName}").apply {
|
||||
if (suppressed != null) addSuppressed(suppressed)
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T : Any> findCreateInstance(fallbackImplementation: String?): T {
|
||||
return Class.forName(fallbackImplementation).cast<Class<out T>>().kotlin.run { objectInstance ?: createInstance() }
|
||||
}
|
||||
|
||||
public actual fun <T : Any> loadServiceOrNull(clazz: KClass<out T>, fallbackImplementation: String?): T? {
|
||||
return ServiceLoader.load(clazz.java).firstOrNull()
|
||||
?: runCatching { findCreateInstance<T>(fallbackImplementation) }.getOrNull()
|
||||
}
|
@ -11,6 +11,11 @@ package net.mamoe.mirai.utils
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
public expect fun <T : Any> loadServiceOrNull(clazz: KClass<out T>, fallbackImplementation: String? = null): T?
|
||||
public expect fun <T : Any> loadService(clazz: KClass<out T>, fallbackImplementation: String? = null): T
|
||||
|
||||
public inline fun <reified T : Any> loadService(fallbackImplementation: String? = null): T =
|
||||
loadService(T::class, fallbackImplementation)
|
||||
loadService(T::class, fallbackImplementation)
|
||||
|
||||
public inline fun <reified T : Any> loadService(noinline fallbackImplementation: () -> T): T =
|
||||
loadServiceOrNull(T::class) ?: fallbackImplementation()
|
@ -35,12 +35,17 @@ public actual inline fun <reified E> Throwable.unwrap(): Throwable {
|
||||
public actual fun <T : Any> loadService(clazz: KClass<out T>, fallbackImplementation: String?): T {
|
||||
var suppressed: Throwable? = null
|
||||
return ServiceLoader.load(clazz.java).firstOrNull()
|
||||
?: runCatching {
|
||||
Class.forName(fallbackImplementation).cast<Class<out T>>().kotlin.run { objectInstance ?: createInstance() }
|
||||
}.onFailure {
|
||||
suppressed = it
|
||||
}.getOrNull()
|
||||
?: runCatching { findCreateInstance<T>(fallbackImplementation) }.onFailure { suppressed = it }.getOrNull()
|
||||
?: throw NoSuchElementException("Could not find an implementation for service class ${clazz.qualifiedName}").apply {
|
||||
if (suppressed != null) addSuppressed(suppressed)
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T : Any> findCreateInstance(fallbackImplementation: String?): T {
|
||||
return Class.forName(fallbackImplementation).cast<Class<out T>>().kotlin.run { objectInstance ?: createInstance() }
|
||||
}
|
||||
|
||||
public actual fun <T : Any> loadServiceOrNull(clazz: KClass<out T>, fallbackImplementation: String?): T? {
|
||||
return ServiceLoader.load(clazz.java).firstOrNull()
|
||||
?: runCatching { findCreateInstance<T>(fallbackImplementation) }.getOrNull()
|
||||
}
|
@ -72,13 +72,13 @@ kotlin {
|
||||
api1(`kotlinx-io-jvm`)
|
||||
implementation1(`kotlinx-coroutines-io`)
|
||||
implementation(`netty-all`)
|
||||
implementation(`log4j-api`)
|
||||
}
|
||||
}
|
||||
|
||||
commonTest {
|
||||
dependencies {
|
||||
implementation(kotlin("script-runtime"))
|
||||
runtimeOnly(`slf4j-simple`)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ internal actual class PlatformInitializationTest : AbstractTest() {
|
||||
actual fun test() {
|
||||
assertTrue {
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
MiraiLogger.create("1") is net.mamoe.mirai.internal.utils.StdoutLogger
|
||||
MiraiLogger.Factory.create(this::class, "1") is net.mamoe.mirai.internal.utils.StdoutLogger
|
||||
}
|
||||
}
|
||||
}
|
@ -57,6 +57,9 @@ internal class OnlineGroupImageImpl(
|
||||
|
||||
}
|
||||
|
||||
private val imageLogger: MiraiLogger by lazy { MiraiLogger.Factory.create(Image::class) }
|
||||
internal val Image.Key.logger get() = imageLogger
|
||||
|
||||
@Serializable(with = OnlineFriendImageImpl.Serializer::class)
|
||||
internal class OnlineFriendImageImpl(
|
||||
internal val delegate: ImMsgBody.NotOnlineImage,
|
||||
@ -70,7 +73,7 @@ OnlineFriendImage() {
|
||||
?: kotlin.run {
|
||||
if (delegate.picMd5.size == 16) generateImageId(delegate.picMd5, imageType)
|
||||
else {
|
||||
MiraiLogger.TopLevel.warning(
|
||||
Image.logger.warning(
|
||||
contextualBugReportException(
|
||||
"Failed to compute friend imageId: resId=${delegate.resId}",
|
||||
delegate._miraiContentToString(),
|
||||
@ -115,7 +118,7 @@ internal fun getImageType(id: Int): String {
|
||||
2001, 3 -> "png"
|
||||
else -> {
|
||||
if (UNKNOWN_IMAGE_TYPE_PROMPT_ENABLED) {
|
||||
MiraiLogger.TopLevel.debug(
|
||||
Image.logger.debug(
|
||||
"Unknown image id: $id. Stacktrace:",
|
||||
Exception()
|
||||
)
|
||||
|
@ -45,7 +45,7 @@ internal interface PacketCodec {
|
||||
val PACKET_DEBUG = systemProp("mirai.network.packet.logger", false)
|
||||
|
||||
internal val PacketLogger: MiraiLoggerWithSwitch by lazy {
|
||||
MiraiLogger.create("Packet").withSwitch(PACKET_DEBUG)
|
||||
MiraiLogger.Factory.create(PacketCodec::class, "Packet").withSwitch(PACKET_DEBUG)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -105,10 +105,10 @@ internal class ServerListImpl(
|
||||
initial: Collection<ServerAddress> = emptyList()
|
||||
) : ServerList {
|
||||
@TestOnly
|
||||
constructor(initial: Collection<ServerAddress>) : this(MiraiLogger.TopLevel, initial)
|
||||
constructor(initial: Collection<ServerAddress>) : this(MiraiLogger.Factory.create(ServerListImpl::class), initial)
|
||||
|
||||
@TestOnly
|
||||
constructor() : this(MiraiLogger.TopLevel)
|
||||
constructor() : this(MiraiLogger.Factory.create(ServerListImpl::class))
|
||||
|
||||
@Volatile
|
||||
private var preferred: Set<ServerAddress> = DEFAULT_SERVER_LIST
|
||||
|
@ -23,6 +23,7 @@ import net.mamoe.mirai.internal.network.protocol.packet.IncomingPacket
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket
|
||||
import net.mamoe.mirai.internal.utils.SingleEntrantLock
|
||||
import net.mamoe.mirai.internal.utils.fromMiraiLogger
|
||||
import net.mamoe.mirai.internal.utils.subLogger
|
||||
import net.mamoe.mirai.utils.*
|
||||
import net.mamoe.mirai.utils.Either.Companion.fold
|
||||
import java.util.concurrent.ConcurrentLinkedQueue
|
||||
@ -56,7 +57,7 @@ internal abstract class NetworkHandlerSupport(
|
||||
}
|
||||
|
||||
protected val packetLogger: MiraiLogger by lazy {
|
||||
MiraiLogger.create(context.logger.identity + ".debug").withSwitch(PacketCodec.PACKET_DEBUG)
|
||||
context.logger.subLogger("NetworkDebug").withSwitch(PacketCodec.PACKET_DEBUG)
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
@ -84,14 +84,14 @@ internal class LoggingStateObserver(
|
||||
return when (ENABLED) {
|
||||
"full" -> {
|
||||
SafeStateObserver(
|
||||
LoggingStateObserver(MiraiLogger.create("States"), true),
|
||||
MiraiLogger.create("LoggingStateObserver errors")
|
||||
LoggingStateObserver(MiraiLogger.Factory.create(LoggingStateObserver::class, "States"), true),
|
||||
MiraiLogger.Factory.create(LoggingStateObserver::class, "LoggingStateObserver errors")
|
||||
)
|
||||
}
|
||||
"on", "true" -> {
|
||||
SafeStateObserver(
|
||||
LoggingStateObserver(MiraiLogger.create("States"), false),
|
||||
MiraiLogger.create("LoggingStateObserver errors")
|
||||
LoggingStateObserver(MiraiLogger.Factory.create(LoggingStateObserver::class, "States"), false),
|
||||
MiraiLogger.Factory.create(LoggingStateObserver::class, "LoggingStateObserver errors")
|
||||
)
|
||||
}
|
||||
else -> null
|
||||
|
@ -11,7 +11,8 @@ package net.mamoe.mirai.internal.utils
|
||||
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
import net.mamoe.mirai.utils.*
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import net.mamoe.mirai.utils.coroutineName
|
||||
|
||||
|
||||
internal fun CoroutineExceptionHandler.Key.fromMiraiLogger(
|
||||
@ -25,54 +26,5 @@ internal fun CoroutineExceptionHandler.Key.fromMiraiLogger(
|
||||
}
|
||||
}
|
||||
|
||||
internal fun MiraiLogger.subLogger(name: String): MiraiLogger {
|
||||
return SubLogger(name, this)
|
||||
}
|
||||
|
||||
private class SubLogger(
|
||||
private val name: String,
|
||||
private val main: MiraiLogger,
|
||||
) : MiraiLoggerPlatformBase() {
|
||||
override val identity: String? get() = main.identity
|
||||
override val isEnabled: Boolean get() = main.isEnabled
|
||||
|
||||
override fun verbose0(message: String?, e: Throwable?) {
|
||||
if (message != null) {
|
||||
main.verbose({ "[$name] $message" }, e)
|
||||
} else {
|
||||
main.verbose(null, e)
|
||||
}
|
||||
}
|
||||
|
||||
override fun debug0(message: String?, e: Throwable?) {
|
||||
if (message != null) {
|
||||
main.debug({ "[$name] $message" }, e)
|
||||
} else {
|
||||
main.debug(null, e)
|
||||
}
|
||||
}
|
||||
|
||||
override fun info0(message: String?, e: Throwable?) {
|
||||
if (message != null) {
|
||||
main.info({ "[$name] $message" }, e)
|
||||
} else {
|
||||
main.info(null, e)
|
||||
}
|
||||
}
|
||||
|
||||
override fun warning0(message: String?, e: Throwable?) {
|
||||
if (message != null) {
|
||||
main.warning({ "[$name] $message" }, e)
|
||||
} else {
|
||||
main.warning(null, e)
|
||||
}
|
||||
}
|
||||
|
||||
override fun error0(message: String?, e: Throwable?) {
|
||||
if (message != null) {
|
||||
main.error({ "[$name] $message" }, e)
|
||||
} else {
|
||||
main.error(null, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
internal fun MiraiLogger.subLogger(name: String): MiraiLogger = subLoggerImpl(this, name)
|
@ -12,6 +12,7 @@
|
||||
package net.mamoe.mirai.internal.utils
|
||||
|
||||
import kotlinx.serialization.Transient
|
||||
import net.mamoe.mirai.IMirai
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import net.mamoe.mirai.utils.debug
|
||||
import net.mamoe.mirai.utils.toUHexString
|
||||
@ -32,7 +33,7 @@ private fun <T> Sequence<T>.joinToStringPrefixed(prefix: String, transform: (T)
|
||||
return this.joinToString(prefix = "$prefix$indent", separator = "\n$prefix$indent", transform = transform)
|
||||
}
|
||||
|
||||
private val SoutvLogger: MiraiLogger by lazy { MiraiLogger.create("soutv") }
|
||||
private val SoutvLogger: MiraiLogger by lazy { MiraiLogger.Factory.create(IMirai::class, "soutv") }
|
||||
internal fun Any?.soutv(name: String = "unnamed") {
|
||||
@Suppress("DEPRECATION")
|
||||
SoutvLogger.debug { "$name = ${this._miraiContentToString()}" }
|
||||
|
@ -26,7 +26,10 @@ import org.junit.jupiter.api.Test
|
||||
internal class EventDispatcherTest : AbstractTest() {
|
||||
private class Ev : AbstractEvent()
|
||||
|
||||
private val dispatcher = TestEventDispatcherImpl(SupervisorJob(), MiraiLogger.create("EventDispatcherTest"))
|
||||
private val dispatcher = TestEventDispatcherImpl(
|
||||
SupervisorJob(),
|
||||
MiraiLogger.Factory.create(EventDispatcherTest::class)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `can broadcast`() = runBlockingUnit {
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
package net.mamoe.mirai.internal.network.framework
|
||||
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.internal.MockBot
|
||||
import net.mamoe.mirai.internal.QQAndroidBot
|
||||
import net.mamoe.mirai.internal.network.component.ConcurrentComponentStorage
|
||||
@ -39,7 +40,7 @@ internal abstract class AbstractMockNetworkHandlerTest : AbstractNetworkHandlerT
|
||||
nhProvider = { createNetworkHandler() }
|
||||
additionalComponentsProvider = { this@AbstractMockNetworkHandlerTest.components }
|
||||
}
|
||||
protected val logger = MiraiLogger.create("test")
|
||||
protected val logger = MiraiLogger.Factory.create(Bot::class, "test")
|
||||
protected val components = ConcurrentComponentStorage().apply {
|
||||
set(SsoProcessor, TestSsoProcessor(bot))
|
||||
set(
|
||||
@ -49,8 +50,8 @@ internal abstract class AbstractMockNetworkHandlerTest : AbstractNetworkHandlerT
|
||||
set(
|
||||
StateObserver,
|
||||
SafeStateObserver(
|
||||
LoggingStateObserver(MiraiLogger.create("States")),
|
||||
MiraiLogger.create("StateObserver errors")
|
||||
LoggingStateObserver(MiraiLogger.Factory.create(LoggingStateObserver::class, "States")),
|
||||
MiraiLogger.Factory.create(SafeStateObserver::class, "StateObserver errors")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ internal sealed class AbstractRealNetworkHandlerTest<H : NetworkHandler> : Abstr
|
||||
}
|
||||
}
|
||||
|
||||
open val networkLogger = MiraiLogger.create("network")
|
||||
open val networkLogger = MiraiLogger.Factory.create(NetworkHandler::class, "network")
|
||||
|
||||
sealed class NHEvent {
|
||||
object Login : NHEvent()
|
||||
|
@ -24,14 +24,14 @@ import net.mamoe.mirai.utils.MiraiLogger
|
||||
|
||||
internal class TestNetworkHandlerContext(
|
||||
override val bot: QQAndroidBot = MockBot(),
|
||||
override val logger: MiraiLogger = MiraiLogger.create("Test"),
|
||||
override val logger: MiraiLogger = MiraiLogger.Factory.create(TestNetworkHandlerContext::class, "Test"),
|
||||
components: ComponentStorage = ConcurrentComponentStorage().apply {
|
||||
set(SsoProcessor, SsoProcessorImpl(SsoProcessorContextImpl(bot)))
|
||||
set(
|
||||
StateObserver,
|
||||
SafeStateObserver(
|
||||
LoggingStateObserver(MiraiLogger.create("States")),
|
||||
MiraiLogger.create("StateObserver errors")
|
||||
LoggingStateObserver(MiraiLogger.Factory.create(LoggingStateObserver::class, "States")),
|
||||
MiraiLogger.Factory.create(LoggingStateObserver::class, "StateObserver errors")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ import java.util.concurrent.atomic.AtomicInteger
|
||||
import kotlin.test.*
|
||||
import kotlin.time.Duration
|
||||
|
||||
internal val selectorLogger = MiraiLogger.create("selector")
|
||||
internal val selectorLogger = MiraiLogger.Factory.create(TestSelector::class, "selector")
|
||||
|
||||
internal class TestSelector<H : NetworkHandler> :
|
||||
AbstractKeepAliveNetworkHandlerSelector<H> {
|
||||
|
@ -12,6 +12,7 @@ package net.mamoe.mirai.internal.test
|
||||
import net.mamoe.mirai.IMirai
|
||||
import net.mamoe.mirai.internal.network.framework.SynchronizedStdoutLogger
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.Timeout
|
||||
import java.util.concurrent.TimeUnit
|
||||
@ -26,9 +27,7 @@ abstract class AbstractTest {
|
||||
init {
|
||||
initPlatform()
|
||||
|
||||
MiraiLogger.setDefaultLoggerCreator {
|
||||
SynchronizedStdoutLogger(it)
|
||||
}
|
||||
restoreLoggerFactory()
|
||||
|
||||
System.setProperty("mirai.network.packet.logger", "true")
|
||||
System.setProperty("mirai.network.state.observer.logging", "true")
|
||||
@ -38,6 +37,14 @@ abstract class AbstractTest {
|
||||
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
protected fun restoreLoggerFactory() {
|
||||
@Suppress("DEPRECATION")
|
||||
MiraiLogger.setDefaultLoggerCreator {
|
||||
SynchronizedStdoutLogger(it)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
init {
|
||||
Exception() // create a exception to load relevant classes to estimate invocation time of test cases more accurately.
|
||||
|
@ -1,10 +1,10 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
* Copyright 2019-2021 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("NOTHING_TO_INLINE")
|
||||
@ -14,12 +14,13 @@ package test
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.Input
|
||||
import kotlinx.io.core.readAvailable
|
||||
import net.mamoe.mirai.IMirai
|
||||
import net.mamoe.mirai.utils.*
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
|
||||
val DebugLogger: MiraiLogger = MiraiLogger.create("Packet Debug")
|
||||
val DebugLogger: MiraiLogger = MiraiLogger.Factory.create(IMirai::class, "Packet Debug")
|
||||
|
||||
internal inline fun ByteArray.debugPrintThis(name: String): ByteArray {
|
||||
DebugLogger.debug(name + "=" + this.toUHexString())
|
||||
|
Loading…
Reference in New Issue
Block a user