dongjinleekr commented on a change in pull request #7898:
URL: https://github.com/apache/kafka/pull/7898#discussion_r793571163



##########
File path: core/src/main/scala/kafka/utils/Log4jController.scala
##########
@@ -17,83 +17,92 @@
 
 package kafka.utils
 
+import org.apache.logging.log4j.core.LoggerContext
+import org.apache.logging.log4j.core.config.Configurator
+import org.apache.logging.log4j.{Level, LogManager}
+
 import java.util
 import java.util.Locale
-
-import org.apache.kafka.common.utils.Utils
-import org.apache.log4j.{Level, LogManager, Logger}
-
-import scala.collection.mutable
 import scala.jdk.CollectionConverters._
 
 
 object Log4jController {
+
+  /**
+   * Note: In log4j, the root logger's name was "root" and Kafka also followed 
that name for dynamic logging control feature.
+   *
+   * The root logger's name is changed in log4j2 to empty string (see: 
[[LogManager.ROOT_LOGGER_NAME]]) but for backward-
+   * compatibility. Kafka keeps its original root logger name. It is why here 
is a dedicated definition for the root logger name.
+   */
   val ROOT_LOGGER = "root"
 
-  private def resolveLevel(logger: Logger): String = {
-    var name = logger.getName
-    var level = logger.getLevel
-    while (level == null) {
-      val index = name.lastIndexOf(".")
-      if (index > 0) {
-        name = name.substring(0, index)
-        val ancestor = existingLogger(name)
-        if (ancestor != null) {
-          level = ancestor.getLevel
-        }
-      } else {
-        level = existingLogger(ROOT_LOGGER).getLevel
-      }
-    }
-    level.toString
-  }
+  /**
+   * Returns given logger's parent's (or the first ancestor's) name.
+   *
+   * @throws IllegalArgumentException loggerName is null or empty.
+   */
 
   /**
-    * Returns a map of the log4j loggers and their assigned log level.
-    * If a logger does not have a log level assigned, we return the root 
logger's log level
-    */
-  def loggers: mutable.Map[String, String] = {
-    val logs = new mutable.HashMap[String, String]()
-    val rootLoggerLvl = existingLogger(ROOT_LOGGER).getLevel.toString
-    logs.put(ROOT_LOGGER, rootLoggerLvl)
-
-    val loggers = LogManager.getCurrentLoggers
-    while (loggers.hasMoreElements) {
-      val logger = loggers.nextElement().asInstanceOf[Logger]
-      if (logger != null) {
-        logs.put(logger.getName, resolveLevel(logger))
-      }
-    }
-    logs
+   * Returns a map of the log4j loggers and their assigned log level.
+   * If a logger does not have a log level assigned, we return the log level 
of the first ancestor with a level configured.
+   */
+  def loggers: Map[String, String] = {
+    val logContext = LogManager.getContext(false).asInstanceOf[LoggerContext]
+    val rootLoggerLevel = logContext.getRootLogger.getLevel.toString
+
+    // Loggers defined in the configuration
+    val configured = logContext.getConfiguration.getLoggers.asScala
+      .values
+      .filter(_.getName != LogManager.ROOT_LOGGER_NAME)
+      .map { logger =>
+        logger.getName -> logger.getLevel.toString
+      }.toMap
+
+    // Loggers actually running
+    val actual = logContext.getLoggers.asScala
+      .filter(_.getName != LogManager.ROOT_LOGGER_NAME)
+      .map { logger =>
+        logger.getName -> logger.getLevel.toString
+      }.toMap
+
+    (configured ++ actual) + (ROOT_LOGGER -> rootLoggerLevel)
   }
 
   /**
-    * Sets the log level of a particular logger
-    */
+   * Sets the log level of a particular logger. If the given logLevel is not 
an available log4j level

Review comment:
       For `Level#toLevel` semantics, see:
   
   - [`Level` (log4j 
1.x)](https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Level.html)
   - [`Level` (log4j 1-2 compatibility 
module)](https://logging.apache.org/log4j/2.x/log4j-1.2-api/apidocs/org/apache/log4j/Level.html)
   - [`Level` (log4j 
2.x)](https://logging.apache.org/log4j/2.x/log4j-api/apidocs/org/apache/logging/log4j/Level.html)
   
   As you can see here, all of above follows the same semantics - they fallback 
to `DEBUG` with unknown level.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: jira-unsubscr...@kafka.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


Reply via email to