How do I create a rolling log files?

In this example we create a rolling or a sequenced of log files. Instead of just limiting the file size (see. How do I limit the size of log file) we can also make the log file to roll. This will prevent a lost to an important log message if we use a single log file.

When using more that one file the log file name will have a sequence number in it starting from 0 to N-1. If we set the count to 5 then we’ll have log files such as myapp.log.0, myapp.log.1 up to myapp.log.5.

If the first log file (myapp.log.0) is about to full, it will be renamed to (myapp.log.1) before the log is written to the first log file. The log is always written to the first file (myapp.log.0).

To read the log messages in sequence you need to start from the highest to the lowest sequence number.

package org.kodejava.example.logging;

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

public class RollingLogFile {
    //
    // Set a small log file size to demonstrate the rolling log files.
    //
    public static final int FILE_SIZE = 1024;

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

        try {
            //
            // Creating an instance of FileHandler with 5 logging files
            // sequences.
            //
            FileHandler handler = new FileHandler("myapp.log", FILE_SIZE, 5, true);
            handler.setFormatter(new SimpleFormatter());
            logger.addHandler(handler);
            logger.setUseParentHandlers(false);
        } catch (IOException e) {
            logger.warning("Failed to initialize logger handler.");
        }

        logger.info("Logging information message.");
        logger.warning("Logging warning message.");
    }
}

By running this program multiple times you’ll see the creation of the log file one by one.

How do I limit the size of log file?

In this example you learn how to limit the size of a log file when using a
FileHandler handler. Limiting the log file will prevent the log
file to grow wildly without limit.

package org.kodejava.example.util.logging;

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

public class LogFileLimit {
    //
    // The log file size is set to 1MB.
    //
    public static final int FILE_SIZE = 1024 * 1024;

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

        try {
            //
            // Create a FileHandler with 1MB file size and a single log file. We
			// also tell the handler to append the log message.
            //
            FileHandler handler = new FileHandler("myapp.log", FILE_SIZE, 1, true);
            logger.addHandler(handler);
        } catch (IOException e) {
            logger.warning("Failed to initialize logger handler.");
        }

        logger.info("Test info");
        logger.warning("Test warning");
        logger.severe("Test severe");
    }
}

How do I create a custom logger Formatter?

To create a custom Formatter we need to extends the java.util.logging.Formatter abstract class and implements the format(LogRecord) method. In the method then we can format the log message stored in the LogRecord to match our need.

The java.util.logging.Formatter class also have the getHead(Handler) and getTail(Handler) which can be overridden to add a head and a tail to our log message.

package org.kodejava.example.util.logging;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.*;

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

        MyFormatter formatter = new MyFormatter();
        ConsoleHandler handler = new ConsoleHandler();
        handler.setFormatter(formatter);

        logger.addHandler(handler);
        logger.info("Example of creating custom formatter.");
        logger.warning("A warning message.");
        logger.severe("A severe message.");
    }
}

class MyFormatter extends Formatter {
    // Create a DateFormat to format the logger timestamp.
    private static final DateFormat df = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss.SSS");

    public String format(LogRecord record) {
        StringBuilder builder = new StringBuilder(1000);
        builder.append(df.format(new Date(record.getMillis()))).append(" - ");
        builder.append("[").append(record.getSourceClassName()).append(".");
        builder.append(record.getSourceMethodName()).append("] - ");
        builder.append("[").append(record.getLevel()).append("] - ");
        builder.append(formatMessage(record));
        builder.append("\n");
        return builder.toString();
    }

    public String getHead(Handler h) {
        return super.getHead(h);
    }

    public String getTail(Handler h) {
        return super.getTail(h);
    }
}

Below is an output produced by the custom formatter above.

01/05/2009 06:22:09.372 - [org.kodejava.example.util.logging.LogCustomFormatter.main] - [INFO] - Example of creating custom formatter.
01/05/2009 06:22:09.374 - [org.kodejava.example.util.logging.LogCustomFormatter.main] - [WARNING] - A warning message.
01/05/2009 06:22:09.374 - [org.kodejava.example.util.logging.LogCustomFormatter.main] - [SEVERE] - A severe message.

How do I prevent the logger send log messages to its parent logger?

To prevent log records being forwarded to the logger’s parent handlers we can
set false the useParentHandlers field using the
Logger.setUserParentHandlers(boolean useParentHandlers) method.

package org.kodejava.example.util.logging;

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

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

        //
        // Do not forward any log messages the the logger parent handlers.
        //
        logger.setUseParentHandlers(false);

        //
        // Specify a ConsoleHanlder for this logger instance.
        //
        logger.addHandler(new ConsoleHandler());
        logger.info("Logging an information message.");
    }
}

How do I set the formatter of logger handlers?

In this example we’ll see how to set the formatter for the logger handlers.
We set the formatter by calling the Handler.setFormatter() method.
In the code below we set a SimpleFormatter for our FileHandler
handler and XMLFormatter for the ConsoleHandler
handler.

This SimpleFormatter format the log in a plain text information
while on the other side the XMLFormatter format the log record in
XML format.

package org.kodejava.example.util.logging;

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

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

        try {
            //
            // Create a FileHanlder that will log to mylog.txt with a
            // SimpleFormatter.
            //
            FileHandler simpleHandler = new FileHandler("mylog.txt", true);
            simpleHandler.setFormatter(new SimpleFormatter());
            logger.addHandler(simpleHandler);

            //
            // Create a ConsoleHanlder that will log to the console with
            // an XMLFormatter.
            //
            ConsoleHandler consoleHandler = new ConsoleHandler();
            consoleHandler.setFormatter(new XMLFormatter());
            logger.addHandler(consoleHandler);

            //
            // Do not sent the message to parent handlers. 
            //
            logger.setUseParentHandlers(false);
        } catch (IOException e) {
            logger.log(Level.SEVERE, "Fail to create logger file handler.", e);
        }

        logger.info("Logging application information message.");
        logger.warning("Logging application warning message.");
    }
}