Using java.util.logging API To Log Records To A Filesystem Log [Example Code]

The Java Logging APIs, introduced in package java.util.logging, facilitate software servicing and maintenance at customer sites by producing log reports suitable for analysis by end users, system administrators, field service engineers, and software development teams. The Logging APIs capture information such as security failures, configuration errors, performance bottlenecks, and/or bugs in the application or platform. The core package includes support for delivering plain text or XML-formatted log records to memory, output streams, consoles, files, and sockets. In addition, the logging APIs are capable of interacting with logging services that already exist on the host operating system.

By going through the following tutorial, you should be able to:

  • Use standard java.util.logging API to log your application logs, messages etc to a log file.
  • Create your own custom formatter to format the output as per your requirement.
  • Understand Log Level and how to use it.
  • Calling diffrent methods of logger class to log different levels of messages.

You will also be able to control the way the file is written to the system. You will be able to do the following actions related to a log file:

  • Define maximum size of data to be logged in one file.
  • Define maximum number of log files to be used. If the logs go over that limit, the oldest log files will be truncated
  • Control whether the data should be appended to the file or overwritten.
  • Define a pattern how you want the log files to be named.

package com.kushal.log;

/**
 * @Author Kushal Paudyal
 * www.sanjaal.com/java
 * Last Modified On: 2009-10-26
 *
 * JavaFileLogger.java
 * Demonstrates the use of java.util.logging API to log
 * program information into file system.
 *
 */
import java.io.IOException;
import java.util.Date;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;

public class JavaFileLogger {

	/**
	 * Defining a log level. Level.ALL logs all levels of messages.
	 */
	static Level logLevel = Level.ALL;

	public static void main(String args[]) throws Exception {

		/**
		 * Defining a location of log file
		 */
		String fileName = "C:/temp/log/myAppLogFile.log";

		/**
		 * Create a file logger with a custom log formatter
		 * If you provide the second parameter as null,
		 * a default XML Formatter will be applied, and the
		 * generated log file will be an XML
		 */
		Logger fileLogger = getFileLogger(fileName, getCustomFormatter());
		/**
		 * Set the Log level.
		 */
		fileLogger.setLevel(logLevel);

		fileLogger.log(new LogRecord(logLevel,
				"We are starting to log into the file"));
		fileLogger.fine("This is a fine level of message");
		fileLogger.finer("This is a finer level of message");
		fileLogger.finest("This is a finest level of message");

		/**
		 * Calling a callMe() method to show the usage of entering ()
		 * and exiting () method of Logger.
		 *
		 * These method calls are used to log when you enter a method
		 * and when you exit it.
		 */
		new JavaFileLogger().callMe(fileLogger);

		/**
		 * Just creating and logging some sample messages by going through a loop.
		 */
		for (int i = 0; i < 50; i++)
			fileLogger.info((i + 1)
					+ " - A Quick brown fox jumps over the lazy dog");

	}

	public static Logger getFileLogger(String fileName, Formatter formatter) {

		/**
		 * Find or create a logger for a named subsystem. If a logger has
		 * already been created with the given name it is returned.
		 * Otherwise a new logger is created.
		 *
		 * If a new logger is created its log level will be configured based
		 * on the LogManager configuration and it will configured to also
		 * send logging output to its parent's handlers. It will be
		 * registered in the LogManager global namespace.
		 */
		Logger logger = Logger.getLogger("com.kushal.log.JavaLogger");

		try {

			/**
			 * Define whether the log should be appended to the existing one
			 * If set to false, the log file will be overwritten, not appended
			 */
			boolean append = true;

			/**
			 * Defining the limit of file size in Bytes.
			 * This is tentatively the maximum data that will be written
			 * to one log file.
			 */
			int limit = 1024; // 1 KB Per log file, modify as required.

			/**
			 * If a file is full (as defined by 'limit' value above), files will
			 * be renamed and a new log file will be crated.
			 *
			 * Pattern defines how the log file should be renamed.
			 *
			 * In this example, we are using the same fileName as the pattern.
			 * So the files will be renamed as:
			 * myAppLogFile.log.0
			 * myAppLogFile.log.1
			 * myAppLogFile.log.2 ..and so on.
			 */
			String pattern = fileName;
			/**
			 * This is the maximum number of log files to be created.
			 * If this number is reached, the last file will be truncated
			 * and a new one will be created.
			 */
			int numLogFiles = 50;

			/**
			 * Creating a file handler based on the above parameters
			 */
			FileHandler handler = new FileHandler(pattern, limit, numLogFiles,
					append);

			if (formatter != null)
				handler.setFormatter(formatter);

			logger.addHandler(handler);
		} catch (IOException e) {
			e.printStackTrace();
		}

		return logger;
	}

	/**
	 * This method will define a custom formatter and return it.
	 * Formatter is used to format the way the output content
	 * is logged to the sytem, in this case a file.
	 */
	public static Formatter getCustomFormatter() {
		return new Formatter() {
			public String format(LogRecord record) {
				String recordStr = "{Date} " + new Date() + " {Log Level} "
						+ record.getLevel() + " {Class} "
						+ record.getSourceClassName() + " {Method} "
						+ record.getSourceMethodName() + " {Message} "
						+ record.getMessage() + "n";
				return recordStr;
			}
		};
	}

	/**
	 * Sample method to show the method entry and exit log usage
	 */
	public void callMe(Logger logger) {
		/**
		 * Getting the current method name.
		 * This is an expensive method, but i have presented here for demonstration only.
		 */
		String myMethodName = new Exception().getStackTrace()[0]
				.getMethodName();
		String myClassName = this.getClass().getName();

		/** Logging the method entry**/
		if (logger.isLoggable(logLevel))
			logger.entering(myClassName, myMethodName);

		logger.info("Middle of the method");

		/** Logging the method exit**/
		if (logger.isLoggable(logLevel))
			logger.exiting(myClassName, myMethodName);

	}

	/*
	 * SANJAAL CORPS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
	 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
	 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
	 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SANJAAL CORPS SHALL NOT BE LIABLE FOR
	 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
	 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
	 *
	 * THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
	 * CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
	 * PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
	 * NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
	 * SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
	 * SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
	 * PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). SANJAAL CORPS
	 * SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
	 * HIGH RISK ACTIVITIES.
	 */
}

 


Screenshot of Log Files generated:

Sample content of first log:

More Info:

The entire logging API is contained in the package java.util.logging and is made up of the following interfaces and classes:

  • ConsoleHandler
  • FileHander
  • Filter
  • Formatter
  • Handler
  • Level
  • Logger
  • LoggingPermission
  • LogManager
  • LogRecord
  • MemoryHandler
  • SimpleFormatter
  • SocketHandler
  • StreamHandler
  • XMLFormatter

Logging Levels:
There are several logging levels in java.util.logging API. The levels in descending order are:

Pleae note that the values in square bracket are unique integers assigned to these levels.

  • SEVERE [1000](highest value)
  • WARNING [900]
  • INFO [800]
  • CONFIG [700]
  • FINE [500]
  • FINER [400]
  • FINEST [300](lowest value)

In addition there two special logging levels:

  • OFF – Turn of logging
  • ALL – Enable logging all messages

You can also implement custom levels.

Few Other Java Logging Frameworks:

  • SL4J
  • Log4J