How do you dynamically change the log4j level
One of the common feature requested in most production application is to reload of log4j properties or lo4j xml file at runtime without retstarting of tomcat. Very helpful when you are debugging production level issues and would only like to turn on logging for a short period of time but also do not want any downtime.
I will show you a brief example on how to dynamically change the log4j level on a Tomcat server. This is a programmatic change
Set up includes
1. Jdk 1.7 and above2.
2. Apache-tomcat-7.0.57
3. Assumption your application is running on spring framework (I am on 3.2.2)
This is my java file. This configurer file is required to reload the updated settings.
public class OptionalLog4jConfigurer extends Log4jConfigurer implements InitializingBean { public static final Long DEFAULT_REFRESH = 30000L; private static final Log LOG = LogFactory .getLog(OptionalLog4jConfigurer.class); private String configLocation; private Long refreshInterval; public OptionalLog4jConfigurer(final String configLocation, final Long refreshInterval) { this.configLocation = configLocation; if (refreshInterval == null) { this.refreshInterval = DEFAULT_REFRESH; } else { this.refreshInterval = refreshInterval; } } /** * Will only customize if a configLocation has been specified. * * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() */ public void afterPropertiesSet() throws Exception { if (!StringUtils.isEmpty(this.configLocation)) { LOG.info("Log4J configuration is being customized."); this.initLoggingInternal(); } else { LOG .info("Using default Log4J configuration. No customization requested"); } } public String getConfigLocation() { return this.configLocation; } public Long getRefreshInterval() { return this.refreshInterval; } }
Changes to application-Context.xml
<bean id="optionalLog4jInitialization" class="com.skg.jetm.OptionalLog4jConfigurer"> <constructor-arg index="0" type="java.lang.String" value="${log4j.configuration}" /> <constructor-arg index="1" type="java.lang.Long" value="100" /> </bean>
${log4j.configuration} is the path to your log4j file.
For local testing on my eclipse, I passed this value in jdk environment variables
-Dlog4j.configuration=file:\C:\Myfolder\log4j.properties -Dlog4j.debug
When running with tomcat, you need to set up this in tomcat configuration
APPLICATION_OPTS="-Dlog4j.configuration=file:/C:/Myfolder/log4j.properties \ -Dlog4j.debug=true"
When I start tomcat, the messages will be displayed as below
INFO: Deploying web application archive C:\devsoftware\apache-tomcat-7.0.57\webapps\myweb-0.0.1-SNAPSHOT.war log4j: Using URL [file:/C:/apps44/log4j.properties] for automatic log4j configuration. log4j: Reading configuration from URL file:/C:/apps44/log4j.properties log4j: Parsing for [root] with value=[error, stdout]. log4j: Level token is [error]. log4j: Category root set to ERROR log4j: Parsing appender named "stdout". log4j: Parsing layout options for "stdout". log4j: End of parsing for "stdout". log4j: Setting property [target] to [System.out]. log4j: Parsed "stdout" options. log4j: Parsing for [com.skg] with value=[info]. log4j: Level token is [info]. log4j: Category com.skg set to INFO log4j: Handling log4j.additivity.com.skg=[null] log4j: Parsing for [com.crunchtime.util] with value=[error]. log4j: Level token is [error]. log4j: Category com.crunchtime.util set to ERROR log4j: Handling log4j.additivity.com.crunchtime.util=[null] log4j: Parsing for [org.springframework.web.context.ContextLoader] with value=[error]. log4j: Level token is [error]. log4j: Category org.springframework.web.context.ContextLoader set to ERROR log4j: Handling log4j.additivity.org.springframework.web.context.ContextLoader=[null] log4j: Finished configuring. Feb 23, 2015 10:18:25 AM org.apache.catalina.startup.HostConfig deployWAR INFO: Deployment of web application archive C:\devsoftware\apache-tomcat-7.0.57\webapps\myweb-0.0.1-SNAPSHOT.war has finished in 2,434 ms
Change any settings in log4j file and you should see the context reload in tomcat server console
log4j: Parsing for [root] with value=[info, stdout]. log4j: Level token is [info]. log4j: Category root set to INFO log4j: Parsing appender named "stdout". log4j: Parsing layout options for "stdout". log4j: End of parsing for "stdout". log4j: Setting property [target] to [System.out]. log4j: Parsed "stdout" options. log4j: Parsing for [com.skg] with value=[error]. log4j: Level token is [error]. log4j: Category com.skg set to ERROR log4j: Handling log4j.additivity.com.skg=[null] log4j: Parsing for [com.crunchtime.util] with value=[error]. log4j: Level token is [error]. log4j: Category com.crunchtime.util set to ERROR log4j: Handling log4j.additivity.com.crunchtime.util=[null] log4j: Parsing for [org.springframework.web.context.ContextLoader] with value=[error]. log4j: Level token is [error]. log4j: Category org.springframework.web.context.ContextLoader set to ERROR log4j: Handling log4j.additivity.org.springframework.web.context.ContextLoader=[null] log4j: Finished configuring.
Project at Github : Coming soon
Thx for the nice example.
Where is the implmentation of initLoggingInternal()?
What do you do in there?