##// END OF EJS Templates
vcs: Use key lookup to explode if key is not available....
vcs: Use key lookup to explode if key is not available. The key has to be in the dictionary, otherwise something changed in the code and expoding here is better than hiding the error.

File last commit:

r1:854a839a default
r890:ed7b68ec default
Show More
logging.js
272 lines | 8.3 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);
},
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.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();