Replacing JUL with logback with Tomcat

I have setup logback-access according to the documentation with a LogbackValve and my Tomcat instance is logging requests. However it seems Tomcat is still writing messages to the console using JUL. What is the best way to route these messages to logback? Do I configure Tomcat to use log4j and then try and bridge those messages into logback-classic or is there a less complicated way? In the past I followed these instructions [1] to get Tomcat logging with log4j but would rather just use logback going forward. Thanks, Alex http://mrhaki.blogspot.com/2011/02/configure-log4j-on-tomcat.html

Hi, I'm trying to use Logback JMX in my application to allow me to change the configuration at runtime. I've created client code that can retrieve the JMX bean, and am able to invoke the JMX bean to get/set logging levels. This works just fine on one single server. However, my application is deployed on a cluster of two servers. When invoking the JMXConfigurator, it only modifies the logging configuration on the particular server that I happened to connect to for that http request, but does not modify the configuration on the other clustered server. Am I missing something, or is there no way to have one JMX call update the logback configuration on all clustered servers? Am I perhaps retrieving the JMX bean incorrectly for a clustered environment? Any help would be greatly appreciated. Here is the client code I am using to access the JMX bean: String contextName = "myContextName"; String objectNameStr = ch.qos.logback.classic.jmx.MBeanUtil. getObjectNameFor(contextName, JMXConfigurator.class); javax.management.ObjectName objectName = new javax.management.ObjectName(objectNameStr); javax.management.MBeanServer mbs = java.lang.management.ManagementFactory. getPlatformMBeanServer(); mbean = javax.management.JMX.newMBeanProxy(mbs, objectName, JMXConfiguratorMBean.class, true); mbean.setLoggerLevel("myLogger", "debug"); Thanks, -Chris *************************** IMPORTANT NOTE*****************************-- The opinions expressed in this message and/or any attachments are those of the author and not necessarily those of Brown Brothers Harriman & Co., its subsidiaries and affiliates ("BBH"). There is no guarantee that this message is either private or confidential, and it may have been altered by unauthorized sources without your or our knowledge. Nothing in the message is capable or intended to create any legally binding obligations on either party and it is not intended to provide legal advice. BBH accepts no responsibility for loss or damage from its use, including damage from virus. ********************************************************************************

bump Thanks, -Chris From: Christopher.White@bbh.com To: logback users list <logback-user@qos.ch> Date: 03/05/2012 02:31 PM Subject: [logback-user] JMX on a WebSphere clustered environment Sent by: logback-user-bounces@qos.ch Hi, I'm trying to use Logback JMX in my application to allow me to change the configuration at runtime. I've created client code that can retrieve the JMX bean, and am able to invoke the JMX bean to get/set logging levels. This works just fine on one single server. However, my application is deployed on a cluster of two servers. When invoking the JMXConfigurator, it only modifies the logging configuration on the particular server that I happened to connect to for that http request, but does not modify the configuration on the other clustered server. Am I missing something, or is there no way to have one JMX call update the logback configuration on all clustered servers? Am I perhaps retrieving the JMX bean incorrectly for a clustered environment? Any help would be greatly appreciated. Here is the client code I am using to access the JMX bean: String contextName = "myContextName"; String objectNameStr = ch.qos.logback.classic.jmx.MBeanUtil.getObjectNameFor(contextName, JMXConfigurator.class); javax.management.ObjectName objectName = new javax.management.ObjectName(objectNameStr); javax.management.MBeanServer mbs = java.lang.management.ManagementFactory.getPlatformMBeanServer(); mbean = javax.management.JMX.newMBeanProxy(mbs, objectName, JMXConfiguratorMBean.class, true); mbean.setLoggerLevel("myLogger", "debug"); Thanks, -Chris *************************** IMPORTANT NOTE*****************************-- The opinions expressed in this message and/or any attachments are those of the author and not necessarily those of Brown Brothers Harriman & Co., its subsidiaries and affiliates ("BBH"). There is no guarantee that this message is either private or confidential, and it may have been altered by unauthorized sources without your or our knowledge. Nothing in the message is capable or intended to create any legally binding obligations on either party and it is not intended to provide legal advice. BBH accepts no responsibility for loss or damage from its use, including damage from virus. ******************************************************************************** _______________________________________________ Logback-user mailing list Logback-user@qos.ch http://mailman.qos.ch/mailman/listinfo/logback-user

Chris, Would sharing the configuration file by all instances be a possibility? If yes, you could probably get by with the auto-scan feature. -- Ceki http://twitter.com/#!/ceki On 30.05.2012 20:50, Christopher.White@bbh.com wrote:
Hi,
I'm trying to use Logback JMX in my application to allow me to change the configuration at runtime.
I've created client code that can retrieve the JMX bean, and am able to invoke the JMX bean to get/set logging levels.
This works just fine on one single server. However, my application is deployed on a cluster of two servers. When invoking the JMXConfigurator, it only modifies the logging configuration on the particular server that I happened to connect to for that http request, but does not modify the configuration on the other clustered server.
Am I missing something, or is there no way to have one JMX call update the logback configuration on all clustered servers? Am I perhaps retrieving the JMX bean incorrectly for a clustered environment? Any help would be greatly appreciated.
Here is the client code I am using to access the JMX bean:
String contextName = "myContextName"; String objectNameStr = ch.qos.logback.classic.jmx.MBeanUtil.getObjectNameFor(contextName, JMXConfigurator.class); javax.management.ObjectName objectName = new javax.management.ObjectName(objectNameStr); javax.management.MBeanServer mbs = java.lang.management.ManagementFactory.getPlatformMBeanServer(); mbean = javax.management.JMX.newMBeanProxy(mbs, objectName, JMXConfiguratorMBean.class, true); mbean.setLoggerLevel("myLogger", "debug");
Thanks, -Chris

Thank you for the reply. When you say "sharing the configuration file by all instances", do you mean having both servers point to the same logback.xml config file? If this is what you meant, I'm not exactly sure how I could use this to my advantage, perhaps you could elaborate more on this suggestion. My ultimate goal is to give the end user of my web application (with an admin role) the ability to change the logging level of any logger at runtime (and have this change applied to both servers in my cluster). Is it possible, in java code, to modify the logging level of a logger, and then save the modifications back to the original logback.xml configuration file? If this is possible, then I can see how your suggestion could help me... 1. End user submits request for change in logging level on some logger (which is received by server 1) 2. Application code uses Logback API to make the desired changes at runtime 3. Application code uses Logback API to save the current runtiime configuration back to logback.xml (still on server 1) 4. Server 2 is also looking at the same logback.xml file (with auto-scan enabled). Once the file is updated, the auto-scan will trigger on server 2, and the logging level changes will then be applied to server 2 as well. Before I go too far with the above approach, I just have a follow-up question to using JMX. Here is the code snippet that I am using to get the mbean proxy instance: mbean = javax.management.JMX.newMBeanProxy(mbs, objectName, JMXConfiguratorMBean.class, true); The last parameter is set to "true", which is supposed to enable broadcasting of the message (to other Mbeans on the MbeanServer I assume) if the Mbean happens to implement NotificationBroadcaster. Based upon some reading on other forums, I think this is how JMX can be used to propagate the message to all servers in the cluster. Here is the excerpt from the Javadoc: This method behaves the same as newMBeanProxy(MBeanServerConnection, ObjectName, Class), but additionally, if notificationBroadcaster is true, then the MBean is assumed to be a NotificationBroadcaster or NotificationEmitter and the returned proxy will implement NotificationEmitter as well as interfaceClass. A call to NotificationBroadcaster.addNotificationListener(javax.management.NotificationListener, javax.management.NotificationFilter, java.lang.Object) on the proxy will result in a call to MBeanServerConnection.addNotificationListener(ObjectName, NotificationListener, NotificationFilter, Object), and likewise for the other methods of NotificationBroadcaster and NotificationEmitter. Type Parameters: T - allows the compiler to know that if the interfaceClass parameter is MyMBean.class, for example, then the return type is MyMBean. Parameters: connection - the MBean server to forward to. objectName - the name of the MBean within connection to forward to. interfaceClass - the management interface that the MBean exports, which will also be implemented by the returned proxy. notificationBroadcaster - make the returned proxy implement NotificationEmitter by forwarding its methods via connection. Returns: the new proxy instance. Does the Logback JMX Mbean implement NotificationEmitter or NotificationBroadcaster? If not, do you think that if it did implement one of these interfaces, that my issue would be resolved? Thanks, -Chris From: ceki <ceki@qos.ch> To: logback users list <logback-user@qos.ch> Date: 05/30/2012 03:39 PM Subject: Re: [logback-user] JMX on a WebSphere clustered environment Sent by: logback-user-bounces@qos.ch Chris, Would sharing the configuration file by all instances be a possibility? If yes, you could probably get by with the auto-scan feature. -- Ceki http://twitter.com/#!/ceki On 30.05.2012 20:50, Christopher.White@bbh.com wrote:
Hi,
I'm trying to use Logback JMX in my application to allow me to change the configuration at runtime.
I've created client code that can retrieve the JMX bean, and am able to invoke the JMX bean to get/set logging levels.
This works just fine on one single server. However, my application is deployed on a cluster of two servers. When invoking the JMXConfigurator, it only modifies the logging configuration on the particular server that I happened to connect to for that http request, but does not modify the configuration on the other clustered server.
Am I missing something, or is there no way to have one JMX call update the logback configuration on all clustered servers? Am I perhaps retrieving the JMX bean incorrectly for a clustered environment? Any help would be greatly appreciated.
Here is the client code I am using to access the JMX bean:
String contextName = "myContextName"; String objectNameStr = ch.qos.logback.classic.jmx.MBeanUtil.getObjectNameFor(contextName, JMXConfigurator.class); javax.management.ObjectName objectName = new javax.management.ObjectName(objectNameStr); javax.management.MBeanServer mbs = java.lang.management.ManagementFactory.getPlatformMBeanServer(); mbean = javax.management.JMX.newMBeanProxy(mbs, objectName, JMXConfiguratorMBean.class, true); mbean.setLoggerLevel("myLogger", "debug");
Thanks, -Chris
_______________________________________________ Logback-user mailing list Logback-user@qos.ch http://mailman.qos.ch/mailman/listinfo/logback-user *************************** IMPORTANT NOTE*****************************-- The opinions expressed in this message and/or any attachments are those of the author and not necessarily those of Brown Brothers Harriman & Co., its subsidiaries and affiliates ("BBH"). There is no guarantee that this message is either private or confidential, and it may have been altered by unauthorized sources without your or our knowledge. Nothing in the message is capable or intended to create any legally binding obligations on either party and it is not intended to provide legal advice. BBH accepts no responsibility for loss or damage from its use, including damage from virus. ********************************************************************************

Chris, Since you are using websphere you could use the Dynamic cache to push the logging levels around to all the servers in the cluster. You would need to implement a LoggerContextListener to update the Dynamic cache when a log level changes. Something like this: public class LogbackContextListener implements LoggerContextListener { private static final String LOG_ID = "LBLOG:"; public void onLevelChange(Logger logger, Level level) { if (DynamicCacheAccessor.isCachingEnabled()) { DistributedMap map = DynamicCacheAccessor.getDistributedMap(); map.put(LOG_ID + logger.getName(), level,1,60,60,EntryInfo.SHARED_PUSH, null); //Update dynamic cache and push to other servers } } and a Dynamic Cache ChangeListener, something like this: public class LogbackCacheChangeListener implements ChangeListener { public void cacheEntryChanged(ChangeEvent changeEvent) { if (ChangeEvent.LOCAL != changeEvent.getSourceOfChance()) { //Level not changed on this server then nothing to do if (changeEvent.getId().toString().startswith(LogbackContextListener.LOG_ID)) { //Log level changed in cache? LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); String loggerName = changeEvent.getId().toString().substring(LogbackContextListener.LOG_ID.length()); Logger logger = lc.getLogger(loggerName); logger.setLevel((Level)changeEvent.getValue()); //set logger level on server to what was pushed in cache. } } } Sorry for any typos... Roy On Wed, May 30, 2012 at 5:00 PM, <Christopher.White@bbh.com> wrote:
Thank you for the reply.
When you say "sharing the configuration file by all instances", do you mean having both servers point to the same logback.xml config file? If this is what you meant, I'm not exactly sure how I could use this to my advantage, perhaps you could elaborate more on this suggestion.
My ultimate goal is to give the end user of my web application (with an admin role) the ability to change the logging level of any logger at runtime (and have this change applied to both servers in my cluster).
Is it possible, in java code, to modify the logging level of a logger, and then save the modifications back to the original logback.xml configuration file? If this is possible, then I can see how your suggestion could help me... 1. End user submits request for change in logging level on some logger (which is received by server 1) 2. Application code uses Logback API to make the desired changes at runtime 3. Application code uses Logback API to save the current runtiime configuration back to logback.xml (still on server 1) 4. Server 2 is also looking at the same logback.xml file (with auto-scan enabled). Once the file is updated, the auto-scan will trigger on server 2, and the logging level changes will then be applied to server 2 as well.
Before I go too far with the above approach, I just have a follow-up question to using JMX. Here is the code snippet that I am using to get the mbean proxy instance:
mbean = javax.management.JMX.newMBeanProxy(mbs, objectName, JMXConfiguratorMBean.class, true);
The last parameter is set to "true", which is supposed to enable broadcasting of the message (to other Mbeans on the MbeanServer I assume) if the Mbean happens to implement NotificationBroadcaster. Based upon some reading on other forums, I think this is how JMX can be used to propagate the message to all servers in the cluster.
Here is the excerpt from the Javadoc:
This method behaves the same as newMBeanProxy(MBeanServerConnection, ObjectName, Class), but additionally, if notificationBroadcaster is true, then the MBean is assumed to be a NotificationBroadcaster or NotificationEmitter and the returned proxy will implement NotificationEmitter as well as interfaceClass. A call to NotificationBroadcaster.addNotificationListener(javax.management.NotificationListener, javax.management.NotificationFilter, java.lang.Object) on the proxy will result in a call to MBeanServerConnection.addNotificationListener(ObjectName, NotificationListener, NotificationFilter, Object), and likewise for the other methods of NotificationBroadcaster and NotificationEmitter. Type Parameters: T - allows the compiler to know that if the interfaceClass parameter is MyMBean.class, for example, then the return type is MyMBean. Parameters: connection - the MBean server to forward to. objectName - the name of the MBean within connection to forward to. interfaceClass - the management interface that the MBean exports, which will also be implemented by the returned proxy. notificationBroadcaster - make the returned proxy implement NotificationEmitter by forwarding its methods via connection. Returns: the new proxy instance.
Does the Logback JMX Mbean implement NotificationEmitter or NotificationBroadcaster? If not, do you think that if it did implement one of these interfaces, that my issue would be resolved?
Thanks, -Chris
From: ceki <ceki@qos.ch>
To: logback users list <logback-user@qos.ch> Date: 05/30/2012 03:39 PM Subject: Re: [logback-user] JMX on a WebSphere clustered environment Sent by: logback-user-bounces@qos.ch ________________________________
Chris,
Would sharing the configuration file by all instances be a possibility? If yes, you could probably get by with the auto-scan feature.
-- Ceki http://twitter.com/#!/ceki
On 30.05.2012 20:50, Christopher.White@bbh.com wrote:
Hi,
I'm trying to use Logback JMX in my application to allow me to change the configuration at runtime.
I've created client code that can retrieve the JMX bean, and am able to invoke the JMX bean to get/set logging levels.
This works just fine on one single server. However, my application is deployed on a cluster of two servers. When invoking the JMXConfigurator, it only modifies the logging configuration on the particular server that I happened to connect to for that http request, but does not modify the configuration on the other clustered server.
Am I missing something, or is there no way to have one JMX call update the logback configuration on all clustered servers? Am I perhaps retrieving the JMX bean incorrectly for a clustered environment? Any help would be greatly appreciated.
Here is the client code I am using to access the JMX bean:
String contextName = "myContextName"; String objectNameStr = ch.qos.logback.classic.jmx.MBeanUtil.getObjectNameFor(contextName, JMXConfigurator.class); javax.management.ObjectName objectName = new javax.management.ObjectName(objectNameStr); javax.management.MBeanServer mbs = java.lang.management.ManagementFactory.getPlatformMBeanServer(); mbean = javax.management.JMX.newMBeanProxy(mbs, objectName, JMXConfiguratorMBean.class, true); mbean.setLoggerLevel("myLogger", "debug");
Thanks, -Chris
_______________________________________________ Logback-user mailing list Logback-user@qos.ch http://mailman.qos.ch/mailman/listinfo/logback-user
*************************** IMPORTANT NOTE*****************************-- The opinions expressed in this message and/or any attachments are those of the author and not necessarily those of Brown Brothers Harriman & Co., its subsidiaries and affiliates ("BBH"). There is no guarantee that this message is either private or confidential, and it may have been altered by unauthorized sources without your or our knowledge. Nothing in the message is capable or intended to create any legally binding obligations on either party and it is not intended to provide legal advice. BBH accepts no responsibility for loss or damage from its use, including damage from virus. ********************************************************************************
_______________________________________________ Logback-user mailing list Logback-user@qos.ch http://mailman.qos.ch/mailman/listinfo/logback-user

Roy's idea of using LoggerContextListener in conjunction with websphere's DynamicCache makes sense as well. On 31.05.2012 01:36, Roy Cronise wrote:
Chris, Since you are using websphere you could use the Dynamic cache to push the logging levels around to all the servers in the cluster.
You would need to implement a LoggerContextListener to update the Dynamic cache when a log level changes. Something like this:
public class LogbackContextListener implements LoggerContextListener { private static final String LOG_ID = "LBLOG:"; public void onLevelChange(Logger logger, Level level) { if (DynamicCacheAccessor.isCachingEnabled()) { DistributedMap map = DynamicCacheAccessor.getDistributedMap(); map.put(LOG_ID + logger.getName(), level,1,60,60,EntryInfo.SHARED_PUSH, null); //Update dynamic cache and push to other servers } }
and a Dynamic Cache ChangeListener, something like this:
public class LogbackCacheChangeListener implements ChangeListener { public void cacheEntryChanged(ChangeEvent changeEvent) { if (ChangeEvent.LOCAL != changeEvent.getSourceOfChance()) { //Level not changed on this server then nothing to do if (changeEvent.getId().toString().startswith(LogbackContextListener.LOG_ID)) { //Log level changed in cache? LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); String loggerName = changeEvent.getId().toString().substring(LogbackContextListener.LOG_ID.length()); Logger logger = lc.getLogger(loggerName); logger.setLevel((Level)changeEvent.getValue()); //set logger level on server to what was pushed in cache. } } }
Sorry for any typos...
Roy
-- Ceki http://twitter.com/#!/ceki

On 30.05.2012 23:00, Christopher.White@bbh.com wrote:
Thank you for the reply.
When you say "sharing the configuration file by all instances", do you mean having both servers point to the same logback.xml config file? If this is what you meant, I'm not exactly sure how I could use this to my advantage, perhaps you could elaborate more on this suggestion.
Any change to that file would be automatically picked up by all instances. The only downside is that it would require editing by the admin. If the admin makes an error editing so that the resulting XML file is not well-formed, logback would fallback to the previous well-formed config.
My ultimate goal is to give the end user of my web application (with an admin role) the ability to change the logging level of any logger at runtime (and have this change applied to both servers in my cluster).
OK.
Is it possible, in java code, to modify the logging level of a logger, and then save the modifications back to the original logback.xml configuration file? If this is possible, then I can see how your suggestion could help me...
No, there is no support for editing the config file at runtime. However, the config separation idea could work (read below).
1. End user submits request for change in logging level on some logger (which is received by server 1) 2. Application code uses Logback API to make the desired changes at runtime 3. Application code uses Logback API to save the current runtiime configuration back to logback.xml (still on server 1)
You could separate appender configuration and logger level configuration into separate files [1]. The main file would define appenders and would include the logger level file which you could maintain programmatically (just dump the logger level settings to the logger level config file upon change). [1] http://logback.qos.ch/manual/configuration.html#fileInclusion
4. Server 2 is also looking at the same logback.xml file (with auto-scan enabled). Once the file is updated, the auto-scan will trigger on server 2, and the logging level changes will then be applied to server 2 as well.
Right. Auto-scan works over included files as well.
Before I go too far with the above approach, I just have a follow-up question to using JMX. Here is the code snippet that I am using to get the mbean proxy instance:
mbean = javax.management.JMX.newMBeanProxy(mbs, objectName, JMXConfiguratorMBean.class, true);
The last parameter is set to "true", which is supposed to enable broadcasting of the message (to other Mbeans on the MbeanServer I assume) if the Mbean happens to implement NotificationBroadcaster. Based upon some reading on other forums, I think this is how JMX can be used to propagate the message to all servers in the cluster.
Here is the excerpt from the Javadoc:
[snip]
Does the Logback JMX Mbean implement NotificationEmitter or NotificationBroadcaster? If not, do you think that if it did implement one of these interfaces, that my issue would be resolved?
I barely understand what you are talking about so I am unable to help.
Thanks, -Chris -- Ceki http://twitter.com/#!/ceki

On 31.05.2012 13:07, ceki wrote:
You could separate appender configuration and logger level configuration into separate files [1]. The main file would define appenders and would include the logger level file which you could maintain programmatically (just dump the logger level settings to the logger level config file upon change).
When the user makes a level change using the UI you provide, make the level change programmatically and then dump the current logger state into the config file reserved for setting logger levels. The other instances will pickup the change in the included config file (reserved for setting logger levels). Dumping the current state should be as easy as iterating over all the loggers and then writing XML elements such as <logger name="a" level="INFO"/> I'd be happy to help if you wish to go along this route. -- Ceki http://twitter.com/#!/ceki

Thank you for these great ideas! I will take a look at both of these options in more detail. I'm not a fan of tying myself to WebSphere, but I do like the idea of using a common cache mechanism over making manual modifications to an xml file (and having to make sure that the single xml file is available to both servers...which would require a significant change to how our applications are packaged and deployed). I think I am also going to investigate the possibility of creating an external application that will allow me to connect to any remote JMX MBeanServer and change the logging as needed. The user will have to provide the connection information, but will be ok as long as they can access any server they want from this single application (providing our company's infrastructure will allow and support this). Thanks, Christopher White Sr. Programmer 1-617-772-2403 Christopher.White@bbh.com From: ceki <ceki@qos.ch> To: logback users list <logback-user@qos.ch> Date: 05/31/2012 07:16 AM Subject: Re: [logback-user] JMX on a WebSphere clustered environment Sent by: logback-user-bounces@qos.ch On 31.05.2012 13:07, ceki wrote:
You could separate appender configuration and logger level configuration into separate files [1]. The main file would define appenders and would include the logger level file which you could maintain programmatically (just dump the logger level settings to the logger level config file upon change).
When the user makes a level change using the UI you provide, make the level change programmatically and then dump the current logger state into the config file reserved for setting logger levels. The other instances will pickup the change in the included config file (reserved for setting logger levels). Dumping the current state should be as easy as iterating over all the loggers and then writing XML elements such as <logger name="a" level="INFO"/> I'd be happy to help if you wish to go along this route. -- Ceki http://twitter.com/#!/ceki _______________________________________________ Logback-user mailing list Logback-user@qos.ch http://mailman.qos.ch/mailman/listinfo/logback-user *************************** IMPORTANT NOTE*****************************-- The opinions expressed in this message and/or any attachments are those of the author and not necessarily those of Brown Brothers Harriman & Co., its subsidiaries and affiliates ("BBH"). There is no guarantee that this message is either private or confidential, and it may have been altered by unauthorized sources without your or our knowledge. Nothing in the message is capable or intended to create any legally binding obligations on either party and it is not intended to provide legal advice. BBH accepts no responsibility for loss or damage from its use, including damage from virus. ********************************************************************************
participants (4)
-
Alex Glass
-
ceki
-
Christopher.White@bbh.com
-
Roy Cronise