Thursday, April 11, 2013

Creating custom Logger Factory

Creating custom Logger Factory 

I hope that the following sample snippet will give you a better understanding how  to create the custom Logger Factory

1)  Logger.java
package com.sample.utility.loggers;

/**
 * This is an interface for application logger.It contains methods which
 * facilitate the logging.Implementing <code>Logger</code> interface will unify
 * most of the logging requirements and result in consistent logging system.
 *
 *
 * @author SUNILG
 * @version 1.0, 11 April 2013
 */
public interface Logger {

    /**
     * Logs the given string as a debug message, provided logging at
     * <tt>DEBUG</tt> level is enabled for the current logger.
     * <p>
     * Any <tt>appendThese</tt> arguments passed will be appended to the
     * message.
     *
     * @param message
     *            the message that needs to be logged.
     *
     * @param appendThese
     *            fragments which will be appended to the message.
     */
    void debug(String message, Object... appendThese);

    /**
     * Logs the given string as an information, provided logging at
     * <tt>INFO</tt> level is enabled for the current logger.
     * <p>
     * Any <tt>appendThese</tt> arguments passed will be appended to the
     * message.
     *
     * @param message
     *            the message that needs to be logged.
     *
     * @param appendThese
     *            fragments which will be appended to the message.
     */
    void info(String message, Object... appendThese);

    /**
     * Logs the given string as a warning message, provided logging at
     * <tt>WARN</tt> level is enabled for the current logger.
     * <p>
     * Any <tt>appendThese</tt> arguments passed will be appended to the
     * message.
     *
     * @param message
     *            the message that needs to be logged.
     *
     * @param appendThese
     *            fragments which will be appended to the message.
     */
    void warn(String message, Object... appendThese);

    /**
     * Logs the given string as an error message.
     *
     * @param message
     *            the message that needs to be logged.
     */
    void error(String message);

    /**
     * Logs the given string at the error level with the exception message.
     *
     * @param message
     *            the message that needs to be logged.
     *
     * @param throwable
     *            the <code>Throwable</code> to be logged.
     */
    void error(String message, Throwable throwable);

    /**
     * Logs the given string at the fatal level.
     *
     * @param message
     *            the message that needs to be logged.
     */
    void fatal(String message);

    /**
     * Logs the given string at the fatal level with the exception message.
     *
     * @param message
     *            the message that needs to be logged.
     * @param throwable
     *            the <code>Throwable</code> to be logged.
     */
    void fatal(String message, Throwable throwable);

    /**
     * Logs a method entry with the list of its parameters at debug level.
     *
     * @param methodName
     *            the string containing method name.
     *
     * @param params
     *            an array of the parameters of the method.
     */
    void entering(String methodName, Object... params);

    /**
     * Logs the exit from a method at debug level.
     *
     * @param methodName
     *            the string containing method name.
     */
    void exiting(String methodName);

    /**
     * Logs the exit from a method which returns a value at debug level.
     *
     * @param methodName
     *            the string containing method name.
     *
     * @param retVal
     *            the return value of the method.
     */
    void exiting(String methodName, Object retVal);

    /**
     * Changes the logging level of a current logger.
     * With this logging levels for a logger can be controlled dynamically.
     *
     * @param loggerLevel
     *            the logging level to be set
     */
    void setLoggerLevel(String loggerLevel);

    /**
     * Returns the <code>Level.DEBUG</code> status of the logger in context.
     *
     * @return boolean indicating whether debug is turned on or off
     *
     * @see org.apache.log4j.Level
     */
    boolean isDebugEnabled();

    /**
     * Returns the <code>Level.WARN</code> status of the logger in context.
     *
     * @return boolean indicating whether warn is turned on or off
     *
     * @see org.apache.log4j.Level
     */
    boolean isWarnEnabled();

    /**
     * Returns the <code>Level.INFO</code> status of the logger in context.
     *
     * @return boolean indicating whether info is turned on or off
     *
     * @see org.apache.log4j.Level
     */
    boolean isInfoEnabled();
}

2) LoggerFactory.java

package com.sample.utility.loggers;

import java.util.HashMap;
import java.util.Iterator;

import org.apache.log4j.Logger;

import com.sample.utility.utils.LogUtil;

/**
 * This class <code>LoggerFactory</code> provides the entry point to the logging
 * layer. On loading caches all the current loggers configured in the runtime
 * environment in a <code>Map</code> for later retrieval.
 *
 * The typical usage in getting a <code>EngineLogger</code> instance to start
 * logging is as shown below :
 *
 * <p>
 * <blockquote>
 *
 * <pre>
 * private static EngineLogger logger = LoggerFactory.getInstance().getLogger(
 * MyClass.class);
 * </pre>
 *
 * <p>
 * It can then use all the methods defined under <code>Logger</code> interface
 * appropriately.
 * </blockquote>
 *
 * @author SUNILG
 * @version 1.0, 11 April 2013
 */

public final class LoggerFactory {
    /**
     * Single ton instance for this class
     */
    private static LoggerFactory theInstance = new LoggerFactory();

    /**
     * Cache of loggers.
     */
    private HashMap logInstance = new HashMap();

    /**
     * Default Constructor- Caches all the system and root loggers.
     */
    private LoggerFactory() {

        try {

            // Get the current loggers configured
            Iterator i = LogUtil.getCurrentLoggers().iterator();

            SampleLogger log = null;
            Logger logger = null;

            // Loop through and cache the named loggers
            while (i.hasNext()) {
                logger = (Logger) i.next();
                log = new SampleLogger(logger);
                logInstance.put(logger.getName(), log);

            }

        } catch (Exception exception) {

            exception.printStackTrace();
            throw new RuntimeException("unknown Exception: "
                    + exception);

        }

    }

    /**
     * Returns the instance of this class.
     *
     * @return an instance of <code>LoggerFactory</code>
     */
    public static LoggerFactory getInstance() {

        return theInstance;

    }

    /**
     * Gets the instance of logger which is associated with the given class.
     * <p>
     * This method searches its cache for the logger instance with the given
     * class name.
     * <p>
     * If an instance of the logger is not found in the cache, then a new
     * instance of logger is created and returned.
     *
     * @param clazz
     *       a <code>Class</code> object interested in using the logger.
     *
     * @return an implementation of <code>Logger</code>
     */
    public SampleLogger getLogger(Class clazz) {
        String name = clazz.getName();

        SampleLogger log = (SampleLogger) logInstance.get(name);

        if (log == null) {

            synchronized (LoggerFactory.class) {
                log = new SampleLogger(clazz);

                logInstance.put(name, log);

            }
        }

        return log;
    }

    /**
     * Sets the logger with the <code>loggerName</code>
     * to the specified level <code>loggerLevel</code>.
     *
     * @param loggerName
     *            the name of the logger.This is used to retrieve the named
     *            logger instance
     * @param loggerLevel
     *            the loggerLevel to change
     */
    public void setCurrentLogger(String loggerName, String loggerLevel) {

        SampleLogger log = (SampleLogger) logInstance.get(loggerName);

        // Set the logger level of the named logger
        if (log != null) {
            log.setLoggerLevel(loggerLevel);
            logInstance.put(loggerName, log);
        }
    }
}

3) SampleLogger.java
/**
 *
 */
package com.sample.utility.loggers;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

/**
 * @author SUNILG
 * @version 1.0, 11 April 2013
 */
public class SampleLogger implements com.sample.utility.loggers.Logger {
    /**
     * Enter method prefix.
     */
    private static final String ENTER_PREFIX = " ENTERING METHOD : ";

    /**
     * Exit method prefix.
     */
    private static final String EXIT_PREFIX = " EXITING METHOD : ";

    /**
     * Parameter prefix.
     */
    private static final String PARAM_PREFIX = " PARAM";

    /**
     * Return value prefix.
     */
    private static final String RETURN_PREFIX = " RETURN VALUE = ";

    /**
     * Name of this class.
     */
    private static final String LOGGER_NAME = SampleLogger.class.getName();

    /**
     * Log4j logger for logging.
     */
    private final Logger logger;

    /**
     * Creates a logger for the given class.
     *
     * @param clazz
     *            the <code>Class</code> object interested in logging.
     */
    public SampleLogger(Class clazz) {
        logger = Logger.getLogger(clazz);
    }

    /**
     * Creates a logger with a given logger.This is used to load all the
     * predefined system loggers.
     *
     * @param logger
     *            a Log4j logger instance
     */
    public SampleLogger(Logger logger) {
        this.logger = logger;
    }

    /**
     * {@inheritDoc}
     */
    public void debug(String message, Object... appendThese) {
        if (!this.isDebugEnabled()) {
            return;
        }
        if (appendThese != null) {
            StringBuilder msg = new StringBuilder(message);

            for (Object appendThis : appendThese) {
                msg.append(appendThis);
            }

            message = msg.toString();
        }

        logger.log(LOGGER_NAME, Level.DEBUG, message, null);
    }

    /**
     * {@inheritDoc}
     */
    public void info(String message, Object... appendThese) {
        if (!this.isInfoEnabled()) {
            return;
        }
        if (appendThese != null) {
            StringBuilder msg = new StringBuilder(message);

            for (Object appendThis : appendThese) {
                msg.append(appendThis);
            }

            message = msg.toString();
        }

        logger.log(LOGGER_NAME, Level.INFO, message, null);
    }

    /**
     * {@inheritDoc}
     */
    public void warn(String message, Object... appendThese) {
        if (!this.isWarnEnabled()) {
            return;
        }
        if (appendThese != null) {
            StringBuilder msg = new StringBuilder(message);

            for (Object appendThis : appendThese) {
                msg.append(appendThis);
            }

            message = msg.toString();
        }

        logger.log(LOGGER_NAME, Level.WARN, message, null);
    }

    /**
     * {@inheritDoc}
     */

    public void error(String message) {
        logger.log(LOGGER_NAME, Level.ERROR, message, null);
    }

    /**
     * {@inheritDoc}
     */

    public void error(String message, Throwable throwable) {
        logger.log(LOGGER_NAME, Level.ERROR, message, throwable);
    }

    /**
     * {@inheritDoc}
     */

    public void fatal(String message) {
        logger.log(LOGGER_NAME, Level.FATAL, message, null);
    }

    /**
     * {@inheritDoc}
     */
    public void fatal(String message, Throwable throwable) {
        logger.log(LOGGER_NAME, Level.FATAL, message, throwable);
    }

    /**
     * {@inheritDoc}
     */
    public void entering(String methodName, Object... params) {
        logger.log(LOGGER_NAME, Level.DEBUG,
                this.getEnterMethodLogStr(methodName, params), null);

    } // end of method enterMethod

    /**
     * {@inheritDoc}
     */

    public void exiting(String methodName) {

        StringBuffer buf = new StringBuffer();
        buf.append(EXIT_PREFIX);
        buf.append(methodName + "(..)");

        logger.log(LOGGER_NAME, Level.DEBUG, buf.toString(), null);

    }

    /**
     * {@inheritDoc}
     */

    public void exiting(String methodName, Object retVal) {
        StringBuffer buf = new StringBuffer();
        buf.append(EXIT_PREFIX);
        buf.append(methodName + "(..)");
        buf.append(RETURN_PREFIX);
        buf.append("[ ");
        buf.append(retVal);
        buf.append(" ]");

        logger.log(LOGGER_NAME, Level.DEBUG, buf.toString(), null);

    }

    /**
     * {@inheritDoc}
     */
    public void setLoggerLevel(String loggerLevel) {

        if ("DEBUG".equals(loggerLevel)) {
            logger.setLevel(Level.DEBUG);
        }

        if ("INFO".equals(loggerLevel)) {
            logger.setLevel(Level.INFO);
        }

        if ("WARN".equals(loggerLevel)) {
            logger.setLevel(Level.WARN);
        }

        if ("ERROR".equals(loggerLevel)) {
            logger.setLevel(Level.ERROR);
        }

        if ("FATAL".equals(loggerLevel)) {
            logger.setLevel(Level.FATAL);
        }
    }

    /**
     * {@inheritDoc}
     */
    public boolean isDebugEnabled() {
        return logger.isDebugEnabled();
    }

    /**
     * {@inheritDoc}
     */
    public boolean isInfoEnabled() {
        return logger.isInfoEnabled();
    }

    /**
     * {@inheritDoc}
     */
    public boolean isWarnEnabled() {

        return logger.isEnabledFor(Level.WARN);

    }

    /**
     * Returns the log string for entry of a method.
     *
     * @param methodName
     *            a string containing the method name as the parameter.
     *
     * @param params
     *            an array of objects containing the parameters to the method.
     *
     * @return a string to be logged indicating the entry of this method.
     */
    private String getEnterMethodLogStr(String methodName, Object[] params) {
        StringBuffer buf = new StringBuffer(ENTER_PREFIX);
        buf.append(methodName + "(..)");

        if (params != null) {
            for (int i = 0; i < params.length; i++) {
                if (i > 0 && i != params.length) {
                    buf.append(",");
                }

                buf.append(PARAM_PREFIX);
                buf.append(i + 1);
                buf.append(" = [");
                buf.append(params[i]);
                buf.append("]");
            }
        }
        return buf.toString();
    }
}

4) LogUtil
package com.sample.utility.utils;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

import com.sample.utility.loggers.LoggerFactory;

/**
 * The <code>LogUtil</code> class contains a collection of public
 * static utility methods for logger used in the application.
 *
 *
 * @author SUNILG
 * @version 1.0, 11 April 2013
 */
public final class LogUtil {

    /**
     * The private constructor to prevent instantiation.
     */
    private LogUtil() {
    }

    /**
     * Sets the level of logging for the given loggerName.
     * This method retrieves the named logger instance
     * and modifies the Level.
     *
     * @param loggerName
     *            the name of the logger to which level has to be modified
     * @param loggerLevel
     *            the new level that has to set to <code>Logger</code>
     *            identified by the <code>loggerName</code>
     * @return a response containing appropriate message
     *
     * @see org.apache.log4j.Logger#getLogger(java.lang.String)
     * @see org.apache.log4j.Category#setLevel(org.apache.log4j.Level)
     *
     */
    public static String setLoggerLevel(
            String loggerName, String loggerLevel) {

        LoggerFactory.getInstance().
        setCurrentLogger(loggerName, loggerLevel);

        // response to the caller
        return "Logger verbosity set successfully, logger=" + loggerName
                + ", level=" + loggerLevel
                + ".  The change may affect"
                + " subordinate loggers.";
    }

    /**
     * Internal method to Retrieve all the current loggers from the logger
     * repository as a <code>Collection</code> instance.
     *
     * @return a Collection holding the Current Loggers
     */
    public static java.util.Collection getCurrentLoggers() {
        // Create an empty list to hold CurrentLoggers
        java.util.List loggers = new java.util.LinkedList();

        // Build the list with logger
        for (java.util.Enumeration e =
            org.apache.log4j.Logger.getRootLogger()
            .getLoggerRepository().getCurrentLoggers();
            e.hasMoreElements();) {
            Logger loggerImpl = (org.apache.log4j.Logger)
            e.nextElement();
            loggers.add(loggerImpl);
        }
        return loggers;
    }

    /**
     * Returns the current logging level of the given logger.
     *
     * @param logger
     *            the logger on which current <code>LEVEL</code> will be
     *            returned
     * @return the effective Level of the input <code>Logger</code>
     *
     * @see org.apache.log4j.Level
     */
    public static Level getCurrentLevel(Logger logger) {

        org.apache.log4j.Level level = logger.getEffectiveLevel();

        if (Level.ALL.equals(level)) {
            return Level.DEBUG;
        }
        if (Level.DEBUG.equals(level)) {
            return Level.DEBUG;
        }
        if (Level.INFO.equals(level)) {
            return Level.INFO;
        }
        if (Level.WARN.equals(level)) {
            return Level.WARN;
        }
        if (Level.ERROR.equals(level)) {
            return Level.ERROR;
        }
        if (Level.FATAL.equals(level)) {
            return Level.FATAL;
        }
        if (Level.OFF.equals(level)) {
            return Level.FATAL;
        }

        return null;
    }
}

No comments:

Post a Comment