diff --git a/mirai-core-api/src/commonMain/kotlin/event/internal/InternalEventListeners.kt b/mirai-core-api/src/commonMain/kotlin/event/internal/InternalEventListeners.kt
index eb70193e7..259531dbd 100644
--- a/mirai-core-api/src/commonMain/kotlin/event/internal/InternalEventListeners.kt
+++ b/mirai-core-api/src/commonMain/kotlin/event/internal/InternalEventListeners.kt
@@ -76,7 +76,7 @@ internal class Handler<in E : Event> internal constructor(
                 ?: coroutineContext[CoroutineExceptionHandler]?.handleException(subscriberContext, e)
                 ?: kotlin.run {
                     @Suppress("DEPRECATION")
-                    (if (event is BotEvent) event.bot.logger else MiraiLogger)
+                    (if (event is BotEvent) event.bot.logger else MiraiLogger.TopLevel)
                         .warning(
                             """Event processing: An exception occurred but no CoroutineExceptionHandler found, 
                         either in coroutineContext from Handler job, or in subscriberContext""".trimIndent(), e
diff --git a/mirai-core-api/src/commonMain/kotlin/utils/BotConfiguration.kt b/mirai-core-api/src/commonMain/kotlin/utils/BotConfiguration.kt
index 50cc4b379..e9f210bb6 100644
--- a/mirai-core-api/src/commonMain/kotlin/utils/BotConfiguration.kt
+++ b/mirai-core-api/src/commonMain/kotlin/utils/BotConfiguration.kt
@@ -48,26 +48,26 @@ public open class BotConfiguration { // open for Java
     /**
      * 日志记录器
      *
-     * - 默认打印到标准输出, 通过 [DefaultLogger]
+     * - 默认打印到标准输出, 通过 [MiraiLogger.create]
      * - 忽略所有日志: [noBotLog]
      * - 重定向到一个目录: `networkLoggerSupplier = { DirectoryLogger("Net ${it.id}") }`
      * - 重定向到一个文件: `networkLoggerSupplier = { SingleFileLogger("Net ${it.id}") }`
      *
      * @see MiraiLogger
      */
-    public var botLoggerSupplier: ((Bot) -> MiraiLogger) = { DefaultLogger("Bot ${it.id}") }
+    public var botLoggerSupplier: ((Bot) -> MiraiLogger) = { MiraiLogger.create("Bot ${it.id}") }
 
     /**
      * 网络层日志构造器
      *
-     * - 默认打印到标准输出, 通过 [DefaultLogger]
+     * - 默认打印到标准输出, 通过 [MiraiLogger.create]
      * - 忽略所有日志: [noNetworkLog]
      * - 重定向到一个目录: `networkLoggerSupplier = { DirectoryLogger("Net ${it.id}") }`
      * - 重定向到一个文件: `networkLoggerSupplier = { SingleFileLogger("Net ${it.id}") }`
      *
      * @see MiraiLogger
      */
-    public var networkLoggerSupplier: ((Bot) -> MiraiLogger) = { DefaultLogger("Net ${it.id}") }
+    public var networkLoggerSupplier: ((Bot) -> MiraiLogger) = { MiraiLogger.create("Net ${it.id}") }
 
     /** 父 [CoroutineContext]. [Bot] 创建后会使用 [SupervisorJob] 覆盖其 [Job], 但会将这个 [Job] 作为父 [Job] */
     public var parentCoroutineContext: CoroutineContext = EmptyCoroutineContext
@@ -349,8 +349,8 @@ public open class BotConfiguration { // open for Java
 
 internal val deviceInfoStub: (Bot) -> DeviceInfo = {
     @Suppress("DEPRECATION")
-    MiraiLogger.warning("未指定设备信息, 已使用随机设备信息. 请查看 BotConfiguration.deviceInfo 以获取更多信息.")
+    MiraiLogger.TopLevel.warning("未指定设备信息, 已使用随机设备信息. 请查看 BotConfiguration.deviceInfo 以获取更多信息.")
     @Suppress("DEPRECATION")
-    MiraiLogger.warning("Device info isn't specified. Please refer to BotConfiguration.deviceInfo for more information")
+    MiraiLogger.TopLevel.warning("Device info isn't specified. Please refer to BotConfiguration.deviceInfo for more information")
     DeviceInfo.random()
 }
\ No newline at end of file
diff --git a/mirai-core-api/src/commonMain/kotlin/utils/MiraiLogger.kt b/mirai-core-api/src/commonMain/kotlin/utils/MiraiLogger.kt
index 2a3a07ad0..bed466465 100644
--- a/mirai-core-api/src/commonMain/kotlin/utils/MiraiLogger.kt
+++ b/mirai-core-api/src/commonMain/kotlin/utils/MiraiLogger.kt
@@ -31,7 +31,15 @@ import kotlin.contracts.contract
  *
  * Java 调用: `Utils.getDefaultLogger().invoke(identity)`
  */
-public var DefaultLogger: (identity: String?) -> MiraiLogger = { PlatformLogger(it) }
+@Deprecated(
+    "Use MiraiLogger.create",
+    level = DeprecationLevel.ERROR,
+    replaceWith = ReplaceWith("MiraiLogger.create(identity)", "net.mamoe.mirai.utils.MiraiLogger")
+)
+@PlannedRemoval("2.0-M2")
+public var DefaultLogger: (identity: String?) -> MiraiLogger
+    get() = { MiraiLogger.create(it) }
+    set(value) = MiraiLogger.setDefaultLoggerCreator(value)
 
 /**
  * 给这个 logger 添加一个开关, 用于控制是否记录 log
@@ -56,14 +64,28 @@ public fun MiraiLogger.withSwitch(default: Boolean = true): MiraiLoggerWithSwitc
  * @see MiraiLoggerPlatformBase 平台通用基础实现. 若 Mirai 自带的日志系统无法满足需求, 请继承这个类并实现其抽象函数.
  */
 public interface MiraiLogger {
-    /**
-     * 顶层日志记录器.
-     *
-     * 顶层日志会导致混乱并难以定位问题. 请自行构造 logger 实例并使用.
-     * 请参考使用 [DefaultLogger]
-     */
-    @Deprecated(message = "顶层日志会导致混乱并难以定位问题. 请自行构造 logger 实例并使用.", level = DeprecationLevel.WARNING)
-    public companion object : MiraiLogger by DefaultLogger("Mirai")
+
+    public companion object {
+        /**
+         * 顶层日志, 仅供 Mirai 内部使用.
+         */
+        @MiraiInternalApi
+        @MiraiExperimentalApi
+        public val TopLevel: MiraiLogger by lazy { create("Mirai") }
+
+        @Volatile
+        private var defaultLogger: (identity: String?) -> MiraiLogger = { PlatformLogger(it) }
+
+        @JvmStatic
+        public fun setDefaultLoggerCreator(creator: (identity: String?) -> MiraiLogger) {
+            defaultLogger = creator
+        }
+
+        @JvmStatic
+        public fun create(identity: String?): MiraiLogger {
+            return defaultLogger.invoke(identity)
+        }
+    }
 
     /**
      * 日志的标记. 在 Mirai 中, identity 可为
@@ -154,14 +176,6 @@ public interface MiraiLogger {
      * @return [follower]
      */
     public operator fun <T : MiraiLogger> plus(follower: T): T
-
-    /**
-     * 添加一个 [follower]
-     * 若 [MiraiLogger.follower] 已经有值, 则会对这个值调用 [plusAssign]. 即会在日志记录器链的末尾添加这个参数 [follower]
-     *
-     * @see follower
-     */
-    public operator fun plusAssign(follower: MiraiLogger)
 }
 
 
@@ -236,8 +250,9 @@ public inline fun MiraiLogger.error(message: () -> String?, e: Throwable?) {
  *
  * 严重程度为 V, I, W, E. 分别对应 verbose, info, warning, error
  *
- * @see DefaultLogger
+ * @see MiraiLogger.create
  */
+@MiraiInternalApi
 public expect open class PlatformLogger constructor(
     identity: String? = "Mirai",
     output: (String) -> Unit, // TODO: 2020/11/30 review logs, currently it's just for compile
@@ -443,8 +458,4 @@ public abstract class MiraiLoggerPlatformBase : MiraiLogger {
         this.follower = follower
         return follower
     }
-
-    public override fun plusAssign(follower: MiraiLogger): Unit =
-        if (this.follower == null) this.follower = follower
-        else this.follower!! += follower
 }
diff --git a/mirai-core-api/src/commonMain/kotlin/utils/SwingSolver.kt b/mirai-core-api/src/commonMain/kotlin/utils/SwingSolver.kt
index d674c8703..38610a164 100644
--- a/mirai-core-api/src/commonMain/kotlin/utils/SwingSolver.kt
+++ b/mirai-core-api/src/commonMain/kotlin/utils/SwingSolver.kt
@@ -84,7 +84,7 @@ internal object WindowHelperJvm {
             kotlin.runCatching {
                 Desktop.isDesktopSupported().also { stat ->
                     if (stat) {
-                        MiraiLogger.info(
+                        MiraiLogger.TopLevel.info(
                             """
                                 Mirai 正在使用桌面环境,
                                 如果你正在使用SSH, 或无法访问桌面等,
@@ -92,7 +92,7 @@ internal object WindowHelperJvm {
                                 然后重启 Mirai
                             """.trimIndent()
                         )
-                        MiraiLogger.info(
+                        MiraiLogger.TopLevel.info(
                             """
                                 Mirai using DesktopCaptcha System.
                                 If you are running on SSH, cannot access desktop or more.
@@ -104,7 +104,7 @@ internal object WindowHelperJvm {
                 }
             }.getOrElse {
                 // Should not happen
-                MiraiLogger.warning("Exception in checking desktop support.", it)
+                MiraiLogger.TopLevel.warning("Exception in checking desktop support.", it)
                 false
             }
         } else {
diff --git a/mirai-core-api/src/jvmMain/kotlin/utils/PlatformLogger.jvm.kt b/mirai-core-api/src/jvmMain/kotlin/utils/PlatformLogger.jvm.kt
index 3ebc31efc..107b0f50c 100644
--- a/mirai-core-api/src/jvmMain/kotlin/utils/PlatformLogger.jvm.kt
+++ b/mirai-core-api/src/jvmMain/kotlin/utils/PlatformLogger.jvm.kt
@@ -38,10 +38,11 @@ import java.util.*
  *
  * @param isColored 是否添加 ANSI 颜色
  *
- * @see DefaultLogger
+ * @see MiraiLogger.create
  * @see SingleFileLogger 使用单一文件记录日志
  * @see DirectoryLogger 在一个目录中按日期存放文件记录日志, 自动清理过期日志
  */
+@MiraiInternalApi
 public actual open class PlatformLogger constructor(
     public override val identity: String? = "Mirai",
     /**
diff --git a/mirai-core/src/commonMain/kotlin/network/protocol/packet/PacketFactory.kt b/mirai-core/src/commonMain/kotlin/network/protocol/packet/PacketFactory.kt
index 33414dc83..9c3efa7df 100644
--- a/mirai-core/src/commonMain/kotlin/network/protocol/packet/PacketFactory.kt
+++ b/mirai-core/src/commonMain/kotlin/network/protocol/packet/PacketFactory.kt
@@ -33,8 +33,6 @@ import net.mamoe.mirai.internal.utils.io.readString
 import net.mamoe.mirai.internal.utils.io.useBytes
 import net.mamoe.mirai.internal.utils.io.withUse
 import net.mamoe.mirai.utils.*
-import kotlin.jvm.JvmName
-import kotlin.jvm.JvmOverloads
 
 internal sealed class PacketFactory<TPacket : Packet?> {
     /**
@@ -122,7 +120,7 @@ internal typealias PacketConsumer<T> = suspend (packetFactory: PacketFactory<T>,
  */
 @PublishedApi
 internal val PacketLogger: MiraiLoggerWithSwitch by lazy {
-    DefaultLogger("Packet").withSwitch(false)
+    MiraiLogger.create("Packet").withSwitch(false)
 }
 
 internal object KnownPacketFactories {
diff --git a/mirai-core/src/commonMain/kotlin/utils/contentToString.kt b/mirai-core/src/commonMain/kotlin/utils/contentToString.kt
index 8c07a5daf..dfa0fa435 100644
--- a/mirai-core/src/commonMain/kotlin/utils/contentToString.kt
+++ b/mirai-core/src/commonMain/kotlin/utils/contentToString.kt
@@ -12,7 +12,7 @@
 package net.mamoe.mirai.internal.utils
 
 import kotlinx.serialization.Transient
-import net.mamoe.mirai.utils.DefaultLogger
+import net.mamoe.mirai.utils.MiraiLogger
 import net.mamoe.mirai.utils.debug
 import java.lang.reflect.Modifier
 import kotlin.reflect.KClass
@@ -31,7 +31,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 by lazy { DefaultLogger("soutv") }
+private val SoutvLogger by lazy { MiraiLogger.create("soutv") }
 internal fun Any?.soutv(name: String = "unnamed") {
     @Suppress("DEPRECATION")
     SoutvLogger.debug { "$name = ${this._miraiContentToString()}" }
diff --git a/mirai-core/src/commonTest/kotlin/test/printing.kt b/mirai-core/src/commonTest/kotlin/test/printing.kt
index 285925a4f..103fd7ad4 100644
--- a/mirai-core/src/commonTest/kotlin/test/printing.kt
+++ b/mirai-core/src/commonTest/kotlin/test/printing.kt
@@ -14,19 +14,18 @@ package test
 import kotlinx.io.core.ByteReadPacket
 import kotlinx.io.core.Input
 import kotlinx.io.core.readAvailable
-import kotlinx.io.core.use
 import kotlinx.io.pool.useInstance
 import net.mamoe.mirai.internal.utils.ByteArrayPool
 import net.mamoe.mirai.internal.utils.toReadPacket
 import net.mamoe.mirai.internal.utils.toUHexString
-import net.mamoe.mirai.utils.DefaultLogger
+import net.mamoe.mirai.utils.MiraiLogger
 import net.mamoe.mirai.utils.MiraiLoggerWithSwitch
 import net.mamoe.mirai.utils.withSwitch
 import kotlin.contracts.InvocationKind
 import kotlin.contracts.contract
 
 
-val DebugLogger: MiraiLoggerWithSwitch = DefaultLogger("Packet Debug").withSwitch(true)
+val DebugLogger: MiraiLoggerWithSwitch = MiraiLogger.create("Packet Debug").withSwitch(true)
 
 internal inline fun ByteArray.debugPrintThis(name: String): ByteArray {
     DebugLogger.debug(name + "=" + this.toUHexString())