Now that we have the basics of Log4J we shall move on to using it in a Java web application. The developer of the application would usually add the logging statements before it is handed to the administrator. However, it is useful to know the syntax and usage of the different options available. We'll start off by using the simple example again, but this time we'll use it from a JSP page in a web application called logging. First though, we need to configure the Logger.
现在我们已经有了Log4J的基础,我们将转移到在一个Java Web应用程序中使用它.
我们再一次通过一个简单的例子出发,但这次我们从Web应用程序中的JSP页调用.首先,我们需要配置
Logger.
Configuring a Logger in a Web Application
在Web应用程序中配置Logger
.As we saw earlier, the easiest way to configure a Logger was to use a configuration file. When using Log4J in a web application it is a good idea to set up a Logger for the entire web application at startup. This can be achieved by using an initialization servlet that loads the configuration file into the web application.
前面我们看到,配置Logger最容易的方法是使用配置文件,当在Web应用程序中使用Log4J时,在启动时为整个应用程序设置一个Logger是一好想法.这可以通过使用一个初始化Servlet完成,它在启动的时候加载配置文件到应用程序中.
The Initialization Servlet
Here is the initialization servlet:
package wrox; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.PrintWriter; import java.io.IOException; import org.apache.log4j.PropertyConfigurator; public class Log4JInitServlet extends HttpServlet {
应用范围内的配置都在init()方法中调用,当Servlet第一次被Tomcat加载的时候,init()方法被自动调用.The application-wide configuration happens in the init() method. 使Logger自启动后就可以是用:
// Initialize the servlet by loading the Log4J properties file public void init() throws ServletException {
The properties file will be stored in the $CATALINA_HOME/webapps/logging/WEB-INF/classes directory of our web application. We need to get the path to the properties file before we can load it, so we get the full path to the web application on the filesystem and then append the name of the file. In this case, the name of the file comes from the properties initialization parameter specified in web.xml. This allows us to specify the location of the properties file outside of the application's code:
属性文件被存储在Web应用程序的 $CATALINA_HOME/webapps/logging/WEB-INF/classes 目录中,在我们加载它之前必须获得它的路径,因此
这允许我们指定应用程序代码之外属性文件的位置
// First we get the fully qualified path to the web application String path = getServletContext().getRealPath("/"); String properties = path + getInitParameter("properties");
The final step is to call the configure () method to make the Logger available for all the other files in the application:
// Next we set the properties for all the servlets and JSP // pages in this web application PropertyConfigurator.configure(properties); }
The final methods are required to be in any servlet:
// The doPost() method forwards all requests to the doGet() method public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } // The doGet() method informs users of the purpose of this servlet public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { PrintWriter out = resp.getWriter(); out.println("Initialization servlet for Log4J"); } public void destroy() {} }
Compile this class and place it in $CATALINA_HOME/webapps/logging/WEB-INF/classes/wrox.
web.xml
Next we need a web.xml file for our web application so that we can specify the location of our properties file:
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <servlet> <servlet-name>log4Jinit</servlet-name> <servlet-class>wrox.Log4JInitServlet</servlet-class> <init-param> <param-name>properties</param-name> <param-value>WEB-INF/classes/log4j.properties</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> </web-app>
The <load-on-startup> element loads the servlet when Tomcat is started. This is exactly what we want as we need the Logger to be available to the web application as soon as Tomcat starts.
Logging To Files
In this section we will start with a simple file example, then show the following formats that are made available to Log4J:
-
HTMLFormat
-
PatternFormat
Simple File
The configuration file for this first example is very similar to the one we saw before. However, this time we'll log to the $CATALINA_HOME/logs directory:
# A simple logger log4j.logger.wrox.simple=DEBUG, simple # This simple example will log to a file log4j.appender.simple=org.apache.log4j.FileAppender log4j.appender.simple.File=<CATALINA_HOME>/logs/log4jsimple.log # We will use a simple layout for this example log4j.appender.simple.layout=org.apache.log4j.SimpleLayout
Note that Log4j does not consider <CATALINA_HOME> to be a shortcut; it is merely a neat piece of notation for us. Be sure and provide the full path in your files.
Save this file as log4j.properties in logging/WEB-INF/classes.
Finally, we need a JSP page to use the Logger (logsimple.jsp):
<%@ page import="org.apache.log4j.Logger" %> <html> <head><title>Logging with Log4J</title></head> <% Logger logger = Logger.getLogger("wrox.simple"); logger.debug("A debug message"); logger.info("An info message"); logger.warn("A warn message"); logger.error("An error message"); logger.fatal("A fatal message"); %> <body> <h1>Logging completed</h1> </body> <html>
Place this in $CATALINA_HOME/webapps/logging. Now, point your browser at http://localhost:8080/logging/logsimple.jsp. You should see the confirmation message. This should have set off the Logger and written the logging messages to $CATALINA_HOME/logs/log4jsimple.log.
HTML
Now we will look at a different kind of Layout, the HTMLLayout. This Layout formats the logging information into HTML tables that can be customized to fit most needs. We shall send the logging information to an HTML file in the logging web application so that we can view it online. However, it would be possible to put this file under a password-protected context, such as admin in Tomcat 4.1.3 onwards.
Here is the configuration file:
# An HTML logger log4j.logger.wrox.html=DEBUG, html # This simple example will log to an HTML file log4j.appender.html=org.apache.log4j.FileAppender log4j.appender.html.File=<CATALINA_HOME>/webapps/logging/log.html # This line stops additional log sessions being appended to the end # of the file log4j.appender.html.Append=false # We will use an HTML Layout for this example log4j.appender.html.layout=org.apache.log4j.HTMLLayout # This line shows where in the servlet/JSP page the logging # statement is placed log4j.appender.html.layout.LocationInfo=true # The Title parameter sets the HTML <title> tag for the HTML page log4j.appender.html.layout.Title=Wrox Log
The JSP page for this example, loghtml.jsp, has only one change:
<%@ page import="org.apache.log4j.Logger" %>
<html>
<head><title>Logging with Log4J</title></head>
<%
Logger logger = Logger.getLogger("wrox.html");
logger.debug("A debug message");
logger.info("An info message");
logger.warn("A warn message");
logger.error("An error message");
logger.fatal("A fatal message");
%>
<body>
<h1>Logging completed</h1>
</body>
<html>
Access this page at http://localhost:8080/logging/loghtml.jsp and then view http://localhost:8080/logging/log.html. You should see something similar to the following:
Pattern
The final Layout that we will look at is the PatternLayout. This Layout allows us to specify a custom format for the logging messages. The format can be configured in a number of ways with various format modifiers and conversion characters playing their part. We saw one example earlier, but here is the example we will be using in this section:
We have already seen the %m and %n conversion characters, as well as a different version of the %d character. This time we have specified a custom format for the date between the {} markers. The initial %-5p section can be further broken down into the -5 and %p blocks. %p displays a string representation of the priority (a throwback to earlier versions of Log4J when a Priority did the same job as a Level), that is, 'DEBUG', 'WARN', and so on. -5 is a format modifier that says 'right pad with spaces if the priority is less than 5 characters long'.
A full list of the format modifiers and conversion characters is available in the Log4J documentation: http://jakarta.apache.org/log4j/docs/api/org/apache/log4j/PatternLayout.html.
We specify this pattern for our file as follows:
# A pattern logger log4j.logger.wrox.pattern=DEBUG, pattern # This simple example will log to a custom format file log4j.appender.pattern=org.apache.log4j.FileAppender log4j.appender.pattern.File=<CATALINA_HOME>/logs/log4jpattern.log # We will use a custom layout for this example log4j.appender.pattern.layout=org.apache.log4j.PatternLayout # Here we set our custom pattern log4j.appender.pattern.layout.ConversionPattern=%-5p : %m %d{dd-MM-yy HH:mm:ss}%n
The only line that has changed since our last JSP page is:
Logger logger = Logger.getLogger("wrox.pattern");
Point your browser to http://localhost:8080/logger/logpattern.jsp and then view $CATALINA_HOME/logs/log4jpattern.log. The log entries should look something like this:
DEBUG : A debug message 06-08-02 01:54:21 INFO : An info message 06-08-02 01:54:21 WARN : A warn message 06-08-02 01:54:21 ERROR : An error message 06-08-02 01:54:21 FATAL : A fatal message 06-08-02 01:54:21
Logging To the Console
Log4J allows us to log to other destinations other than files. In this section we shall send logging messages to the console. This allows an application to instantly notify the administrator of any problems that occur. To log to the console we need to attach a ConsoleAppender to our Logger:
# A console Logger log4j.logger.wrox.console=DEBUG, console # This simple example will log to the console log4j.appender.console=org.apache.log4j.ConsoleAppender # Set the target to Sysytem.out log4j.appender.console.Target=System.out # We will use the simple format for the console example log4j.appender.console.layout=org.apache.log4j.SimpleLayout
The Target parameter must be one of System.out (the default) or System.err.ConsoleAppenders accept the same Layouts as FileAppenders: in this case we are using a SimpleLayout.
Again, our JSP page (logconsole.jsp) only needs one change:
Logger logger = Logger.getLogger("wrox.console");
Accessing http://localhost:8080/logging/logconsole.jsp will cause the log messages to be logged to Tomcat's console:
Logging To Multiple Destinations
One of the more useful features of Log4J is the ability to log to several destinations at once. This can allow us to send serious error messages to a location where they will be instantly noticed, for example the console, while other more routine messages can be sent to a regular logging file.
We shall look at the following examples in this section:
-
Logging FATAL events to the console and all events to a file
-
Logging FATAL events to the console and all events to Unix's syslog system Logger
-
Logging FATAL events to the console and FATAL and ERROR level events to WinNT's Event Logger
Console and a File
Our first example will log all FATAL level events to the console so that an administrator will be instantly alerted to any serious problems with an application. Also, we still need a record of other events (and a permanent record of FATAL events) so we will log all events to a file.
First we assign two Appenders to the wrox.multifile Logger: fatalconsole and errorfile. We also set the default logging level:
# A multi-destination logger # FATAL errors will go to the console # All errors will go to a file log4j.logger.wrox.multifile=DEBUG, fatalconsole, errorfile
Now we set the fatalconsole Appender's type to ConsoleAppender, set the target to System.out, and set the logging level to FATAL, using the Threshold parameter of the Appender:
# All fatal messages for this example go to the console log4j.appender.fatalconsole=org.apache.log4j.ConsoleAppender log4j.appender.fatalconsole.Target=System.out log4j.appender.fatalconsole.Threshold=FATAL
Next we set up the file where all log messages will be sent. We also set the logging level to DEBUG:
# All messages go to a file log4j.appender.errorfile=org.apache.log4j.FileAppender log4j.appender.errorfile.File=<CATALINA_HOME>/logs/log4jerrors.log log4j.appender.errorfile.Threshold=DEBUG # We will use simple layouts for both the console and the file log4j.appender.fatalconsole.layout=org.apache.log4j.SimpleLayout log4j.appender.errorfile.layout=org.apache.log4j.SimpleLayout
Now all we need to do to set up this example is change the same line of code in our JSP page (fatalconsole.jsp):
Logger logger = Logger.getLogger("wrox.multifile");
The logging method calls remain the same. Now each time a logging message is logged by the wrox.multifile Logger it is compared to the level of each Appender and only sent to its destination if it is less than or equal to this level.
Now if you point a browser at http://localhost:8080/logging/fatalconsole.jsp you should see the following in the Tomcat console:
Now look at $CATALINA_HOME/logs/log4jerrors.jsp:
DEBUG - A debug message INFO - An info message WARN - A warn message ERROR - An error message FATAL - A fatal message
As you can see, Log4J has only sent FATAL level messages to the console, but has sent all messages to the regular logging file.
Console and Syslog
The Unix syslog program is an integral part of all Unix systems. It was designed with two important functions in mind: liberating programmers from having to write log files and putting logging in the hands of the administrator.
Log4J provides the SyslogAppender for working with syslog. It needs a bit more configuring than the other Appenders we have seen before, but it is still relatively straightforward. In this example, we will again send FATAL level events to the console, but this time we will send all events to syslog as user-level events:
# A multi-destination logger # FATAL errors will go to the console # All errors will go to syslog log4j.logger.wrox.multisyslog=DEBUG, fatalconsolesys, syslog # All fatal messages for this example go to the console log4j.appender.fatalconsolesys=org.apache.log4j.ConsoleAppender log4j.appender.fatalconsolesys.Target=System.out log4j.appender.fatalconsolesys.Threshold=FATAL
Here is the SyslogAppender configuration. After setting the syslog Appender type, we set its logging level. We then need to set the syslog facility using the SyslogAppender's Facility parameter. syslog uses facilities alongside a severity index to decide where the logging message should be sent, much like Log4J does with the logging level and Appender name. Many system functions have their own facility, for example sendmail has the mail facility and the kernel has the kern facility. In our example we will use the user facility that is designed for user-level processes.
The final piece of configuration for a SyslogAppender is the SyslogHost parameter. This should specify the central logging host of your network, or localhost if you are logging to the local machine:
# All messages go to syslog log4j.appender.syslog=org.apache.log4j.net.SyslogAppender log4j.appender.syslog.Threshold=DEBUG log4j.appender.syslog.Facility=USER log4j.appender.syslog.SyslogHost=localhost # We will use simple layouts for both the console and syslog log4j.appender.fatalconsolesys.layout=org.apache.log4j.SimpleLayout log4j.appender.syslog.layout=org.apache.log4j.SimpleLayout
Important | Note that if syslog is running on a Linux box over a network, you will have to start it with the -r switch to enable network logging. This can be set in the /etc/init.d/syslog file. Run /etc/init.d/syslog restart to restart syslog. |
Again, there is only one change to the JSP file:
Logger logger = Logger.getLogger("wrox.multisyslog");
Point a browser at http://localhost:8080/logging/fatalsyslog.jsp and then examine the log file where syslog sends all user-level log messages. You should see the messages listed in syslog's format, which should look like the following:
Aug 5 16:48:40 matthew user: DEBUG - A debug message
Console and WinNT Event Logger
Our final example will be logging messages to the console and WinNT's Event Logger. The Event Logger can be found under Start | Settings | Control Panel | Administrative Tools | Event Viewer. This is where WinNT logs its system messages. These messages include serious errors in applications like Internet Explorer, as well as less important messages such as print job completion messages. WinNT messages have error types that are similar in concept to Log4J Levels. For example, WinNT Errors correspond to Log4J's FATAL and ERROR levels.
In this example, we will again send only FATAL errors to the console, but this time only FATAL and ERROR messages will be sent to the Event Logger:
# A multi-destination logger # FATAL errors will go to the console # FATAL and ERROR will go to the NT Event Logger log4j.logger.wrox.multiwinnt=DEBUG, winntconsole, winntlogger # All fatal messages for this example go to the console log4j.appender.winntconsole=org.apache.log4j.ConsoleAppender log4j.appender.winntconsole.Target=System.out log4j.appender.winntconsole.Threshold=FATAL
Here is where we configure the NTEventLogAppender that allows us to write to the Event Logger:
# All fatal and error messages go to the WinNT logger log4j.appender.winntlogger=org.apache.log4j.nt.NTEventLogAppender log4j.appender.winntlogger.Threshold=ERROR
The Event Logger displays the source of the message in its window. By default, Log4J messages are given the name 'log4j'. This isn't very useful if we have a number of applications using Log4J, so we will add our own source name:
# We will set the Source parameter so we know which application # this message came from log4j.appender.winntlogger.Source=Wrox Logging
The Event Logger can take the same Layouts as other Layouts, but only SimpleLayout and PatternLayout make sense in this situation (as we shall see when we examine the log message):
# We will use a simple layout for both the console and the Event Logger log4j.appender.winntconsole.layout=org.apache.log4j.SimpleLayout log4j.appender.winntlogger.layout=org.apache.log4j.SimpleLayout
Here's that line of code again:
Logger logger = Logger.getLogger("wrox.multiwinnt");
Viewing the page http://localhost:8080/logging/fatalwinnt.jsp will send the usual FATAL message to the console as well as an ERROR message and a FATAL message to the Event Logger:
Both messages are logged as WinNT errors, but are given different categories. Double-clicking on a log message will show its properties:
The Description box explains why the SimpleLayout and PatternLayout are the only sensible options for this kind of Appender: putting HTML tables into this box would make it almost unreadable.