在Tomcat JULI中,"特定于设施"的记录器是否成为每个Web应用程序的记录器根?



我可以期望向${catalina.base}/logs/webapp.log发出"Hi!"的日志条目吗?

雄猫配置

{$CATALINA_BASE}/conf/logger.properties

# DECLARE HANDLERS
handlers = 3webapp.org.apache.juli.FileHandler
# CONFIGURE HANDLERS
3webapp.org.apache.juli.FileHandler.level = ALL
3webapp.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
3webapp.org.apache.juli.FileHandler.prefix = webapp
3webapp.org.apache.juli.FileHandler.rotatable = false
# Webapp-local 'ROOT' logger??  The Apache-provided logger.properties
# calls these 'Facility specific'
org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/webapp].level = ALL
org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/webapp].handlers = 3webapp.org.apache.juli.FileHandler

Web 应用级日志记录配置

部署到/webapp的战争WEB-INF/classes/logger.properties

au.com.mydomain.level = ALL

代码中的用法

部署到/webapp的 WAR 中的代码

package au.com.mydomain.foo;
import java.util.logging.Logger;
import java.util.logging.Level;
public class Bar {
  ...
  Logger.getLogger(Bar.class.getName()).log(Level.INFO, "Hi!");
  ...
}

答案是"否">

正如在调试器中确认的那样,如果 Web 应用程序执行以下操作:

 import java.util.logging.Logger;
 ...
 Logger foo = Logger.getLogger("foo");

然后foo的直接父级是org.apache.juli.ClassLoaderLogManager$RootLogger,它是由Catalina建立的JVM范围的记录器,并且是{$CATALINA_BASE}/conf/logger.properties中定义的所有其他记录器的最终祖先。

但一切都没有丢失

可以获得

对"每网络应用"记录器的引用:

String prefix = "org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/webapp]";
Logger hmm = Logger.getLogger(prefix);

这意味着我们可以获取一个将每个 WebApp 记录器作为父级的记录器:

Logger.getLogger(prefix + "." + MyClass.class.getName())

一个可怕的,可怕的黑客

但是,当然,所有现有的代码都在不指定前缀的情况下执行 Logger.getLogger((。

如果您执行以下操作(在类似 ServletContextListener#contextInitialized(ServletContextEvent) 的地方,您可以:

// eg "org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/webapp]"
String tomcatHack = sce.getServletContext().getInitParameter("tomcatHack");
if (tomcatHack != null) {
   Logger ctxLog = Logger.getLogger("webappLogger");
   Logger appLog = Logger.getLogger("au.com.mydomain");
   appLog.setParent(ctxLog);
}

现在后续日志到:

Logger.getLogger("au.com.mydomain.foo").log(Level.INFO, "Ha!");

。会出现在log.log.

作为一个令人讨厌的副作用,如果你有两个网络应用程序在同一容器中运行这个技巧(例如,/prod 和/test(,那么它们将覆盖父级。

作为一个潜在的令人讨厌的副作用,我们的记录器根现在在JVM范围的记录器层次结构中的两个点上是一个"孩子",这可能会在某个地方,某个时候让某人感到不安。

最新更新