|
|
/**
|
|
|
* 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();
|
|
|
|