How do I set a filter on a logger handler?

This example give you an example on how to set the Filter of a logger handler. In the code below we implement the Filter on the FileHandler to log only a Level.SEVERE message. Other log level will not be recorded to the file.

package org.kodejava.util.logging;

import java.util.logging.*;
import java.io.IOException;

public class LoggerFilter {
    public static void main(String[] args) {
        Logger logger = Logger.getLogger(LoggerFilter.class.getName());

        FileHandler handler = null;
        try {
            handler = new FileHandler("myapp.log");
            // The message will be recorded to the file When the 
            // LogRecord level is equals to Level.SEVERE
            handler.setFilter(record -> record.getLevel().equals(Level.SEVERE));
        } catch (IOException e) {
            logger.log(Level.SEVERE, "Fail to create logger handler", e);
        }

        logger.addHandler(handler);

        logger.info("Information message");
        logger.warning("Warning message");
        logger.severe("Severe message");
    }
}

How do I use Logger’s MemoryHandler class?

In this example we demonstrate the use of Logger‘s MemoryHandler to log only when some conditions happen in our application, for example when a Level.SEVERE message is logged.

We create an instance of MemoryHandler that will delegate the log to FileHandler class, and it logs the last 100 record until a Level.SEVERE message is logged.

package org.kodejava.util.logging;

import java.util.logging.Logger;
import java.util.logging.FileHandler;
import java.util.logging.MemoryHandler;
import java.util.logging.Level;

public class MemoryHandlerDemo {
    public static void main(String[] args) {
        MemoryHandlerDemo demo = new MemoryHandlerDemo();
        try {
            demo.testMethod();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void testMethod() throws Exception {
        Logger logger = Logger.getLogger(MemoryHandlerDemo.class.getName());
        FileHandler fileHandler = new FileHandler("myapp.log");

        // Create a MemoryHandler that will dump the log messages for the 
        // latest 100 records when a Level.SEVERE log is logged to by the
        // Logger class.
        MemoryHandler memoryHandler = new MemoryHandler(fileHandler, 100, Level.SEVERE);
        logger.addHandler(memoryHandler);

        // Write some messages to the log
        logger.info("Information message");
        logger.warning("Warning message");

        // This causes the log messages dump to the file log.
        logger.severe("Severe message");
    }
}

To check if the message is logged you can open the myapp.log file created by this small program.

How do I use logger ConsoleHandler?

In this example you’ll see how to add ConsoleHandler to the Logger instance. It is simple, just create an instance of ConsoleHandler and add it to the Logger using the Logger.addHandler() method.

package org.kodejava.util.logging;

import java.util.logging.Logger;
import java.util.logging.ConsoleHandler;
import java.util.logging.Level;

public class LogConsoleHandler {
    public static void main(String[] args) {
        // Obtains Logger instance
        Logger logger = Logger.getLogger(LogConsoleHandler.class.getName());

        // Add ConsoleHandler to Logger.
        ConsoleHandler consoleHandler = new ConsoleHandler();
        logger.addHandler(consoleHandler);

        if (logger.isLoggable(Level.INFO)) {
            logger.info("This is information message for testing ConsoleHandler");
        }
    }
}

How do I write log to a file?

An application log need to be persisted so that we can analyze the log when an error occurred in our application. For this reason we need to write to log into a file.

The Logging API provide handlers which helps us to do this. To write log to a file we can use the FileHandler. We define the name of our log file and the appendable mode in this class constructor. For example, you can look at the code presented below.

package org.kodejava.util.logging;

import java.util.logging.FileHandler;
import java.util.logging.Logger;
import java.util.logging.Level;
import java.io.IOException;

public class WriteLogToFile {
    public static void main(String[] args) throws IOException {
        Logger logger = Logger.getLogger(WriteLogToFile.class.getName());

        // Create an instance of FileHandler that write log to a file called
        // app.log. Each new message will be appended at the at of the log file.
        FileHandler fileHandler = new FileHandler("app.log", true);
        logger.addHandler(fileHandler);

        if (logger.isLoggable(Level.INFO)) {
            logger.info("Information message");
        }

        if (logger.isLoggable(Level.WARNING)) {
            logger.warning("Warning message");
        }

    }
}

How do I do a conditional logging?

When logging some messages in our application the purpose could be creating a log for debugging purposes. To minimize the impact of these debug message we can use a conditional logging. To do this we need to wrap each call to the logger method with a Logger.isLoggable(Level level) check.

The check will ensure that only logs with the appropriate level will be logged into our application logs. This will automate the on and off our application log without touching the code.

package org.kodejava.util.logging;

import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.Date;

public class ConditionalLogging {
    private Logger logger =
            Logger.getLogger(ConditionalLogging.class.getName());

    public static void main(String[] args) {
        ConditionalLogging demo = new ConditionalLogging();
        demo.executeMethod();
    }

    // In this method we will check if the Logger level is equals to
    // Level.INFO before we do the real logging. This will minimize
    // the impact of logging if in the next time we increase the level
    // to Level.WARNING or Level.SEVERE so that these message will not
    // be logged anymore.
    public void executeMethod() {
        if (logger.isLoggable(Level.INFO)) {
            logger.info("Entering executeMethod() at : " + new Date());
        }

        // Method body
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 5; j++) {
                System.out.print(i * j + " ");
            }
            System.out.println();
        }

        if (logger.isLoggable(Level.INFO)) {
            logger.info("Exiting executeMethod() at  : " + new Date());
        }
    }
}

The result of our example code above is shown below:

Oct 07, 2021 8:26:49 PM org.kodejava.util.logging.ConditionalLogging executeMethod
INFO: Entering executeMethod() at : Thu Oct 07 20:26:49 CST 2021
Oct 07, 2021 8:26:49 PM org.kodejava.util.logging.ConditionalLogging executeMethod
INFO: Exiting executeMethod() at  : Thu Oct 07 20:26:49 CST 2021
0 0 0 0 0 
0 1 2 3 4 
0 2 4 6 8 
0 3 6 9 12 
0 4 8 12 16 

How do I log an exception?

In this example you can see how we can log an exception when it occurs. In the code below we are trying to parse an invalid date which will give us a ParseException. To log the exception we call the Logger.log() method, passes the logger Level, add some user-friendly message and the Throwable object.

package org.kodejava.util.logging;

import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.text.ParseException;

public class LoggingException {
    private static Logger logger =
            Logger.getLogger(LoggingException.class.getName());

    public static void main(String[] args) {
        DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
        df.setLenient(false);

        try {
            // Try to parse a wrong date.
            Date date = df.parse("12/30/1990");

            System.out.println("Date = " + date);
        } catch (ParseException e) {
            // Create a Level.SEVERE logging message
            if (logger.isLoggable(Level.SEVERE)) {
                logger.log(Level.SEVERE, "Error parsing date", e);
            }
        }
    }
}

The code above will produce the following log message.

Oct 07, 2021 8:21:44 PM org.kodejava.util.logging.LoggingException main
SEVERE: Error parsing date
java.text.ParseException: Unparseable date: "12/30/1990"
    at java.base/java.text.DateFormat.parse(DateFormat.java:399)
    at org.kodejava.util.logging.LoggingException.main(LoggingException.java:20)

How do I check if a message is loggable?

The Logger class provide a setLevel() method to set the logging level. By setting logging to a certain level we can control which message will be logged.

To determine or check if a message will be logged we can use the Logger.isLoggable(Level level) method. Let see the example below.

package org.kodejava.util.logging;

import java.util.logging.Logger;
import java.util.logging.Level;

public class LoggingLevelCheck {
    public static void main(String[] args) {
        // Obtains an instance of Logger and set the logging level to 
        // Level.WARNING.
        Logger log = Logger.getLogger(LoggingLevelCheck.class.getName());
        log.setLevel(Level.WARNING);

        // Log INFO level message. This message will not be logged due to
        // the log level set to Level.WARNING
        if (log.isLoggable(Level.INFO)) {
            log.info("Application Information Message");
        }

        // Log WARNING level message when Level.WARNING is loggable.
        if (log.isLoggable(Level.WARNING)) {
            log.warning("Application Warning Information");
        }

        // Log SEVERE level message when Level.SEVERE is loggable.
        if (log.isLoggable(Level.SEVERE)) {
            log.severe("Information Severe Information");
        }
    }
}

This will result only the Level.WARNING and Level.SEVERE messages are logged.

Oct 07, 2021 8:18:03 PM org.kodejava.util.logging.LoggingLevelCheck main
WARNING: Application Warning Information
Oct 07, 2021 8:18:03 PM org.kodejava.util.logging.LoggingLevelCheck main
SEVERE: Information Severe Information

How do I obtain or create a Logger?

Since JDK 1.4 a logging API was introduced into the Java class libraries. This API enables our application to logs some messages to record our application activities.

To create an instance of Logger we can call the Logger.getLogger() factory method which will return the available logger for the given namespace, or it will create a new one when it doesn’t exist.

package org.kodejava.util.logging;

import java.util.logging.Logger;

public class LoggingDemo {
    public static void main(String[] args) {
        // Obtaining an instance of Logger. This will create a new Logger
        // is it doesn't exist.
        Logger log = Logger.getLogger(LoggingDemo.class.getName());

        // Log some message using a different type of severity level.
        log.info("Info Message");
        log.warning("Warning Message");
        log.severe("Severe Message");
        log.config("Config Message");
        log.fine("Fine Message");
        log.finer("Finer Message");
        log.finest("Finest Message");
    }
}

After we create the Logger instance we can create a message log by calling the logging method such as info(String message), warning(String message) and severe(String message). Below are some message produces by the Logger.

Oct 07, 2021 8:13:48 PM org.kodejava.util.logging.LoggingDemo main
INFO: Info Message
Oct 07, 2021 8:13:48 PM org.kodejava.util.logging.LoggingDemo main
WARNING: Warning Message
Oct 07, 2021 8:13:48 PM org.kodejava.util.logging.LoggingDemo main
SEVERE: Severe Message