When enabling ClassLoaderLogManager, the top of the logger are three instances of ClassLoaderLogManager$RootLogger - all named "". Whilst I can't point to anything in the spec to say that Loggers must be uniquely named, the implementation of java.util.LogManager's getLogger() (via LoggerContext.findLogger()) itself uses a HashMap to lookup Logger instances by name. That might suggest that ClassLoaderLogManager's behaviour is, at minimum, unexpected. I found this situation when attempting to use Log4J's Log4jBridgeHandler and found my logs were getting published twice: the duplicate Loggers foiled Log4jBridgeHandler's logic in trying to remove existing handlers on the JULI Root Logger.
I believe that this behavior is dictated by the lack of support in JUL for logger contexts, which forces Tomcat to use several hacks and tricks. However, I have to partially agree with this report. The way Tomcat JULI deals with `Handler` sharing between applications is inconsistent. If an application does not have a `logging.properties` file (very common case): * the root logger of an application has the global root logger as parent and `useParentHandlers` set to true. This way it delegates all logging to the global root logger handlers, * all other loggers copy the references to global handlers as their own. I believe that this architecture can be simplified and remove the need for a parent of the root logger. I'll try to submit a PR for it.
Tomcat JULI is explicitly intended to permit multiple loggers with the same name. Consider the case where different applications using the same library are deployed to a Tomcat instance. If that library uses java.util logging, the applications will share loggers making it difficult/impossible to identify which messages originate from which application. JULI solves this problem by extending the unique key for a logger from name to class loader + name. Since each web application has a dedicated class loader, loggers for each web application remain separate - even if both applications have a logger with the same name. The description in comment #1 of how the handlers are configured does not match what I see with the current code. Given that there is one root logger (called "") per class loader and that the requirement is for logging to be delegated to the parent class loader's handlers if the current class loader doesn't have an explicit configuration, I don't see how the current setup could be simplified but I'll leave this issue open for now as it is always possible there is a solution I haven't thought of. I am changing this to an enhancement request though as having multiple loggers with the same name, including the root loggers, is by design.
Hi Mark, (In reply to Mark Thomas from comment #2) > The description in comment #1 of how the handlers are configured does not > match what I see with the current code. I was referring to this snippet of code, that deals with the case, where the application's classloader does not contain a `logging.properties` resource: if (is == null) { // Retrieve the root logger of the parent classloader instead ClassLoader current = classLoader.getParent(); ClassLoaderLogInfo info = null; while (current != null && info == null) { info = getClassLoaderInfo(current); current = current.getParent(); } if (info != null) { localRootLogger.setParent(info.rootNode.logger); } } https://github.com/apache/tomcat/blob/bb81a2cf7abf2384e73bdac0313731b8963b9b66/java/org/apache/juli/ClassLoaderLogManager.java#L496 I believe that the reporter's main problem isn't having multiple loggers with the same name, but having a root logger that has a parent. That is the reason the code that removes all root handlers and replaces them with a Log4jBridgeHandler does not work: https://issues.apache.org/jira/browse/LOG4J2-3646 We can probably greatly reduce the `if` clause above, by ensuring that a `logging.properties` file is always found. There are however implications to such a change: Spring Boot uses heuristic to decide whether or not install a Slf4jBridgeHandler. IIRC the current version checks if the root logger has a single Console handler. In the current Tomcat JULI version the root logger of a web app has no handlers, if we make the change above, it will have all the handlers from the standard Catalina `logging.properties`. https://github.com/spring-projects/spring-boot/issues/8933