##// END OF EJS Templates
fix(tests): added ability for test to get an up-to-date version mercurial.
fix(tests): added ability for test to get an up-to-date version mercurial.

File last commit:

r4335:049df98d default
r5653:11c8ab5c tip default
Show More
logging.js
277 lines | 8.4 KiB | application/javascript | JavascriptLexer
/**
* LOGGING CONFIG
*
*
Usage:
Logger.debug("I'm a debug message!");
Logger.info("OMG! Check this window out!", window);
Logger.warn("Purple Alert! Purple Alert!");
Logger.error("HOLY SHI... no carrier.");
// Only log WARN and ERROR messages.
Logger.setLevel(Logger.WARN);
Logger.debug("Donut machine is out of pink ones"); // Not a peep.
Logger.warn("Asteroid detected!"); // yes show
// Retrieve a named logger and store it for use.
var myLogger = Logger.get('ModuleA');
myLogger.info("FizzWozz starting up");
// This logger instance can be configured independent of
// all others (including the global one).
myLogger.setLevel(Logger.WARN);
// As it's the same instance being returned each time, you
// don't have to store a reference:
Logger.get('ModuleA').warn('FizzWozz combombulated!");
*/
/*!
* js-logger - http://github.com/jonnyreeves/js-logger
* Jonny Reeves, http://jonnyreeves.co.uk/
* js-logger may be freely distributed under the MIT license.
*/
(function (global) {
"use strict";
// Top level module for the global, static logger instance.
var Logger = { };
// For those that are at home that are keeping score.
Logger.VERSION = "1.0.0";
// Function which handles all incoming log messages.
var logHandler;
// Map of ContextualLogger instances by name; used by Logger.get() to return the same named instance.
var contextualLoggersByNameMap = {};
// Polyfill for ES5's Function.bind.
var bind = function(scope, func) {
return function() {
return func.apply(scope, arguments);
};
};
// Super exciting object merger-matron 9000 adding another 100 bytes to your download.
var merge = function () {
var args = arguments, target = args[0], key, i;
for (i = 1; i < args.length; i++) {
for (key in args[i]) {
if (!(key in target) && args[i].hasOwnProperty(key)) {
target[key] = args[i][key];
}
}
}
return target;
};
// Helper to define a logging level object; helps with optimisation.
var defineLogLevel = function(value, name) {
return { value: value, name: name };
};
// Predefined logging levels.
Logger.DEBUG = defineLogLevel(1, 'DEBUG');
Logger.INFO = defineLogLevel(2, 'INFO');
Logger.TIME = defineLogLevel(3, 'TIME');
Logger.WARN = defineLogLevel(4, 'WARN');
Logger.ERROR = defineLogLevel(8, 'ERROR');
Logger.OFF = defineLogLevel(99, 'OFF');
// Inner class which performs the bulk of the work; ContextualLogger instances can be configured independently
// of each other.
var ContextualLogger = function(defaultContext) {
this.context = defaultContext;
this.setLevel(defaultContext.filterLevel);
this.log = this.info; // Convenience alias.
};
ContextualLogger.prototype = {
// Changes the current logging level for the logging instance.
setLevel: function (newLevel) {
// Ensure the supplied Level object looks valid.
if (newLevel && "value" in newLevel) {
this.context.filterLevel = newLevel;
}
},
// Is the logger configured to output messages at the supplied level?
enabledFor: function (lvl) {
var filterLevel = this.context.filterLevel;
return lvl.value >= filterLevel.value;
},
debug: function () {
this.invoke(Logger.DEBUG, arguments);
},
info: function () {
this.invoke(Logger.INFO, arguments);
},
warn: function () {
this.invoke(Logger.WARN, arguments);
},
warning: function () {
this.invoke(Logger.WARN, arguments);
},
error: function () {
this.invoke(Logger.ERROR, arguments);
},
time: function (label) {
if (typeof label === 'string' && label.length > 0) {
this.invoke(Logger.TIME, [ label, 'start' ]);
}
},
timeEnd: function (label) {
if (typeof label === 'string' && label.length > 0) {
this.invoke(Logger.TIME, [ label, 'end' ]);
}
},
// Invokes the logger callback if it's not being filtered.
invoke: function (level, msgArgs) {
if (logHandler && this.enabledFor(level)) {
logHandler(msgArgs, merge({ level: level }, this.context));
}
}
};
// Protected instance which all calls to the to level `Logger` module will be routed through.
var globalLogger = new ContextualLogger({ filterLevel: Logger.OFF });
// Configure the global Logger instance.
(function() {
// Shortcut for optimisers.
var L = Logger;
L.enabledFor = bind(globalLogger, globalLogger.enabledFor);
L.debug = bind(globalLogger, globalLogger.debug);
L.time = bind(globalLogger, globalLogger.time);
L.timeEnd = bind(globalLogger, globalLogger.timeEnd);
L.info = bind(globalLogger, globalLogger.info);
L.warn = bind(globalLogger, globalLogger.warn);
L.warning = bind(globalLogger, globalLogger.warning);
L.error = bind(globalLogger, globalLogger.error);
// Don't forget the convenience alias!
L.log = L.info;
}());
// Set the global logging handler. The supplied function should expect two arguments, the first being an arguments
// object with the supplied log messages and the second being a context object which contains a hash of stateful
// parameters which the logging function can consume.
Logger.setHandler = function (func) {
logHandler = func;
};
// Sets the global logging filter level which applies to *all* previously registered, and future Logger instances.
// (note that named loggers (retrieved via `Logger.get`) can be configured independently if required).
Logger.setLevel = function(level) {
// Set the globalLogger's level.
globalLogger.setLevel(level);
// Apply this level to all registered contextual loggers.
for (var key in contextualLoggersByNameMap) {
if (contextualLoggersByNameMap.hasOwnProperty(key)) {
contextualLoggersByNameMap[key].setLevel(level);
}
}
};
// Retrieve a ContextualLogger instance. Note that named loggers automatically inherit the global logger's level,
// default context and log handler.
Logger.get = function (name) {
// All logger instances are cached so they can be configured ahead of use.
return contextualLoggersByNameMap[name] ||
(contextualLoggersByNameMap[name] = new ContextualLogger(merge({ name: name }, globalLogger.context)));
};
// Configure and example a Default implementation which writes to the `window.console` (if present).
Logger.useDefaults = function(defaultLevel) {
// Check for the presence of a logger.
if (typeof console === "undefined") {
return;
}
// Map of timestamps by timer labels used to track `#time` and `#timeEnd()` invocations in environments
// that don't offer a native console method.
var timerStartTimeByLabelMap = {};
// Support for IE8+ (and other, slightly more sane environments)
var invokeConsoleMethod = function (hdlr, messages) {
Function.prototype.apply.call(hdlr, console, messages);
};
Logger.setLevel(defaultLevel || Logger.DEBUG);
Logger.setHandler(function(messages, context) {
var hdlr = console.log;
// append INFO/DEBUG etc into the messages
var levelPrefix = ((context.level.name+" ").toUpperCase()).substr(0,6);
messages[0] = levelPrefix + messages[0];
// Prepend the logger's name to the log message for easy identification.
if (context.name) {
messages[0] = "[" + context.name + "] " + messages[0];
}
if (context.level === Logger.TIME) {
if (messages[1] === 'start') {
if (console.time) {
console.time(messages[0]);
}
else {
timerStartTimeByLabelMap[messages[0]] = new Date().getTime();
}
}
else {
if (console.timeEnd) {
console.timeEnd(messages[0]);
}
else {
invokeConsoleMethod(hdlr, [ messages[0] + ': ' +
(new Date().getTime() - timerStartTimeByLabelMap[messages[0]]) + 'ms' ]);
}
}
}
else {
// Delegate through to custom warn/error loggers if present on the console.
if (context.level === Logger.WARN && console.warn) {
hdlr = console.warn;
} else if (context.level === Logger.ERROR && console.error) {
hdlr = console.error;
} else if (context.level === Logger.INFO && console.info) {
hdlr = console.info;
}
invokeConsoleMethod(hdlr, messages);
}
});
};
// Export to popular environments boilerplate.
if (typeof define === 'function' && define.amd) {
define(Logger);
}
else if (typeof module !== 'undefined' && module.exports) {
module.exports = Logger;
}
else {
Logger._prevLogger = global.Logger;
Logger.noConflict = function () {
global.Logger = Logger._prevLogger;
return Logger;
};
global.Logger = Logger;
}
}(this));
// init defaults
Logger.useDefaults();