@@ -5,7 +5,8 @@ import scala.collection.mutable
55
66object Logger {
77
8- val GLOBAL_LOGGER_NAME : String = " global"
8+ final val GLOBAL_LOGGER_NAME = " global"
9+ private final val ROOT_LOGGER_NAME = " "
910
1011 // Not implemented, deprecated on JDK 1.8
1112 // val global: Logger
@@ -14,30 +15,57 @@ object Logger {
1415
1516 private val loggers : mutable.Map [String , Logger ] = mutable.Map .empty
1617
18+ /** Find parent logger */
19+ @ tailrec
20+ private def findParentLoggerOf (name : String ): Logger = {
21+ name match {
22+ case null => // Anonymous logger
23+ rootLogger
24+ case ROOT_LOGGER_NAME =>
25+ null
26+ case _ =>
27+ val parentName = name.substring(0 , name.lastIndexOf('.' ).max(0 ))
28+ loggers.get(parentName) match {
29+ case Some (l) => l
30+ case None => findParentLoggerOf(parentName)
31+ }
32+ }
33+ }
34+
1735 private def newLogger (name : String ): Logger = {
1836 val logger = new Logger (name, null )
1937 logger.setLevel(null )
2038 logger.setUseParentHandlers(true )
21- logger.setParent(rootLogger)
39+ logger.setParent(findParentLoggerOf(name))
40+ if (name != null ) {
41+ updateChildLoggerParent(logger)
42+ }
2243 logger
2344 }
2445
46+ private def updateChildLoggerParent (newParent : Logger ): Unit = {
47+ val prefix = s " ${newParent.getName}. "
48+ // Traverse all child loggers of the new parent
49+ for ((name, childLogger) <- loggers if name.startsWith(prefix)) {
50+ val currentParent = childLogger.getParent
51+ // For example, when a new parent a.b is added:
52+ // - if child is a.b.c.d (parent = null) => needs to be a.b.c.d (parent = a.b)
53+ // - if child is a.b.c.e (parent = a.b.c) => no update is required.
54+ if (currentParent == null || ! currentParent.getName.startsWith(prefix)) {
55+ childLogger.setParent(newParent)
56+ }
57+ }
58+ }
59+
2560 // Root is not visible to the outside but gives defaults
2661 private [this ] val rootLogger : Logger = {
27- val l = new Logger (" " , null )
28- l.setLevel(defaultLogLevel)
29- l.setUseParentHandlers(false )
30- l.setParent(null )
31- l
62+ val root = getLogger(ROOT_LOGGER_NAME )
63+ root.setLevel(defaultLogLevel)
64+ root.setUseParentHandlers(false )
65+ root
3266 }
3367
34- private [this ] val globalLogger : Logger = {
35- val l = new Logger (GLOBAL_LOGGER_NAME , null )
36- l.setLevel(defaultLogLevel)
37- l.setUseParentHandlers(true )
38- l.setParent(rootLogger)
39- l
40- }
68+ private [this ] val globalLogger : Logger = getLogger(GLOBAL_LOGGER_NAME )
4169
4270 def getGlobal (): Logger = globalLogger
4371
@@ -51,20 +79,6 @@ object Logger {
5179 // Not implemented, no resource bundle in scala.js
5280 // def getLogger(name: String, resourceBundle: String): Logger
5381
54- private [logging] def findParent (logger : Logger ): Option [Logger ] = {
55- @ tailrec
56- def go (s : List [String ]): Option [Logger ] = s match {
57- case Nil => None
58-
59- case b if loggers.contains(b.mkString(" ." )) =>
60- loggers.get(b.mkString(" ." ))
61-
62- case b => go(b.dropRight(1 ))
63- }
64-
65- go(Option (logger.getName).getOrElse(" " ).split(" \\ ." ).toList.dropRight(1 ))
66- }
67-
6882 def getAnonymousLogger (): Logger = {
6983 // No references to anonymous loggers are kept
7084 newLogger(null )
@@ -315,7 +329,7 @@ class Logger(name: String, resourceBundle: String) {
315329
316330 def getUseParentHandlers (): Boolean = useParentsHandlers
317331
318- def getParent (): Logger = Logger .findParent( this ).getOrElse( parent)
332+ def getParent (): Logger = parent
319333
320334 def setParent (parent : Logger ): Unit = this .parent = parent
321335}
0 commit comments