1

我们目前正在使用 Tomcat 7,其中使用 -Djava.util.logging.config.file 指定单个日志配置,默认 ClassLoaderLogManager 使用 -Djava.util.logging.manager="org.apache.juli.ClassLoaderLogManager"。这对于一次性启动配置非常有用。

我们有几个 servlet 和其他在 servlet 上下文之外运行的代码。我们在我们完全控制的专用 tomcat 服务器上运行,并且我们希望所有代码使用相同的日志配置。我们使用 java.util.logging API 进行日志记录。这意味着 LogManager.getLogManager().getLogger(name) 需要工作,而 Logger.isLoggable(Level) 需要工作。

ClassLoaderLogManager 似乎与我们的情况相反:允许 servlet 指定单独的日志设置。我们希望将所有日志控制在一个地方。但是,我们确实想要其他 JULI 的好处,比如改进的 FileHandlers。

现在的问题是:如何在运行时从文件中重新加载这些设置而不重新加载应用程序?

我试过的:

  • LogManager.getLogManger.readConfiguration():在 ClassLoaderLogManager 中产生有效的 NOOP,因为 Thread.currentThread.getContextClassLoader() 不是系统类加载器。
  • 显式设置 Thread.setContextClassLoader(ClassLoader.getSystemClassLoader()) 然后调用上面的。这确实读取了配置文件(在调试器中逐步执行),但它没有将更改传播到包含的 ClassLoaders 中的现有记录器。Logger.setLevel() 从未在现有记录器上调用。
  • 在这些调用之前调用 reset() 似乎没有任何改变。
  • JMX 似乎只公开单个 ClassLoader(可能是系统 ClassLoader)的记录器
4

2 回答 2

2

我找到了一个解决方案。将启动脚本中的日志管理器替换为默认的 java.util.logging.LogManager 或简单地删除命令行参数会导致使用常规的 LogManager。当调用 readConfiguration() 时,此 LogManager 将完全重新加载所有 ClassLoaders 中所有 Logger 的配置,这正是我需要的行为。

但是,这确实涉及修改 tomcat 启动脚本。如果有人可以在不这样做的情况下找到更好的解决方案,那就太好了,否则我会接受这个答案。

于 2013-02-28T20:48:11.143 回答
0

如果您没有与 Tomcat JULI 结婚,您可能需要考虑使用 Logback,因为恕我直言,它是唯一能够在运行时可靠地处理日志配置重新加载的方法。

我自己没有这样做,但是有人写了一个指南:Logging with SLF4J and Logback in Tomcat and TomEE,它基本上使用了一堆桥接 jar。

您可能会考虑的另一件事是仅将每个 Web 应用程序日志记录与 Logback 一起使用,而忽略 Tomcat 的 JULI 日志(这就是我所做的)。

警告:http : //www.slf4j.org/legacy.html#jul-to-slf4j ...因此请不要直接使用 JUL .... Guava和 Tomcat 在我使用 JUL 的 $hit 列表中。

于 2013-02-28T18:21:34.173 回答