3

I am using JULI logging framework in current Tomcat 7, providing a webapp specific logging.properties in my WEB-INF/classes folder.

Now I am looking for a way to change the log level of a logger at runtime.

I found several sources saying that changing the level of a logger at runtime might be possible via MBean Server. Unfortunately the appropriate MBean "java.util.logging.Logging" does not list my webapp specific logger, so I cannot execute the method "setLoggerLevel".

Does anyone know how to accomplish this? Thanks for any hints - excluding those suggesting to use log4j, that is... ;-)

Torgeist
  • 524
  • 4
  • 13

1 Answers1

2

Connecting JConsole to Tomcat and using the MBean tab to change the logger level is the ideal way. One issue is that the logger names don't exist unless the code has triggered the creation of a logger. You can't use the MBean to create a logger ahead of the code running. You should use JConsole to double check that the MBean itself doesn't exist.

Tomcat installs a custom LogManager that filters by the current class loader. JMX would be using the system class loader so it is possible that ClassLoaderLogManager won't return the logger names because the current classloader is not the web app classloader.

You could always create a servlet/jsp form or webservice deployed with the application to get the logger and set the level. You might have to pin each modified logger in memory to keep your logger level active. You can free the logger once the level is set back to null. You'll have to deal with security concerns with including such a page.

I wouldn't do this on a production server but you can configure a WatchedResource in tomcat that points to your logging.properties. Then any time that file is updated the web app is redeployed with the new settings. Watch out for ClassLoader leaks going that route.

jmehrens
  • 10,580
  • 1
  • 38
  • 47
  • Thanks for your suggestions. Option 1: I connected to Tomcat (with Mission Control) and looked at the bean "java.util.logging:type=Logging". No webapp specific loggers listed there. Option 2 might be possible, though I always retrieve the logger instances via Logger.getLogger("..."), and afaik there is no guarantee that setting the level on such an instance really works in all cases - yet I'll give it a try! Option 3 is out of scope - it's the redeployment I want to avoid :-) – Torgeist Nov 19 '14 at 15:07
  • Yeah, your edit points to what I meant in my comment of option 2: changing a logger instance does not necessarily solve the problem. Geez - why are no web-app specific loggers listed in that MBean?! After all that seems to be the real problem to solve... – Torgeist Nov 20 '14 at 15:54
  • There might be a bug in the Tomcat ClassLoaderLogManager where it is filtering for all loggers related to the system class loader and not the web app classloader. You should write a jsp to iterate over the LogManager.getLoggerNames under your web-app classloader and see if the names differ with JMX – jmehrens Nov 20 '14 at 16:44
  • Yeah, there is a difference: LogManager.getLoggerNames() on a JSP delivers all the loggers I would expect - including those web-app specific ones I want to alter! Now what to do? Does this mean there is simply no way to change the log level using an MBean browser? PS: sorry for the delay... I appreciate your efforts very much :-) – Torgeist Jan 13 '15 at 15:37
  • You can file a RFE against Tomcat ClassLoaderLogManager to allow access to all loggers when the call site is coming from the java.util.logging.LoggingMXBean. Or allow access to all loggers when the CCL is the system class loader. – jmehrens Jan 13 '15 at 21:04
  • Some other options would be to create and register and MXBean from your webapp. If you can capture the web app class loader you can gain access to the loggers by setting the CCL before you call into the ClassLoaderLogManager. Or try and install the default LogManager with Tomcat. – jmehrens Jan 15 '15 at 15:25
  • I'm sorry but I didn't quite understand your last comment: what do you mean by "setting the CCL before you call into the CLLM"? – Torgeist Jan 16 '15 at 07:49
  • The [context classloader](http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setContextClassLoader-java.lang.ClassLoader-) is used to restrict access to loggers in the CLLM. – jmehrens Jan 16 '15 at 14:14