Log4j, setting up a web application to use a relative path

I have java webapp that needs to be deployed on Win or Linux machines. Now I want to add log4j for logging, and I would like to use the relative path for the log file, since I do not want to change the file path with every deployment. The container will most likely be Tomcat, but not necessarily.

What is the best way to do this?

+75
java web-applications log4j
Oct 19 '08 at 18:32
source share
10 answers

I finally did it this way.

Added ServletContextListener, which performs the following actions:

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 

Thus, Log4j will be written to the desired folder until you use it before the system property "rootPath" is set. This means that you cannot use it from the ServletContextListener itself, but you must use it from anywhere in the application.

It should work on every web container and OS, since it does not depend on the container-specific system property and does not depend on specific problems associated with the OS. Tested with Tomcat and Orion web containers, as well as on Windows and Linux, and so far it works fine.

What do you think?

+52
Oct 20 '08 at 10:52
source share

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

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

On Debian (including Ubuntu) ${catalina.home} will not work because it points to / usr / share / tomcat 6, which does not have a link to / var / log / tomcat 6. Here just use ${catalina.base} .

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

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

Then your log4j.properties will be:

 log4j.rootCategory=DEBUG,errorfile log4j.appender.errorfile.File=${custom.logging.root}/LogFilename.log 
+97
Oct 19 '08 at 18:58
source share

If you use Spring, you can:

1) create a log4j configuration file, for example. "/WEB-INF/classes/log4j-myapp.properties" Do not call 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 will define "myWebapp-instance-root" later at (3)

2) Specify the configuration location in web.xml:

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

3) Provide a variable name unique to your webapp root, for example. "MyWebapp-instance-root"

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

4) Add Log4jConfigListener:

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

If you choose a different name, be sure to also change it in log4j-myapp.properties.

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

UPDATE (2009/08/01) I translated the article into English: http://www.megadix.it/node/136

+14
Nov 26 '08 at 11:40
source share

Just a comment on the Iker decision .

ServletContext is a good solution for your problem. But I do not think this is good for maintenance. Large time log files must be kept for a long time.

Since ServletContext makes the file under the expanded file, it will be deleted when the server is redistributed. I suggest going with the parent folder rootPath instead of the child one.

+6
Jan 05 '10 at 22:44
source share

Is log4j the application root directory working if you did not specify the root directory in the FileAppender path property? Therefore, you should simply use:

log4j.appender.file.File = logs /MyLog.log

It has been a while since I did Java web development, but it seems the most intuitive and also does not come across other, unfortunately, log names written to the $ {catalina.home} / logs directory.

+4
Oct 20 '08 at 15:20
source share

My suggestion is that the log file should always be logged above the root context of webApp, so if we redeploy webApp, we don’t want to redefine existing log files.

+1
Dec 25 '10 at 1:01
source share

If you are using Maven, I have a great solution for you:

  • Edit the pom.xml file to include the following lines:

     <profiles> <profile> <id>linux</id> <activation> <os> <family>unix</family> </os> </activation> <properties> <logDirectory>/var/log/tomcat6</logDirectory> </properties> </profile> <profile> <id>windows</id> <activation> <os> <family>windows</family> </os> </activation> <properties> <logDirectory>${catalina.home}/logs</logDirectory> </properties> </profile> </profiles> 

    Here you define the logDirectory property specifically for the OS family.

  • Use the already defined logDirectory property in the logDirectory file:

     log4j.appender.FILE=org.apache.log4j.RollingFileAppender log4j.appender.FILE.File=${logDirectory}/mylog.log log4j.appender.FILE.MaxFileSize=30MB log4j.appender.FILE.MaxBackupIndex=10 log4j.appender.FILE.layout=org.apache.log4j.PatternLayout log4j.appender.FILE.layout.ConversionPattern=%d{ISO8601} [%x] %-5p [%t] [%c{1}] %m%n 
  • What is it!

PS: I'm sure that this can be achieved with Ant, but, unfortunately, I have not enough experience.

+1
Apr 17 '13 at 18:55
source share

As an additional comment on https://stackoverflow.com/a/312932/2128 , this can break if the web application implicitly starts other ServletContextListener that can be called earlier and which are already trying to use log4j - in this case, the log4j configuration will be read and analyzed before the property that defines the root directory of the log is set => log files will be displayed somewhere below the current directory (the current directory when tomcat starts).

I could only think of the following solution to this problem: - rename the log4j.properties file (or logj4.xml) so that log4j will not automatically read. - In your context filter, after setting the property, call the DOM / PropertyConfigurator helper class to make sure your log4j is. {Xml, properties} read - Reset log4j configuration (IIRC - method for this)

This is a little brute force, but this is the only way to make it waterproof.

+1
Nov 19 '14 at 16:23
source share

My solution is similar to the Iker Jimenez solution, but instead of using System.setProperty(...) I use org.apache.log4j.PropertyConfigurator.configure(Properties) . To do this, I also need log4j to be unable to find its own configuration, and I load it manually (both points described in Wolfgang Liebich answer ).

This works for Jetty and Tomcat, is standalone or works from the IDE, requires zero configuration, allows you to put the logs of each application in their own folder, regardless of how many applications are inside the container ( problem with a solution based on System ). Thus, you can also place the log4j configuration file anywhere in the web application (for example, in one project we had all the configuration files inside WEB-INF/ ).

More details:

  • I have my properties in the log4j-no-autoload.properties file in the classpath (for example, in my Maven project initially in src/main/resources , it is packaged in WEB-INF/classes ),
  • It has an application file configured, for example:

     log4j.appender.MyAppFileAppender = org.apache.log4j.FileAppender log4j.appender.MyAppFileAppender.file = ${webAppRoot}/WEB-INF/logs/my-app.log ... 
  • And I have such a context listener (it is much shorter with the Java 7 syntax "try-with-resource"):

     @WebListener public class ContextListener implements ServletContextListener { @Override public void contextInitialized(final ServletContextEvent event) { Properties props = new Properties(); InputStream strm = ContextListener.class.getClassLoader() .getResourceAsStream("log4j-no-autoload.properties"); try { props.load(strm); } catch (IOException propsLoadIOE) { throw new Error("can't load logging config file", propsLoadIOE); } finally { try { strm.close(); } catch (IOException configCloseIOE) { throw new Error("error closing logging config file", configCloseIOE); } } props.put("webAppRoot", event.getServletContext().getRealPath("/")); PropertyConfigurator.configure(props); // from now on, I can use LoggerFactory.getLogger(...) } ... } 
0
Sep 03 '15 at 15:09
source share

You can specify the relative path to the log file using the working directory :

 appender.file.fileName = ${sys:user.dir}/log/application.log 

This is independent of the servlet container and does not require the user variable to be passed to the system environment.

0
Apr 17 '17 at 22:01
source share



All Articles