// Log: A simple logging facility for ChucK
//
// Loosely modeled after logging packages in other languages, Log
// allows you to sprinkle your code with print messages tagged with
// different severity levels. What gets printed at run time depends
// on the setting of the log severity level. The levels (from lowest
// to highest severity) are:
//
// TRACE
// DEBUG
// INFO
// WARN
// ERROR
// FATAL
//
// A simple example of usage:
// ================
// class ArrayFns {
// fun int iterate(Object things[]) {
// Log.debug(this, "entering iterate()");
// if (things == null) {
// Log.warn(this, "null array, returning 0");
// return 0;
// }
// for (0 => int i; i<things.size(); i++) {
// if (Log.severity(Log.TRACE)) Log.log(this, "iterate(), processing " + i);
// process(things[i]);
// }
// things.size() => int retval;
// if (Log.severity(Log.DEBUG)) Log.log(this, "exiting iterate() with " + retval);
// return retval;
// }
// }
// ================
// The explanation:
//
// The line:
// Log.debug(this, "entering iterate()");
// will print the message if Log.set_severity() is DEBUG or TRACE.
//
// The line:
// Log.warn(this, "null array, returning 0");
// will print the message if Log.set_severity() is WARN or lower
// (WARN, INFO, DEBUG or TRACE).
//
// The line:
// if (Log.severity(TRACE)) Log.log(this, "iterate(), count=" + i);
// is equivalent to:
// Log.trace(this, "iterate(), count=" + i);
// except that the latter form will always evaluate its arguments,
// which in this case causes string catenation. You can avoid the
// extra evaluation by using the first form, which will call Log.log()
// iff the current severity level is TRACE. This is especially useful
// in inner loops that are called often, or if the construction of the
// error message itself is particularly costly.
//
// ==== Authors:
// ==== Revision History:
// 20100321_214041: Initial Version
// ====
public class Log {
static int TRACE;
static int DEBUG;
static int INFO;
static int WARN;
static int ERROR;
static int FATAL;
static int _severity;
fun static void init() {
0 => TRACE;
1 => DEBUG;
2 => INFO;
3 => WARN;
4 => ERROR;
5 => FATAL;
set_severity(WARN);
}
// get/set the severity level
fun static int get_severity() { return _severity; }
fun static void set_severity(int severity) { severity => _severity; }
// Return true if Log is at severity or lower
fun static int severity(int level) { return level >= _severity; }
fun static void trace(string msg) { log_if(TRACE, msg); }
fun static void trace(Object o, string msg) { log_if(TRACE, o, msg); }
fun static void debug(string msg) { log_if(DEBUG, msg); }
fun static void debug(Object o, string msg) { log_if(DEBUG, o, msg); }
fun static void info(string msg) { log_if(INFO, msg); }
fun static void info(Object o, string msg) { log_if(INFO, o, msg); }
fun static void warn(string msg) { log_if(WARN, msg); }
fun static void warn(Object o, string msg) { log_if(WARN, o, msg); }
fun static void error(string msg) { log_if(ERROR, msg); }
fun static void error(Object o, string msg) { log_if(ERROR, o, msg); }
fun static void fatal(string msg) { log_if(FATAL, msg); }
fun static void fatal(Object o, string msg) { log_if(FATAL, o, msg); }
// Conditionally log
fun static void log_if(int level, string msg) { if (severity(level)) log(msg); }
fun static void log_if(int level, Object o, string msg) { if (severity(level)) log(o, msg); }
// Unconditionally log
fun static void log(string msg) { log("[toplevel]", msg); }
fun static void log(Object o, string msg) { <<< now, me, o.toString(), msg >>>; }
}
// setup static constants and defaults at load time.
Log.init();