Log4j, configuring a Web App to use a relative path

Solution 1:

Tomcat sets a catalina.home system property. You can use this in your log4j properties file. Something like this:

log4j.rootCategory=DEBUG,errorfile

log4j.appender.errorfile.File=${catalina.home}/logs/LogFilename.log

On Debian (including Ubuntu), ${catalina.home} will not work because that points at /usr/share/tomcat6 which has no link to /var/log/tomcat6. Here just use ${catalina.base}.

If your using another container, try to find a similar system property, or define your own. Setting the system property will vary by platform, and container. But for Tomcat on Linux/Unix I would create a setenv.sh in the CATALINA_HOME/bin directory. It would contain:

export JAVA_OPTS="-Dcustom.logging.root=/var/log/webapps"

Then your log4j.properties would be:

log4j.rootCategory=DEBUG,errorfile

log4j.appender.errorfile.File=${custom.logging.root}/LogFilename.log

Solution 2:

I've finally done it in this way.

Added a ServletContextListener that does the following:

public void contextInitialized(ServletContextEvent event) {
    ServletContext context = event.getServletContext();
    System.setProperty("rootPath", context.getRealPath("/"));
}

Then in the log4j.properties file:

log4j.appender.file.File=${rootPath}WEB-INF/logs/MyLog.log

By doing it in this way Log4j will write into the right folder as long as you don't use it before the "rootPath" system property has been set. This means that you cannot use it from the ServletContextListener itself but you should be able to use it from anywhere else in the app.

It should work on every web container and OS as it's not dependent on a container specific system property and it's not affected by OS specific path issues. Tested with Tomcat and Orion web containers and on Windows and Linux and it works fine so far.

What do you think?

Solution 3:

If you use Spring you can:

1) create a log4j configuration file, e.g. "/WEB-INF/classes/log4j-myapp.properties" DO NOT name it "log4j.properties"

Example:

log4j.rootLogger=ERROR, stdout, rollingFile

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n

log4j.appender.rollingFile=org.apache.log4j.RollingFileAppender
log4j.appender.rollingFile.File=${myWebapp-instance-root}/WEB-INF/logs/application.log
log4j.appender.rollingFile.MaxFileSize=512KB
log4j.appender.rollingFile.MaxBackupIndex=10
log4j.appender.rollingFile.layout=org.apache.log4j.PatternLayout
log4j.appender.rollingFile.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.rollingFile.Encoding=UTF-8

We'll define "myWebapp-instance-root" later on point (3)

2) Specify config location in web.xml:

<context-param>
  <param-name>log4jConfigLocation</param-name>
  <param-value>/WEB-INF/classes/log4j-myapp.properties</param-value>
</context-param>

3) Specify a unique variable name for your webapp's root, e.g. "myWebapp-instance-root"

<context-param>
  <param-name>webAppRootKey</param-name>
  <param-value>myWebapp-instance-root</param-value>
</context-param>

4) Add a Log4jConfigListener:

<listener>
  <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

If you choose a different name, remember to change it in log4j-myapp.properties, too.

See my article (Italian only... but it should be understandable): http://www.megadix.it/content/configurare-path-relativi-log4j-utilizzando-spring

UPDATE (2009/08/01) I've translated my article to English: http://www.megadix.it/node/136