So, what is an application log and why do we need one? An application log is a text history of notable events logged by your application. This log helps you to figure out what went wrong (and right) during the execution of your application. Of four very large projects I have been involved in, only one planned for an application log from the start. The other three had to create them in the testing phase, at great expense and delay I might add. With the advent of N-tier architectures, Servlets, JSPs, and EJBs, application logging is particularly important to report errors that cannot or should not be surfaced to the user interface.
All good frameworks are just starting points. The vision I have for this framework is to be a VERY good starting point from which you can log important events in your application. There may be bugs. There is definitely many inadequacies. But hopefully the design is good enough and well-documented enough for you to take the framework and make it useful in your application domain. JavaDoc for the framework is here.
A significant event happens in your Java code. That event could be any of several different types and conditions. Before you start using a logging framework, you must categorize and document your events so that all users of the framework will log events consistently. JLog comes out of the box with the following event definitions.
To make the JLF logging framework operate properly, more critical events must have lower event level numbers than less critical events. The most critical event category must be level 1.
Level | Name | Purpose |
1 | CRITICAL_ERROR | The system encountered a critical error at this logging level, which affects the accuracy, integrity, reliability, or capability of the system. Someone should be paged to address the error as soon as possible. |
2 | ERROR | The system encountered an unexpected error at this logging level, which means the code intercepted an error it cannot handle. This error is not of a critical nature and typically can be recovered from automatically. Future requests into the system should be able to be processed without error. Someone should be emailed to resolve the error in the near future to increase the reliability of the product. |
3 | WARNING | The system encountered an expected error situation. The system recovered from it but the fact that it happened should be recorded to see how frequent it happens. |
4 | INFORMATION | Normal logging level. All interesting periodic events should be logged at this level so someone looking through the log can see the amount and kind of processing happening in the system. |
5 | DETAIL | Moderately detailed logging level to be used to help debug typical problems in the system. Not so detailed that the big picture gets lost. |
6 | TRACE | Most detailed logging level. Everything sent to the log will be logged. Use this level to trace system execution for really nasty problems. At this level, the logging will typically be so verbose that the system performance will be affected. |
Once you have agreed upon a set of event categories and documented them in your coding standards, you need to determine the granularity you will log those events. For example, in my application we have a thread pool, a database connection pool, a request processing framework, a SQL processing framework, and then the application that uses all of the above services. When debugging a thread pool problem, I don't want the log to be cluttered with SQL log statements, so I have one log for the thread pool and another for the SQL processor. The application is still pretty small, so we only have one log for the entire application. However, I could see us split the log in the future as the application grows (and we want to be able to more easily debug a particular subsystem of the application). The next table shows the logging granularity in for a proposed application. Just as with event categories, you need to agree upon, document, and enforce logging granularity standards for your application. JLF only comes with the AppLog log configured (AppLog.java), but you copy and rename this log to fit your needs.
Log Name | Purpose |
AppLog | General application event logging |
SQLLog | Logs all SQL-related processing activities |
ThreadLog | Logs all events related to managing the thread pool |
RequestLog | Logs all requests into the system, including the time to fulfill the request |
DbConnectLog | Logs events related to managing the database connection pool |
Once you have a log that you can conveniently access, you need to add logging statements throughout your code. The log is only as useful as the information written to it. Three examples follow:
AppLog.criticalError("Caught unexpected exception: " + e); SQLLog.info("Executing SQL query: " + statement); AppLog.trace("Entering method getName()");
Notice that the code above does not have any "if" logic in it to determine if the event should be
output. The log takes care of that automatically as the system runs.
One note for those people overly concerned about performance (you know who you are). Using JLog, the application
will construct the log messages and execute framework code even when logging is turned off. Without using a C/C++
type preprocessor, logging of this type will add a slight performance hit to your system. You can easily overdo
logging. When I added method-level tracing (that is, logging the entrance to each method) to my application, I
saw a 12% performance hit when all logs were turned off (and the application slowed to a crawl when the logs were
turned to trace level). However, I would definitely maintain that the slight performance hit you take when doing
judicious logging is well worth it when you debug a difficult production problem.
Each log can output its information to one or more logging mechanisms. A logging mechanism is a separate class that abstracts the details of the particular logging destination (for example, System.err, a local text file). Each log also registers itself with a log manager, so you see what logs are active in the system. You should configure the logs from a properties file (described in the LogProperties.java class Javadoc) so your application, at startup time, has a good set of defaults. After that, you can use the set of JSPs I have included in the JLF WAR file to view and update log file properties at run time.
Todd Lauinger