taylorialcom/ Miscellaneous

Logging

The Logger class provides a convenient way to generate log files in your programs.

The following method can be used to configure a logger named, name, that will write to a log file called filename. The third argument determines the format of the log file. It will use a simple format unless "XML" is passed as the third argument, in which case, the log file will use an XML format.

private static boolean configureLogger(String name, String filename, String format) {
    Logger logger = Logger.getLogger(name);
    try {
        FileHandler handler = new FileHandler(filename);
        logger.addHandler(handler);
        switch (format == null ? "" : format) {
            case "XML" -> handler.setFormatter(new XMLFormatter());
            default -> handler.setFormatter(new SimpleFormatter());
        }
        logger.setUseParentHandlers(false);
        logger.info("Log file initialized");
    } catch (IOException e) {
        System.err.println("Warning: error initializing log file. Logging disabled.");
        logger = null;
    }
    return logger != null;
}

Using the logger is pretty simple. You just need to call configureLogger() at the beginning of your program. Then anywhere you wish to add a log entry to the log file, you just need to call one of the following on the logger object: severe(), warning(), or info(). With each call, you should pass the message that you wish to be logged. For example, the logger.info("Log file initiatized"); call in the method above adds something like the following to the log file:

Dec 09, 2024 6:22:33 AM wk15.LogExample configureLogger
INFO: Log file initialized

In the above example, configureLogger was a method in the wk15.LogExample class.

Once the logger object has been configured, it is possible to get access to the logger object anywhere else in the code. Only the name of the logger object needs to be known.

Logger logger = Logger.getLogger(name);

This will cause the local variable logger to point to the logger object created in configureLogger().

Appending to Log Files

The example above will overwrite the previous log file. To append to the log file, pass true as a second argument to the FileHandler constructor on line 4.

Severity Levels

There may be times when we are interested in more detailed information in our logs and other times when we'd like to limit the information written to log files. For example, when performing internal testing, more verbose logs may be appropriate; however, we may not want to expose all of that information to the end user.

The setLevel() method in the Logger class sets the level of logging. Once set the logger will only log messages at that level of severity or higher. The Level class provides the following levels:

The default level is INFO.

Singleton Design Pattern

Careful readers may have noticed that configureLogger() does not make use of a constructor. In fact, the constructors for the Logger class do not have public visibility, so it is not possible to instantiate a Logger object in the traditional way. This is by design.

The Logger design makes use of the singleton pattern. This pattern is used when we would like to have one single, global object that is shared throughout the code. The constructors for this class are hidden. Instead, a static method, getLogger() is used to gain access to the single logger object. The first time getLogger("log.txt") is called, a Logger object is constructed and returned. On all subsequent calls, a reference to the already existing object is returned.