This article explains a bit of the importance of application logging and log4j API in Java. The following paragraphs will give you an overview of how logging mechanism works in Java application and how use one of the common logging APIs to log messages.
The importance of logging
Logging is a vital part in the majority of applications. It enables to record most of events as well as what are going on your application that save a lot hours of developers, system administrators, especially the support team. To implement logging mechanism properly, you need to find the answer of some common questions in developing the application which are what to log, when to log, how much to log, how to control logging and how correlate it with your exception system (see more in [1]).
What does log4j API do?
Like I said, Log4J is one of Java based logging APIs that helps you recording likely messages in your program.
Example 1: we create a class named SimpleStatistics.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
package com.itersdesktop.javatechs; import org.apache.log4j.Logger; public class SimpleStatistics { /* Get actual class name to be printed on */ static Logger log = Logger.getLogger(SimpleStatistics.class.getName()); public static void main(String[] args) { int[] numbers = new int[]{20, 30, 25, 35, -16, 60, -100}; //calculate sum of all array elements int sum = 0; for(int i=0; i < numbers.length ; i++) sum = sum + numbers[i]; //calculate average value double average = sum / numbers.length; log.debug("Average value of the array elements is : " + average); log.info("Finished!"); } } |
To declare a log instance, we can use one of the following syntax:
1 2 3 4 |
static Logger log = Logger.getLogger(SimpleStatistics.getClass()); static Logger log = Logger.getLogger(SimpleStatistics.class); static Logger log = Logger.getLogger(this.getClass()); static Logger log = Logger.getLogger(SimpleStatistics.class.getName()); |
Then, we use the following statements to record informative, debugging or warning message.
1 2 3 |
log.info(messages); log.debug(message); log.warn(message); |
What does commons-logging framework do?
Commons-logging is an abstraction layer for logging frameworks so it doesn’t log anything itself.
Example 2: we get back the example introduced above and modified a bit
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package com.itersdesktop.javatechs; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class SimpleStatistics { /* the class logger */ private static final Log log = LogFactory.getLog(SimpleStatistics.class.getName()); // private static final Log log = LogFactory.getLog(SimpleStatistics.getClass()); // private final Log log = LogFactory.getLog(this.getClass()); public void SayHi(String name) { System.out.println(SimpleStatistics.class); // class com.itersdesktop.javatechs.SimpleStatistics System.out.println(this.getClass()); // class com.itersdesktop.javatechs.SimpleStatistics System.out.println(SimpleStatistics.class.getName()); // com.itersdesktop.javatechs.SimpleStatistics String helloMessage = "Hi " + name; System.out.println(helloMessage); log.debug(helloMessage); log.info(helloMessage); log.info("Finished!"); } } |
Output
Regardless of ways you use to log messages, the output could look like the following images
From the console
From the log file
The logs.log file is created automatically once you run the application at first. We will discuss on how to customise the log configuration to generate log messages in a favourite form later on in this article.
Customise the logs file
By default, a file named logs.log is created in the logs folder. As you see in the above screenshot, we have two files: logs.log and running.log. The former records messages coming from different log points (i.e. classes using logging API). In the toy application, I create two classes in the same package. The logging messages of both classes have been saved in the logs.log file under the pattern.
1 2 |
2017-07-07 10:42:48 INFO SimpleStatistics:22 - Hi Khang 2017-07-07 10:42:48 INFO SimpleStatistics:23 - Finished! |
However, log API enables us customise a lot of things either prettifying the messages or avoiding lost of messages due to over capacity of the logs file. It creates a default file named log4j.properties (if you use log4j API) or commons-logging.properties (if you use commons-logging framework) in the src/resources folder. The following is the basic settings created at the first run.
log4j.properties
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
log4j.rootLogger=DEBUG, file, stdout #log4j.logger.com.itersdesktop.javatechs=DEBUG, file, stdout #log4j.additivity.com.itersdesktop.javatechs=false log4j.appender.file=org.apache.log4j.RollingFileAppender log4j.appender.file.File=logs/logs.log log4j.appender.file.MaxFileSize=5MB log4j.appender.file.MaxBackupIndex=10 log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{dd/MMM/yyyy HH:mm:ss,SSS}- %c{1}: %m%n |
commons-logging.properties
1 |
org.apache.commons.logging.Log = org.apache.commons.logging.impl.Log4JLogger |
- Enable/disable log message out the standard output
- Rename the logs file and replace the location where the logs file is stored
- Change the maximum size of the logs file
- Use full package name rather than class name
- ….
Source code
I pushed my work to bitbucket in case you want to review.