If you always want to stay on top of your production system and always want to know whats going on in your APP, you would want to configure JMX for your application.
First you need to start your JVM with the following parameters to enable any JMX client to connect to your system.
-Dcom.sun.management.jmxremote.port=8888 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
This is just done without any security but in production, you would want to add authentication.
Now, add these configuration for your spring APP to automatically expose your Spring Beans as MBeans if they have the right annotations.
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false"> <property name="autodetect" value="true"></property> <property name="namingStrategy" ref="namingStrategy"></property> <property name="assembler" ref="assembler"></property> <property name="server" ref="mbeanServer"></property> </bean> <bean id="assembler" class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler"> <property name="attributeSource" ref="attributeSource" /> </bean> <bean id="namingStrategy" class="org.springframework.jmx.export.naming.MetadataNamingStrategy"> <property name="attributeSource" ref="attributeSource" /> </bean> <bean id="mbeanServer" class="java.lang.management.ManagementFactory" factory-method="getPlatformMBeanServer"/>
The ‘exporter’ will inspect all your defined Spring Beans in your configuration and see if the have Spring JMX annotations. Now you need to define your beans with Annotations.
@ManagedResource(objectName = "yourapp:name=log4jLevelChanger", description = "LOG4j Level Changer") public class Log4jLevelChanger { private static final Log log = LogFactory.getLog(Log4jLevelChanger.class); public void init() throws AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException { ArrayList<MBeanServer> servers = MBeanServerFactory.findMBeanServer(null); for(MBeanServer server : servers) { String name = (String) server.getAttribute(MBeanServerDelegate.DELEGATE_NAME, "MBeanServerId"); log.info("found server: " + name); } } /* * (non-Javadoc) * * @see * com.vantage.callcenter.web.utils.Log4jLevelChanger#setLogLevel(java.lang * .String, java.lang.String) */ @ManagedOperation @ManagedOperationParameters({ @ManagedOperationParameter(description="Name of the Logger to configure", name="loggerName"), @ManagedOperationParameter(description="Level ofthe Logger to set", name="level") }) public void setLogLevel( String loggerName, String level) { if ("debug".equalsIgnoreCase(level)) { Logger.getLogger(loggerName).setLevel(Level.DEBUG); } else if ("info".equalsIgnoreCase(level)) { Logger.getLogger(loggerName).setLevel(Level.INFO); } else if ("error".equalsIgnoreCase(level)) { Logger.getLogger(loggerName).setLevel(Level.ERROR); } else if ("fatal".equalsIgnoreCase(level)) { Logger.getLogger(loggerName).setLevel(Level.FATAL); } else if ("warn".equalsIgnoreCase(level)) { Logger.getLogger(loggerName).setLevel(Level.WARN); } } //Read the log4j.properties to reconfigure the logging levels. @ManagedOperation public boolean refreshLogging() { try { Log4jConfigurer.initLogging("classpath:log4j.properties"); return true; } catch (FileNotFoundException e) { return false; } } @ManagedOperation @ManagedOperationParameters ({ @ManagedOperationParameter(description="Name of the Logger to get the Level", name="loggerName") }) public String getLogLevel( String loggerName) { log.debug("getLogLevel -> loggerName: " + loggerName); Logger logger = Logger.getLogger(loggerName); if(logger != null) { if(logger.getLevel() != null) { return logger.getLevel().toString(); } } return Logger.getRootLogger().getLevel().toString(); } }
and define it in your application-context.xml as a regular bean
<bean id="log4jLevelChanger" class="com.test.Log4jLevelChanger"></bean>
Thats it! Now you can open any Standard JMX client (JConsole / VisualVM / JManage) to inspect the bean and changing log levels!
You can also add Mbean Annotations to any regular Bean that you wish to inspect at runtime. For example, you can add it to the bean that manages your threadpool to see its utilization at runtime, you can add it to any in memory cache to find out memory leaks. If you think closely, the possibilities can be endless!