Logger - a simple way to log Java applications
In this article I'd like to describe a small Java class that will enable you to log what your application is doing. Before I continue, I'd like to point out that this is a very simple, basic logger - if you need a serious logging framework for your application I suggest that you check out Log4J.
This logger class, however, is more than enough for most applications. As with most loggers, the messages are separated into different categories:
- debug: messages used to help debug the software, not shown in production.
- info: messages that allow users to get some basic information about what the software is doing.
- warn: warning messages, stuff that users should be aware of. Things that are not really a problem at the moment, but one should keep an eye out for possible errors as a result.
- error: errors which occured in the application, but from which the application was able to recover or continue.
- fatal: errors from which there is no recovery possible, the application will probably exit at this time.
Now then, let's have a look at the code:
import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.Calendar; public class Logger { public final static int LOG_DEBUG = 0; public final static int LOG_INFO = 1; public final static int LOG_WARN = 2; public final static int LOG_ERROR = 3; public final static int LOG_FATAL = 4; private static int level = LOG_DEBUG; private static File logFile = null; private static boolean logToFile = false; private static boolean display = true; public static void debug(String message) { if (level <= LOG_DEBUG) { logMessage(message); } } public static void info(String message) { if (level <= LOG_INFO) { logMessage(message); } } public static void warn(String message) { if (level <= LOG_WARN) { logMessage(message); } } public static void error(String message) { if (level <= LOG_ERROR) { logMessage(message); } } public static void fatal(String message) { if (level <= LOG_FATAL) { logMessage(message); } } public static void setDisplay(boolean display) { Logger.display = display; } public static void setLevel(int level) { Logger.level = level; } public static void setLogFile(File logFile) { Logger.logFile = logFile; } public static void setLogToFile(boolean logToFile) { Logger.logToFile = logToFile; } public static synchronized void logMessage(String message) { Calendar c = Calendar.getInstance(); String time = c.get(Calendar.YEAR) + "/" + c.get(Calendar.MONTH) + "/" + c.get(Calendar.DAY_OF_MONTH) + " " + c.get(Calendar.HOUR_OF_DAY) + ":" + c.get(Calendar.MINUTE) + ":" + c.get(Calendar.SECOND) + "." + c.get(Calendar.MILLISECOND); if (display) { System.out.println(time + " " + message); } if ((logToFile) && (logFile != null)) { try { PrintWriter pw = new PrintWriter( new FileWriter(logFile, true) ); pw.println(time + " " + message); pw.close(); } catch (IOException ioe) { // be silent } } } }
All methods are declared static - it's just another way to keep the class both easy to use and simple. The code can be easily rewritten to use a Singleton pattern if needed.
Only the method which performs the actual logging is synchronized - but that does not keep this class from being thread-safe, so you can safely use this logger class in a multi-threaded environment.
Perhaps a little word about configuration. There are a few options to configure this logger to your liking.
- setDisplay: tells the logger whether or not to show the log statement in your console window (note: only if the log level permits this)
- setLevel: set the level of log messages. Only messages of this level and higher will be logged. Levels can be set using the static level fields available in the class.
- setLogFile: tells the logger which file should be used to store log messages in. Messages will be appended to the end of the file.
- setLogToFile: tells the logger whether or not messages should be written to a log file
Please note that using setLogToFile without specifying a log file makes no sense - the logger needs to know where to store messages.
A typical usage of this logger class would look like the following snippet:
Logger.setDisplay(true); Logger.setLogToFile(true); Logger.setLogFile(new File("logfile.log")); Logger.setLevel(Logger.LOG_DEBUG); Logger.debug("This is a message of type 'debug'."); Logger.info ("This is a message of type 'info'."); Logger.warn ("This is a message of type 'warn'."); Logger.error("This is a message of type 'error'."); Logger.fatal("This is a message of type 'fatal'.");
So there you have it - a very simple logger class to use in your own applications. May it be as useful for you as it is for me.