PROBLEM
Most of the time, we set the Log4j’s log levels to something lower (debug
or info
) during our local development. Once it is ready for production, we normally set the Log4j’s log levels to something higher (warn
or even error
) to prevent meaningless information from flooding the server log.
One way to do this is to manually adjust the log level(s) in log4.xml
during our local development, for example:-
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration> <!-- This appender logs to the console --> <appender name="consoleAppender" class="org.apache.log4j.ConsoleAppender"> <param name="Target" value="System.out"/> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="[%-5p] [%c{1}] [%M:%L] - %m%n"/> </layout> </appender> <!-- Set "debug" log level for project code --> <logger name="com.choonchernlim.myproject"> <level value="debug"/> </logger> <!-- Set "info" log level for Spring framework --> <logger name="org.springframework"> <level value="info"/> </logger> <!-- Set "debug" log level for Hibernate framework --> <logger name="org.hibernate"> <level value="debug"/> </logger> <root> <!-- The default log level is "warn" --> <priority value="warn"/> <appender-ref ref="consoleAppender"/> </root> </log4j:configuration>
Once we are ready for production, we will manually change the package specific log levels back to warn
or comment them out, for example:-
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration> <!-- this appender logs to the console --> <appender name="consoleAppender" class="org.apache.log4j.ConsoleAppender"> <param name="Target" value="System.out"/> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="[%-5p] [%c{1}] [%M:%L] - %m%n"/> </layout> </appender> <!-- Comment out package specific log levels <logger name="com.choonchernlim.myproject"> <level value="debug"/> </logger> <logger name="org.springframework"> <level value="info"/> </logger> <logger name="org.hibernate"> <level value="debug"/> </logger> --> <root> <!-- The default log level is "warn" --> <priority value="warn"/> <appender-ref ref="consoleAppender"/> </root> </log4j:configuration>
The problem with this approach is I always forget to make necessary changes in log4j.xml
when I’m ready to package my project to be deployed in production.
SOLUTION
The solution that I come up with is rather simple. We will have two Log4j XML files under src/main/resources
:-
log4j.xml
log4j-dev.xml
By default, assuming there’s no further Log4j configuration, log4j.xml
will always get picked up by Log4j due to the default filename and its location. log4j-dev.xml
will always be ignored by Log4j.
To ensure our local development picks up the configuration from log4j-dev.xml
, we will need to make a minor tweak to the Jetty configuration in pom.xml
:-
<project ...> ... <build> <plugins> <plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>8.1.8.v20121106</version> <configuration> <systemProperties> <!-- When Jetty runs, "log4j-dev.xml" will be used instead of "log4j.xml" because the latter is reserved for production usage. --> <systemProperty> <name>log4j.configuration</name> <value>log4j-dev.xml</value> </systemProperty> </systemProperties> ... </configuration> <dependencies> ... </dependencies> </plugin> </plugins> </build> </project>
This way, when we run our local development on Jetty, log4j-dev.xml
will be used. When we deploy the project in production, log4j.xml
will be used instead.
Thanks! Great solution.. bang on!
But everytime, when you release you have to comment the pom file this time.
one more simple solution. for example have log4j_dev.properties and log4j_prod.properties then when run your app specify which one you want e.g. -Dlog4j.configuration=log4j_dev.properties