/*
* EuroCarbDB, a framework for carbohydrate bioinformatics
*
* Copyright (c) 2006-2009, Eurocarb project, or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
* A copy of this license accompanies this distribution in the file LICENSE.txt.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* Last commit: $Rev: 1147 $ by $Author: glycoslave $ on $Date:: 2009-06-04 #$
*/
package org.eurocarbdb.util;
import java.util.Map;
import java.util.HashMap;
import java.util.Date;
/* class Logger *//************************************************
*
* Wrapper class for logging functions.
*
* java.util.logging.Logger *does not work as advertised*, and log4j
* requires an extra library jarfile just for logging. Therefore this
* class was created to fulfill the requirements of basic logging without
* using an external library, and to provide an abstraction over what
* logging system we are currently using.
*
* The API used here is a subset of the java.util.logging.Logger
* API (which is a copy of the log4j API). This is to make it easy to
* delgate logging to log4j or java logging as/when required.
*
* Final note: unlike java.util.logging.Logger, this class actually does work.
*
* Typical usage:
*
<pre>
<code>
import org.eurocarbdb.util.Logger;
class MyClass
{
private static final Logger log
= Logger.getLogger( MyClass.class.getName() );
public static void logging_demo()
{
// determines minimum log level for which log messages will be shown.
// defaults to Logger.Level.Info.
log.setLevel( Logger.Level.Debug2 );
// determines minimum log level that will show a small stack trace.
// defaults to Logger.Level.Warning.
log.setTraceLevel( Logger.Level.Warning );
// determines minimum log level that will show a timestamp.
// defaults to Logger.Level.Warning.
log.setTimestampLevel( Logger.Level.Warning );
log.debug3("a debug level 3 message");
log.debug2("a debug level 2 message");
log.debug("a debug message");
log.info("some info");
log.notice("a notice");
log.warning("a warning");
log.severe("a severe warning");
log.critical("a critical warning");
}
}
</code>
</pre>
*
* @author mjh
* @see java.util.logging.Logger
*/
public final class Logger
{
public enum Level
{
//~~~ ENUM VALUES ~~~//
/*
* Structure is:
*
* Name(
* <arbitrary severity integer>,
* <default string to put before log message>,
* <default string to put after log message>
* )
*/
/* Log level that always logs (duh). */
LogEverything( 0, "", "" ),
/* debug levels */
Debug4( 5, " (", ")" ),
Debug3( 10, " (", ")" ),
Debug2( 15, " (", ")" ),
Debug( 20, "(", ")" ),
/* general informational messages. default level is Info. */
Info( 25, "INFO: ", "" ),
Notice( 30, "NOTICE: ", "" ),
/* unexpected/problem messages. */
Warning( 50, "WARNING: ", "" ),
Severe( 100, "SEVERE: ", "" ),
Critical( 500, "CRITICAL: ", "" ),
/* Log level that never logs */
LogNothing( 999, "", "" ),
/* internal use for bypassing logging test. */
Unconditional( 1000, "", "")
;
//~~~ OBJECT DATA ~~~//
/** Arbitrary severity integer. */
public final int level;
/** String prepended to log message. */
final String before;
/** String appended to log message. */
final String after;
/* Constructor *//*****************************************
*
*/
Level( int level, String before, String after )
{
this.level = level;
this.before = before;
this.after = after;
}
} // end enum
//~~~ STATIC DATA ~~~//
/** The default lowest logging level for which logging messages will be shown. */
public static Level DefaultLogLevel = Level.Info;
/** The default lowest logging level for which stack traces for log messages
* will be shown. */
public static Level DefaultTraceLevel = Level.Warning;
/**The default lowest logging level for which timestamps for log messages
* will be shown. */
public static Level DefaultTimestampLevel = Level.Warning;
/** Private static hash of logger-id to Logger instance. */
private static final Map<String,Logger> LogLevel = new HashMap<String,Logger>();
//~~~ OBJECT DATA ~~~//
/** Unique logging identifier string. Can be any arbitrary string, but
* would usually be the name of the Logger client class or package. */
public final String id;
/** The logging level of this Logger instance. Log messages with Levels
* lower than this will be silently discarded. Defaults to DefaultLogLevel. */
public Level logLevel = DefaultLogLevel;
/** The lowest logging level for which stack traces will be shown
* for logging messages. */
public Level traceLevel = DefaultTraceLevel;
/** The lowest logging level for which timestamps will be shown
* for logging messages. */
public Level timestampLevel = DefaultTimestampLevel;
//~~~ STATIC METHODS ~~~//
/* getLogger *//***********************************************
*
* Static factory constructor for Logger instances. The given
* logger id may be any arbitrary string, but would usually be
* the name of the class or package in which this Logger will
* be used.
*/
public static final Logger getLogger( String logger_id )
{
Logger logger = LogLevel.get( logger_id );
if ( logger == null )
{
logger = new Logger( logger_id );
LogLevel.put( logger_id, logger );
}
return logger;
}
/* log *//*****************************************************
*
* Convenience method for trivial logging usage.
*/
public static final void log( String logger_id, Level severity, Object... messages )
{
Logger log = getLogger( logger_id );
// show message?
if ( log.logLevel.level > severity.level )
return;
// show message(s)
for ( Object m : messages )
if ( m instanceof Throwable )
((Throwable) m).printStackTrace();
else
System.err.println( severity.before + m.toString() + severity.after );
// show timestamp?
if ( log.timestampLevel.level <= severity.level )
{
System.err.println( severity.before
+ "[timestamp] "
+ new Date().toString()
+ severity.after
);
}
// show mini stack trace?
if ( log.traceLevel.level <= severity.level )
{
StackTraceElement[] ste = Thread.currentThread().getStackTrace();
for ( int i = 4; i < 8 && i < ste.length; i++ )
{
System.err.println( severity.before
+ "[traceback] method "
+ (i - 3)
+ ": "
+ ste[i].getMethodName()
+ " ("
+ ste[i].getFileName()
+ " line "
+ ste[i].getLineNumber()
+ ")"
+ severity.after
);
}
}
return;
}
//~~~ CONSTRUCTORS ~~~//
Logger( String id )
{
this.id = id;
}
//~~~ OBJECT METHODS ~~~//
/** Logs a debug level message. */
public void debug( Object... messages ) { log( id, Level.Debug, messages ); }
/** Logs a debug2 level message. */
public void debug2( Object... messages ) { log( id, Level.Debug2, messages ); }
/** Logs a debug3 level message. */
public void debug3( Object... messages ) { log( id, Level.Debug3, messages ); }
/** Logs a debug4 level message. */
public void debug4( Object... messages ) { log( id, Level.Debug4, messages ); }
/** Logs an info level message. */
public void info( Object... messages ) { log( id, Level.Info, messages ); }
/** Logs a notice level message. */
public void notice( Object... messages ) { log( id, Level.Notice, messages ); }
/** Logs a warning message. */
public void warning( Object... messages ) { log( id, Level.Warning, messages ); }
/** Logs a severe warning message. */
public void severe( Object... messages ) { log( id, Level.Severe, messages ); }
/** Logs a critical warning message. */
public void critical( Object... messages ) { log( id, Level.Critical, messages ); }
/** Logs an error message. */
public void error( Object... messages ) { log( id, Level.Critical, messages ); }
public void unconditionally( Object... messages ) { log( id, Level.Unconditional, messages ); }
/* isLoggable *//**********************************************
*
* Returns true if a message of the given level would be logged.
*/
public final boolean isLoggable( Level severity )
{
assert severity != null;
return ( this.logLevel.level <= severity.level );
}
public final boolean isDebugEnabled() { return this.logLevel.level <= Level.Debug.level; }
/* setLevel *//************************************************
*
* Sets logging level for this Logger instance; log messages with
* levels below the given Level will be silently discarded.
*/
public final void setLevel( Level level )
{
assert( level != null );
logLevel = level;
}
/* setTraceLevel *//*******************************************
*
* Sets the minimum logging level for which stack traces will be
* printed for log messages.
*/
public final void setTraceLevel( Level level )
{
assert( level != null );
traceLevel = level;
}
/* setTimestampLevel *//***************************************
*
* Sets the minimum logging level for which stack traces will be
* printed for timestamp messages.
*/
public final void setTimestampLevel( Level level )
{
assert( level != null );
timestampLevel = level;
}
}