2

我们在 Linux 上使用 Tomcat 5.5。我们的 webapp 使用 log4j 进行日志记录(基于功能且记录器不多),并有意将记录器的可加性设置为 false。我们的记录器记录到我们自己的日志文件中。他们都没有登录到控制台。

我们遇到的一个问题是,当我们的记录器级别设置为 DEBUG 时,我们开始在 catalina.out 中从 3rd 方组件(尤其是 oscache)获取大量调试日志记录。

.../common/classes 中有一个最小的 log4j.properties 文件:

log4j.rootLogger=INFO, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout

# Print the date in ISO 8601 format
log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n

.../webapps/ourapp/WEB-INF/classes 中没有 log4g.properties 文件。

我尝试的第一件事是更改为,log4j.rootLogger=ERROR, A1但这没有任何区别。

我尝试的下一件事是创建一个包含单行的 .../webapps/ourapp/WEB-INF/classes/log4j.properties 文件

log4j.logger.com.opensymphony.oscache=ERROR

看看这是否会停止 oscache 日志记录。确实如此,但令人惊讶的是(对我而言)它停止了所有不需要的日志记录,而不仅仅是 oscache 日志记录。所以我评论了这条线并再次尝试。仍然没有任何不需要的日志记录。我将文件移到一边,现在不需要的日志记录又回来了。我创建了一个长度为零的 log4j.properties,所有不需要的日志记录又消失了(!)虽然这是我想要的短期内容,但它让我想知道还有哪些其他日志记录被丢弃(以及为什么!)。所以我只是依靠它感到不舒服。

Tomcat 5.5 文档中的“日志”一章只是说您可以通过将属性文件放在 WEB-INF/classes 中来进行每个应用程序的配置,但没有(至少我找不到)谈论它如何与在 common/classes 中指定的配置。

所以:

  • 第 3 方组件如何首先记录到 catalina.out?我猜他们的日志记录可能会冒泡到根记录器,但是为什么即使根记录器级别设置为错误,他们仍然会记录?
  • 为什么将记录器上的记录器级别设置为 DEBUG 会启动此记录?我们的记录器有自己的名称,因此 oscache 和其他东西不可能是我们记录器的祖先。
  • 为什么即使是零长度的 WEB-INF/classes/log4j.properties 文件也会停止一大堆日志记录?
  • 我怎样才能以“正确”的方式做到这一点并以有意义的方式限制日志记录,而不是依靠一些奇怪的(对我而言)副作用来关闭它?


越来越好奇。我尝试了马特关于打开调试的建议。我还为 webapp 制作了一个更广泛的 log4j.properties 文件:

log4j.rootLogger=INFO, SSOA1
log4j.appender.SSOA1=org.apache.log4j.ConsoleAppender
log4j.appender.SSOA1.layout=org.apache.log4j.PatternLayout

# Print the date in ISO 8601 format
log4j.appender.SSOA1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n

log4j.logger.com.opensymphony.oscache=ERROR
#log4j.additivity.com.opensymphony.oscache=false

当tomcat启动时,我看到:

log4j: Using URL [file:/srv/www/tomcat5/base/webapps/myapp/WEB-INF/classes/log4j.properties] for automatic log4j configuration.
log4j: Reading configuration from URL file:/srv/www/tomcat5/base/webapps/myapp/WEB-INF/classes/log4j.properties
log4j: Parsing for [root] with value=[INFO, SSOA1].
log4j: Level token is [INFO].
log4j: Category root set to INFO
log4j: Parsing appender named "SSOA1".
log4j: Parsing layout options for "SSOA1".
log4j: Setting property [conversionPattern] to [%d [%t] %-5p %c - %m%n].
log4j: End of parsing for "SSOA1".
log4j: Parsed "SSOA1" options.
log4j: Parsing for [com.opensymphony.oscache] with value=[ERROR].
log4j: Level token is [ERROR].
log4j: Category com.opensymphony.oscache set to ERROR
log4j: Handling log4j.additivity.com.opensymphony.oscache=[null]
log4j: Finished configuring.

但是尽管 oscache 记录器的级别设置为错误,我仍然在日志中看到类似这样的内容:

2011-03-30 14:53:22,076 [main] DEBUG com.opensymphony.oscache.base.algorithm.AbstractConcurrentReadCache - get called (key=AUDIT_KEY_OLDEST_TIMSTAMP)

如果我将 oscache 记录器级别强制为 ERROR(log4j 调试输出显示我是),那么为什么要发送此 DEBUG 消息?子记录器覆盖代码中的级别?

我注意到的是,如果我在 webapp 的 log4j.properties 文件中取消注释 oscache 记录器的“可加性”行,那么日志记录确实会消失。因此,似乎 oscache 日志记录依赖于祖先附加程序,而不是它自己的。但似乎更奇怪的是,将 oscache 记录器级别设置为 ERROR 并没有阻止这些事情。

4

2 回答 2

2

您可以配置 log4j.properties 以仅获取您的代码日志,如下所示,并将其放入与 catalina.out 不同的文件中。

处理程序 = org.apache.juli.FileHandler

org.apache.juli.FileHandler.level=所有 org.apache.juli.FileHandler.directory=${catalina.base}/logs org.apache.juli.FileHandler.prefix=yourapp-name。

com.yourproject.module.package.level=ALL

于 2011-03-29T21:58:46.150 回答
2

我已经弄清楚到底发生了什么。问题在于,隐藏在 webapp 另一部分内部的是以下代码,该代码在该组件进入调试模式时运行:

public static synchronized void setDebugOn(boolean debugOn) {
    if (isAllDebugOn() ^ debugOn) {
        setAllDebugOn(debugOn);
        Enumeration en = LogManager.getCurrentLoggers();
        while (en.hasMoreElements()) {
            setDebugOn((Logger) en.nextElement(), debugOn);
        }
        setDebugOn(LogManager.getRootLogger(), debugOn);
    }
}

public static void setDebugOn(String name, boolean debugOn) {
    setDebugOn(getLogger(name), debugOn);
}

private static void setDebugOn(Logger logger, boolean debugOn) {
    logger.setLevel(debugOn ? Level.DEBUG : Level.INFO);
}

换句话说,当这个组件处于调试模式时,它也会将WEBAPP 中的每个 LOG4J LOGGER都置于调试模式(我已经通过更改代码以打印出最后一个方法中的每个记录器的名称来验证这一点这三个。所以 blammo - 所有碰巧使用 log4j 的第 3 方的东西都开始记录它的调试输出,不管 log4j.properties 说什么。叹息。

When I change the method with that loop to only mess with the levels of specific loggers related to that component then my log4j.properties configuration starts working as expected.

于 2011-03-30T21:39:36.337 回答