/** * Copyright 2007-2008 University Of Southern California * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package edu.isi.pegasus.common.logging.logger; import edu.isi.pegasus.common.logging.LogManager; import edu.isi.pegasus.common.logging.LogFormatter; import java.util.Collection; import org.apache.log4j.Logger; import org.apache.log4j.Level; import org.apache.log4j.Appender; import org.apache.log4j.PropertyConfigurator; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.PatternLayout; import java.util.Enumeration; import java.util.Properties; /** * A Log4j implementation of the LogManager interface. Using this allows us * us log messages using Log4j * * @author Karan Vahi * @version $Revision$ */ public class Log4j extends LogManager{ /** * The property that specifies the path to the log4j properties file. */ private static final String LOG4J_CONF_PROPERTY = "log4j.conf"; //level constants that loosely match Log4J and are used //to generate the appropriate mask values. /** * The handle to a log4j logger object. */ private Logger mLogger; /** * Keeps track of log4j's root logger as singleton. */ private static Logger mRoot; /** * Initializes the root logger when this class is loaded. */ static { if ( (mRoot = Logger.getRootLogger()) != null ) { //get hold of all appenders and override the console appender for ( Enumeration e = mRoot.getAllAppenders(); e.hasMoreElements(); ){ Appender a = ( Appender )e.nextElement(); if( a instanceof ConsoleAppender ){ //set the layout of the console appender //this can be overriden by the log4j.properties file a.setLayout( new PatternLayout("%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p [%c{1}] %m%n") ); } } mRoot.setLevel( Level.INFO ); mRoot.debug( "starting" ); } } /** * The properties passed at runtime */ private Properties mProperties; /** * The constructor. */ public Log4j(){ //configure properties through log4j.properties file mLogger = Logger.getLogger( "pegasus" ); } /** * Sets the log formatter to use for formatting the messages. * * @param formatter the formatter to use. * @param properties properties that the underlying implementations understand */ public void initialize( LogFormatter formatter, Properties properties ){ mLogFormatter = formatter; mProperties = properties; //set formatter to pegasus always for time being mLogFormatter.setProgramName( "pegasus" ); //specify the path to the log4j properties file if specified. String conf = properties.getProperty( Log4j.LOG4J_CONF_PROPERTY); if( conf != null ){ PropertyConfigurator.configure( conf ) ; } } /** * Log a message that connects the parent entities with the * children. For e.g. can we use to create the log messages connecting the * jobs with the workflow they are part of. They are by default logged * to INFO level * * @param parentType the type of parent entity * @param parentID the id of the parent entity * @param childIDType the type of children entities * @param childIDs Collection of children id's * */ public void logEntityHierarchyMessage( String parentType, String parentID, String childIDType, Collection<String> childIDs ){ this.logEntityHierarchyMessage( parentType, parentID, childIDType, childIDs, LogManager.INFO_MESSAGE_LEVEL ); } /** * Sets the debug level. All those messages are logged which have a * level less than equal to the debug level. * * @param level the level to which the debug level needs to be set to. */ public void setLevel(Level level){ setLevel( level, true ); } /** * Sets the debug level. All those messages are logged which have a * level less than equal to the debug level. In addition the info messages * are always logged. * * @param level the level to which the debug level needs to be set to. */ public void setLevel(int level){ setLevel( level, true ); } /** * Sets the debug level. All those messages are logged which have a * level less than equal to the debug level. In case the boolean info * is set, all the info messages are also logged. * * @param level the level to which the debug level needs to be set to. * @param info boolean denoting whether the INFO messages need to be * logged or not. */ protected void setLevel( int level, boolean info){ Level l = Level.ALL; switch( level ){ case LogManager.FATAL_MESSAGE_LEVEL: l = Level.FATAL; break; case LogManager.ERROR_MESSAGE_LEVEL: l = Level.ERROR; break; case LogManager.WARNING_MESSAGE_LEVEL: l = Level.WARN; break; case LogManager.CONFIG_MESSAGE_LEVEL: l = Level.INFO; break; case LogManager.INFO_MESSAGE_LEVEL: l = Level.INFO; break; case LogManager.DEBUG_MESSAGE_LEVEL: l = Level.DEBUG; break; } mLogger.setLevel( l ); } /** * Sets the debug level. All those messages are logged which have a * level less than equal to the debug level. In case the boolean info * is set, all the info messages are also logged. * * @param level the level to which the debug level needs to be set to. * @param info boolean denoting whether the INFO messages need to be * logged or not. */ protected void setLevel(Level level, boolean info){ mDebugLevel = level.toInt(); mLogger.setLevel( level ); } /** * Returns the debug level. * * @return the level to which the debug level has been set to. */ public int getLevel(){ return mDebugLevel; } /** * Sets both the output writer and the error writer to the same * underlying writer. * * @param out is the name of a file to append to. Special names are * <code>stdout</code> and <code>stderr</code>, which map to the * system's respective streams. * */ public void setWriters(String out){ throw new UnsupportedOperationException( "Log4jLogger does not support setWriters(out)" ); } /** * Logs the exception on the appropriate queue if the level of the message * is less than or equal to the level set for the Logger. For INFO level * message, the boolean indicating that a completion message is to follow * is set to true always. * * @param message the message to be logged. * @param e the exception to be logged * @param level the level on which the message has to be logged. * * @see #setLevel(int) * @see #log(String,int) */ public void log( String message, Exception e, int level ){ switch( level ){ case LogManager.FATAL_MESSAGE_LEVEL: mLogger.fatal( message, e ); break; case LogManager.ERROR_MESSAGE_LEVEL: mLogger.error( message, e ); break; case LogManager.WARNING_MESSAGE_LEVEL: mLogger.warn( message, e ); break; case LogManager.CONFIG_MESSAGE_LEVEL: mLogger.info( message, e ); break; case LogManager.INFO_MESSAGE_LEVEL: mLogger.info( message, e ); break; case LogManager.DEBUG_MESSAGE_LEVEL: mLogger.debug( message, e ); break; } } /** * Logs the message on the appropriate queue if the level of the message * is less than or equal to the level set for the Logger. For INFO level * message, the boolean indicating that a completion message is to follow * is set to true always. * * @param message the message to be logged. * @param level the level on which the message has to be logged. * * @see #setLevel(int) */ protected void logAlreadyFormattedMessage(String message, int level){ switch( level ){ case LogManager.FATAL_MESSAGE_LEVEL: mLogger.fatal( message ); break; case LogManager.ERROR_MESSAGE_LEVEL: mLogger.error( message ); break; case LogManager.WARNING_MESSAGE_LEVEL: mLogger.warn( message ); break; case LogManager.CONFIG_MESSAGE_LEVEL: mLogger.info( message ); break; case LogManager.INFO_MESSAGE_LEVEL: mLogger.info( message ); break; case LogManager.DEBUG_MESSAGE_LEVEL: mLogger.debug( message ); break; } } /** * Logs the completion message on the basis of the debug level. * * @param level the debug level of the start message for whose completion * you want. */ public void logEventCompletion( int level ){ String message = mLogFormatter.getEndEventMessage(); logAlreadyFormattedMessage( message , level ); mLogFormatter.popEvent(); } }