/**
* Helios, OpenSource Monitoring
* Brought to you by the Helios Development Group
*
* Copyright 2007, Helios Development Group and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*
*/
package org.helios.apmrouter.codahale;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import org.helios.apmrouter.jmx.ConfigurationHelper;
/**
* <p>Title: SimpleLogger</p>
* <p>Description: Zero framework logger</p>
* <p>Company: Helios Development Group LLC</p>
* @author Whitehead (nwhitehead AT heliosdev DOT org)
* <p><code>org.helios.apmrouter.codahale.SimpleLogger</code></p>
*/
public class SimpleLogger {
/** The property name to configure the simple logger level */
public static final String LEVEL_PROP = "org.helios.simplelogger.level";
/** The default level if no level is defined */
public static final Level DEFAULT_LEVEL = Level.INFO;
/** The default level if an invalid level is defined */
public static final Level INVALID_LEVEL = Level.DEBUG;
/** The current level */
public static Level level = DEFAULT_LEVEL;
static {
level = Level.forName(ConfigurationHelper.getSystemThenEnvProperty(LEVEL_PROP, null));
System.setProperty(LEVEL_PROP, level.name());
}
/**
* Returns the SimpleLogger's current level
* @return the SimpleLogger's current level
*/
public static Level getLevel() {
return level;
}
/**
* <p>Title: Level</p>
* <p>Description: Enumerates the verbosity levels of the {@link SimpleLogger}</p>
* <p>Company: Helios Development Group LLC</p>
* @author Whitehead (nwhitehead AT heliosdev DOT org)
* <p><code>org.helios.apmrouter.codahale.SimpleLogger.Level</code></p>
*/
public static enum Level {
/** Logging turned off */
OFF(null),
/** Logs fatals only to System.err */
FATAL(System.err),
/** Logs errors and below to System.err */
ERROR(System.err),
/** Logs warnings and below to System.err */
WARN(System.err),
/** Logs info and below to System.out */
INFO(System.out),
/** Logs debug and below to System.out */
DEBUG(System.out),
/** Logs everything to System.out */
TRACE(System.out);
/**
* Determines if the passed level enables logging vs. this level
* @param otherLevel The level to compare to
* @return true if logging is enabled, false otherwise.
*/
public boolean isEnabledFor(Level otherLevel) {
if(otherLevel==OFF) return false;
return ordinal()>=otherLevel.ordinal();
}
/**
* Determines if the passed name is a valid level
* @param name the name to test
* @return true if the passed name is a valid level, false otherwise
*/
public static boolean isValidLevel(CharSequence name) {
if(name==null) return false;
try {
Level.valueOf(name.toString().trim().toUpperCase());
return true;
} catch (Exception ex) {
return false;
}
}
/**
* Returns a level for the passed name.
* If the passed name is null or empty, returns the default level.
* If the passed name is invalid, returns the invalid level.
* @param name The name to get the level for
* @return a level
*/
public static Level forName(CharSequence name) {
if(name==null || name.toString().trim().isEmpty()) return DEFAULT_LEVEL;
if(!isValidLevel(name)) return INVALID_LEVEL;
return Level.valueOf(name.toString().trim().toUpperCase());
}
private Level(PrintStream ps) {
this.ps = ps;
}
private final PrintStream ps;
/**
* Returns the print stream for this level
* @return the ps the print stream for this level
*/
public PrintStream getPs() {
return ps;
}
}
/**
* Issues a trace level logging request
* @param msgs The objects to format into a log message
*/
public static void trace(Object...msgs) {
logAtLevel(Level.TRACE, msgs);
}
/**
* Issues a debug level logging request
* @param msgs The objects to format into a log message
*/
public static void debug(Object...msgs) {
logAtLevel(Level.DEBUG, msgs);
}
/**
* Issues an info level logging request
* @param msgs The objects to format into a log message
*/
public static void info(Object...msgs) {
logAtLevel(Level.INFO, msgs);
}
/**
* Issues a warn level logging request
* @param msgs The objects to format into a log message
*/
public static void warn(Object...msgs) {
logAtLevel(Level.WARN, msgs);
}
/**
* Issues a error level logging request
* @param msgs The objects to format into a log message
*/
public static void error(Object...msgs) {
logAtLevel(Level.ERROR, msgs);
}
/**
* Issues a fatal level logging request
* @param msgs The objects to format into a log message
*/
public static void fatal(Object...msgs) {
logAtLevel(Level.FATAL, msgs);
}
/**
* Forwards the logging directive if the current level is enabled for the passed level
* @param l The requested level
* @param msgs The logged messages
*/
protected static void logAtLevel(Level l, Object...msgs) {
if(level.isEnabledFor(l)) {
l.ps.println(format(l, msgs));
}
}
/**
* Formats the passed objects into a loggable string.
* If the last object is a {@link Throwable}, it will be formatted into a stack trace.
* @param level The level at which this log is being made
* @param msgs The objects to log
* @return the loggable string
*/
public static String format(Level level, Object...msgs) {
if(msgs==null||msgs.length<1) return "";
StringBuilder b = new StringBuilder(level.name());
b.append(" [").append(Thread.currentThread().getName()).append("]");
int c = msgs.length-1;
for(int i = 0; i <= c; i++) {
if(i==c && msgs[i] instanceof Throwable) {
b.append(formatStackTrace((Throwable)msgs[i]));
} else {
b.append(msgs[i]);
}
}
return b.toString();
}
/**
* Formats a throwable's stack trace
* @param t The throwable to format
* @return the formatted stack trace
*/
public static String formatStackTrace(Throwable t) {
if(t==null) return "";
ByteArrayOutputStream baos = new ByteArrayOutputStream();
t.printStackTrace(new PrintStream(baos, true));
try {
baos.flush();
} catch (IOException e) {
}
return baos.toString();
}
}