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:
Him188 2021-08-06 02:31:17 +08:00
parent 2562099884
commit 5950e9e1e8
33 changed files with 620 additions and 169 deletions

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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") }
}
/**

View File

@ -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(

View File

@ -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
}
}

View File

@ -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))
}

View File

@ -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}")
}
/**

View File

@ -60,6 +60,7 @@ public class DeviceInfo(
)
public companion object {
internal val logger = MiraiLogger.Factory.create(DeviceInfo::class, "DeviceInfo")
/**
* 加载一个设备信息. 若文件不存在或为空则随机并创建一个设备信息保存.

View File

@ -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)
}
}

View File

@ -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
)
}
}

View File

@ -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")
}
}
}

View 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

View File

@ -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()
}

View File

@ -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()

View File

@ -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()
}

View File

@ -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`)
}
}

View File

@ -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
}
}
}

View File

@ -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()
)

View File

@ -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)
}
}
}

View File

@ -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

View File

@ -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)
}
///////////////////////////////////////////////////////////////////////////

View File

@ -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

View File

@ -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)

View File

@ -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()}" }

View File

@ -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 {

View File

@ -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")
)
)
}

View File

@ -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()

View File

@ -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")
)
)
}

View File

@ -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> {

View File

@ -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.

View File

@ -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())