1

We are currently using Tomcat 7 with a single log configuration specified using -Djava.util.logging.config.file and the default ClassLoaderLogManager with -Djava.util.logging.manager="org.apache.juli.ClassLoaderLogManager". This works great for a one-time startup config.

We have several servlets and other code that runs outside the servlet context. We run on a dedicated tomcat server that we completely control, and we want all the code to use the same log configuration. We are using the java.util.logging API for logging. This means that LogManager.getLogManager().getLogger(name) needs to work, and that Logger.isLoggable(Level) needs to work.

ClassLoaderLogManager seems geared towards the opposite of our situation: allowing servlets to specify individual log settings. We want all the logs controlled in one place. But, we do want the other JULI benefits like the improved FileHandlers.

Now the question: How can I reload these settings from the file at runtime without reloading the application?

What I've tried:

  • LogManager.getLogManger.readConfiguration(): results in an effective NOOP in ClassLoaderLogManager because Thread.currentThread.getContextClassLoader() isn't the system classloader.
  • Explicitly setting Thread.setContextClassLoader(ClassLoader.getSystemClassLoader()) and then calling the above. This did actually read the config file (stepped through in a debugger) but it didn't propagate the changes down to existing loggers in the contained ClassLoaders. Logger.setLevel() was never called on existing loggers.
  • also calling reset() before these calls doesn't seem to change anything.
  • JMX appears to only expose the loggers for a single ClassLoader (possibly the system ClassLoader)
TREE
  • 1,292
  • 2
  • 12
  • 21
  • What, specifically with JMX? JConsole shows something exposed on java.util.logging, but it appears to only be part of the top-level ClassLoader. No loggers for classes from the servlets, for example, are exposed. – TREE Feb 28 '13 at 17:28
  • JConsole ist correct but you can, see [here](http://i.imgur.com/7mNwh5D.png) – Michael-O Feb 28 '13 at 17:40
  • If you see the "LoggerNames" under Attributes, that's what I was referring to. It does not include the loggers in the servlets. That means that I wouldn't be able to set the log level for any loggers that were created in the servlets. – TREE Feb 28 '13 at 18:02
  • Why don't you use setLogLevel? This should do. – Michael-O Feb 28 '13 at 18:36
  • From where? I would need to call it for every logger in every ClassLoader. And I don't particularly want to rewrite the config file parsing code. – TREE Feb 28 '13 at 18:53
  • Wouldn't it suffice to set that on the ROOT logger? JULI has a VM wide config. You cannot have more control over. Am I wrong? – Michael-O Feb 28 '13 at 19:10
  • Yes, I believe you are wrong. Each ClassLoader has a separate Root logger. Also, I don't wish to have a single log level across all loggers, just a single configuration file across all ClassLoaders, which I can reload at runtime. – TREE Feb 28 '13 at 19:16
  • They you should really follow Adam's advice and resort to Logback it will give you exactly what you need. You can even specify a scan period. – Michael-O Feb 28 '13 at 19:23

2 Answers2

2

I found one solution to this. Replacing the log manager in the startup script with the default java.util.logging.LogManager or simply deleting the command line argument results in the regular LogManager being used. This LogManager will fully reload the configuration for all Loggers in all ClassLoaders when readConfiguration() is called, exactly the behavior I need.

This does involve modifying the tomcat startup scripts, however. If someone can find a better solution without doing that, that would be great, otherwise I'll accept this answer.

TREE
  • 1,292
  • 2
  • 12
  • 21
0

If your not married to Tomcat JULI you might want to consider using Logback since IMHO its the only the that reliably handles log configuration reloading during runtime.

I haven't done this myself but some one has written a guide: Logging with SLF4J and Logback in Tomcat and TomEE which basically using a bunch of bridge jars.

The other thing you might consider is just using per web app logging with Logback and just ignore Tomcat's JULI logs (thats what I do).

CAVEAT: http://www.slf4j.org/legacy.html#jul-to-slf4j ... consequently please never use JUL directly.... Guava and Tomcat are on my $hit list for using JUL.

Community
  • 1
  • 1
Adam Gent
  • 47,843
  • 23
  • 153
  • 203
  • Would logback update the log levels for java.util.logging Loggers? – TREE Feb 28 '13 at 18:34
  • No, you would brigde JULI to SLF4J and then Use Logback as backend. – Michael-O Feb 28 '13 at 18:36
  • Yes but I do know that I think logback has some sort of issue with java.util.logging in terms of performance: http://www.slf4j.org/legacy.html#jul-to-slf4j ... basically JULI is a POS. – Adam Gent Feb 28 '13 at 18:40
  • JULI != java.util.logging. JULI is from apache, part of Tomcat (although the documentation describes it as an independent project) – TREE Feb 28 '13 at 18:48
  • Yes I got the acronyms confused. Tomcat is not as guilty as Guava. – Adam Gent Feb 28 '13 at 18:49
  • The comment on performance implies that slf4j/logback will *not* call back to the java.util.logging.Loggers. It implies that those loggers log everything, and then slf4j does the filtering. That is very clearly going to cause bad performance. So using slf4j or logback as a backend only is probably not an option. – TREE Feb 28 '13 at 18:49
  • Read the blog post. The author mentions a JULI direct adapter ie [Tomcat -> SLF4J](http://code.google.com/p/tomcat-slf4j/) instead of Tomcat -> JUL -> SLF4J... but yes that is one of the reasons why I just gave up and use per webapp logging. – Adam Gent Feb 28 '13 at 18:52
  • The question has been clarified RE: dependence on java.util.logging Loggers. We can't rewrite the calling code at this point. The blog post linked doesn't say anything about using this API with other backends, other than as a Handler. A Handler cannot configure the Loggers, which is the part I really need. – TREE Feb 28 '13 at 19:36