在Tomcat JULI中,“特定设施”记录器是否成为每个webapp记录器的根?

时间:2013-10-09 01:57:01

标签: tomcat logging tomcat-juli

我可以期待“嗨!”的日志条目将被发送到${catalina.base}/logs/webapp.log

Tomcat配置

{$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

Webapp级别日志记录配置

部署到WEB-INF/classes/logger.properties

/webapp WAR

au.com.mydomain.level = ALL

代码

的用法

WAR中的代码部署到/webapp

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!");
  ...
}

1 个答案:

答案 0 :(得分:1)

答案是“不”

在调试器中确认,如果Web应用程序执行:

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

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

但一切都没有丢失

可以获得对'per-webapp'记录器的引用:

{$CATALINA_BASE}/conf/logger.properties

这意味着我们可以使用per-webapp记录器作为父记录来获取记录器:

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

一个可怕的,可怕的黑客

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

如果您执行以下操作(在Logger.getLogger(prefix + "." + MyClass.class.getName()) 之类的地方,您可以:

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!");

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

作为一种潜在的令人讨厌的副作用,我们的记录器根目录在JVM范围的记录器层次结构中的两个点上是一个“子”,这可能会在某个时间某个地方扰乱某人。