views:

2048

answers:

11

I am planning to implement logging into a web application that I am currently working on but I am struggling with some of the details. What is the best way to go about logging a Java web application?

Specifically;

  • Where does the configuration file go in .war package file?
  • Where do people log to, relative or absolute path flat file, or a database?
  • Does Log4J logging go directly into the application server log file automatically or is that something you have to set up? In this case I am using Tomcat, but I often use Jrun.
  • Any other gotchas I should be aware of for web application logging?

Currently I am using Log4J but I imagine that the best practices would apply universally to all logging implementations.

EDIT:
One addition to the questions up top.

  • Where do you initilize the log configuration?

In a traditional app, I do this at the entry point;

DOMConfigurator.configureAndWatch("log4j.xml");

What would the web application equivalent be?

+3  A: 

I place my configuration on the default package: src/

and log to files using the ${catalina.home} system property:

log4j.appender.???.file=${catalina.home}/logs/system.log
cherouvim
Ah, I am using windows and catalina.home doesn't seem be set as an environment variable on any of the machines I have tomcat on. Is that resolved by some mechanism internal to tomcat or do I just need to manually set it? Also where does catalina.home point to, the root tomcat folder?
James McMahon
Sorry, my mistake, it's not an env variable, but a system property that tomcat sets when it starts.
cherouvim
Go ahead and manually set it. There are actually 2 ways to install tomcat on windows. One goes through a standard windows install (and installs tomcat as a windows service), the other is just a plain old zip file. I don't think either approach updates any environment variables for you.
toolkit
@cherouvim, ah yes I remember there being some strange about it. Can you do me a favor and update your answer to correct the reference to the environment variable.
James McMahon
@nemo: of course. Right now I was trying to see how to do overstrike in SO
cherouvim
I could have sworn that I've seen the overstrike here, I have no idea how to do it however.
James McMahon
A: 
  • put the log4j in the container (server) and create proper appenders per application
  • relative to server path, but that depends on your needs
  • we use appenders which log to different files, depends on your needs, e.g. one file for hibernate info/statistics, one for application only, etc.
  • don't log to much, it slows the application down
Michael Lange
Putting the Log4j configuration in the container is an interesting idea. However in my particular work environment I could see that creating deployment issues.
James McMahon
this approach makes it possible to further decouple development and production logging needs, developer has his own server instance and can log what he wants, without the problem to "accidentally" check in and deploy the development log4j on a production machine
Michael Lange
@Michael Lange: You can do the same by having different configuration artifacts for dev, stageing, production. I prefer to have log4j in my application. Having it on the container makes it impossible for more than 1 applications to control the logging configuration.
cherouvim
depends on architecture, process modell and sheer amount of applications the server guys have to master, we have strictly separated between developer and maintenance (and more)
Michael Lange
+5  A: 

Where does the configuration file go in .war package file? Root of the classpath.

Where do people log to, relative or absolute path flat file, or a database? Depends on the need. It's always better to use relative paths. Databases are good if you implement another application which will fetch logs from it and send them using email/sms

Does Log4J logging go directly into the application server log file automatically or is that something you have to set up? In this case I am using Tomcat, but I often use Jrun. If you use Console appender, yes, it's going to be logged in your servlet container log file.

Any other gotchas I should be aware of for web application logging? If you are logging from different threads use logback, it's thread-safe and it exposes parameterized log messages.

Boris Pavlović
I was under the impression that Log4J is also thread safe.
James McMahon
It is: http://logging.apache.org/log4j/1.2/faq.html#1.7
Jens Schauder
A: 

Personally I put the log4j.properties in the WEB-INF directory and use an init servlet with the following code :

public class InitServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {

private static final String LOG4J_FILE = "WEB-INF/log4j.properties";

public InitServlet() {
 super();
}

@Override
public void init() throws ServletException {
 super.init();
 PropertyConfigurator.configure(getServletContext().getRealPath(LOG4J_FILE));
 LogFactory.getLog(InitServlet.class).info("LOG 4J configured");
}

}

Vinze
+2  A: 

It might be a good idea to place the config file somewhere where an admin can modify it without rebuilding your web app (e.g., so they can turn on detailed logging without waking you up in the middle of the night).

Unfortunately, there's no "official" way for locating externalized resources from a web app (correct me if I'm wrong). The most common way of doing it I've seen is to look through the directories in the classpath.

gustafc
Yeah I've hit the same issues with application configuration files. It's the curse of the war package. Then again, a savvy admin should be able to open the package up using something like 7-Zip and edit the configuration file. Sadly we don't employee anyone like that.
James McMahon
Yeah, and even if the admin actually is savvy enough to hack the WAR file, their custom settings will be overridden when the next version is deployed.
gustafc
A: 
  • Where does the configuration file go in .war package file?

At the root of the classpath but... Don't put the configuration file in the war package. You don't want to repackage and redeploy the application if you change the logging configuration, do you ? A better practice would be to put the configuration file somewhere in the classpath outside the war.

  • Where do people log to, relative or absolute path flat file, or a database?

I usually log to the file system on a separate partition (log files can grow very fast and should never block the application or the operating system if they become too big). I use most of time an absolute path based on the following model: /var/projects/<PROJECT_NAME>/<PRODUCT>/<CLUSTER_NAME>/logs/<INSTANCE_NAME>.log where <PROJECT_NAME> is the project name, <PRODUCT> can be Apache, Tomcat, Weblogic,..., <CLUSTER_NAME> the name of the cluster and <INSTANCE_NAME> the name of the instance inside the cluster. Logging to the file system is faster than in a database. The drawback is that logs aren't centralized if you are using several instances and physical machines. But merging can easily be done with a script.

  • Does Log4J logging go directly into the application server log file automatically or is that something you have to set up? In this case I am using Tomcat, but I often use Jrun.

Application server logs are application server logs, not application logs. Don't write to them but set up a logger tool (e.g. log4j) and write to application logs (understand dedicated).

  • Any other gotchas I should be aware of for web application logging?

If you are using log4j, don't forget to use the isDebugEnabled() before to log:

if(logger.isDebugEnabled()) {
  logger.debug("Bla Bla Bla");
}
Pascal Thivent
A: 
  • Where does the configuration file go in .war package file?

Usually, I do not place any logging configuration into the application, rather leaving that to the appserver admins to configure logging server-wide. In the rare cases I want the log4j configuration deployed with a webapp, WEB-INF is the usual path.

  • Where do people log to, relative or absolute path flat file, or a database?

Again, depends on appserver settings. One common log file for a appserver and rotating on a daily basis is the usual setup. If there are any app-specific needs, the admin may configure a separate logfile for an app (distinguished by package / class names).

  • Does Log4J logging go directly into the application server log file automatically or is that something you have to set up? In this case I am using Tomcat, but I often use Jrun.

See above. For tomcat used for development purposes, I'd just look for its logging (log4j) configuration and add app-specific specific there.

  • Any other gotchas I should be aware of for web application logging? Performance. Limit the ,log level to a minimum (i.e. WARN or ERROR) once you go live. Use if (log.isDebugEnabled()) { log.debug("..."); } and alike constructs in your code.
david a.
+1  A: 

Logging to a DB adds another failure point. We had a situation where the prod servers logged to a DB and someone ran an expensive query on that DB that slowed it so much that the prod servers got very, very slow. Logging to a file can cause issues if you run out of space but it seems less likely to slow down the who app.

James A. N. Stauffer
A: 

I recommend to call log API (log4j) via slf4j. Even if you use log4j, web container or depending modules may use different log API such as Java.util.logging or Jakarta commons logging. Slf4j provides bridge modules that redirect them to slf4j API. As a result, all log messages are written by log4j in that case.

grayger
A: 

Note that if you just need a bit of logging, the servlet standard specifies that you can get the ServletContext and use the log methods there. That is the generic servlet equivalent of System.out.println.

Thorbjørn Ravn Andersen
+5  A: 

I would recommend you to use SLF4J. This is simple logging facade which supports most of popular logging systems (Log4j, commons-logging, Java Logging API and Logback). Using it, you will able to replace your underline logging system to any other, by simple CLASSPATH update.

The other benefit of SLF4J are parameterized calls, which reduces ugly logging code.

Actually, they recommends to use SLF4J with Logback. Logback is a successor of Log4J. And it was designed by the same author.

Andrey Vityuk