Last active
December 21, 2015 18:19
-
-
Save theladyjaye/6346352 to your computer and use it in GitHub Desktop.
Simple port of python's std logging module.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
define(function(require, exports, module){ | |
var test = {}; | |
var _ = require('underscore'), | |
_loggers = {}, | |
_levelNames = { | |
0: 'NOTSET', | |
1: 'TRACE', | |
2: 'DEBUG', | |
3: 'INFO', | |
4: 'WARN', | |
5: 'ERROR', | |
NOTSET: 0, | |
TRACE: 1, | |
DEBUG: 2, | |
INFO: 3, | |
WARN: 4, | |
ERROR: 5}; | |
var PlaceHolder = function(options){ | |
var logger = options.logger; | |
this.loggerMap = {}; | |
this.loggerMap[logger] = null; | |
}; | |
_.extend(PlaceHolder.prototype, { | |
append: function(logger){ | |
if (!_.has(this.loggerMap, logger)){ | |
this.loggerMap[logger] = null; | |
} | |
} | |
}); | |
var Logger = function(options){ | |
var level = options.level || _levelNames.NOTSET; | |
options.level = _checkLevel(level); | |
_.extend(this, options); | |
var noop = function(){}; | |
this.trace = noop; | |
this.debug = noop; | |
this.info = noop; | |
this.warn = noop; | |
this.error = noop; | |
}; | |
_.extend(Logger.prototype, { | |
setLevel: function(level){ | |
this.level = _checkLevel(level); | |
var prefix = this.name; | |
_.each(_loggers, function(v, k){ | |
if (k.indexOf(prefix) === 0 && v instanceof Logger){ | |
_applyLevelLoggers(v); | |
} | |
}); | |
}, | |
isEnabledFor: function(level){ | |
return level >= this.getEffectiveLevel(); | |
}, | |
getEffectiveLevel: function(){ | |
var logger = this; | |
while(logger){ | |
if(logger.level){ | |
return logger.level; | |
} | |
logger = logger.parent; | |
} | |
return 0; | |
} | |
}); | |
function config(data){ | |
_.each(data.loggers, function(v, k){ | |
var logger = getLogger(k); | |
logger.setLevel(v.level); | |
}); | |
} | |
function getLogger(name){ | |
name = name || 'root'; | |
var result = null; | |
if (_.has(_loggers, name)){ | |
result = _loggers[name]; | |
if (result instanceof PlaceHolder){ | |
var placeholder = result; | |
result = new Logger({name: name}); | |
_loggers[name] = result; | |
_applyChildren(placeholder, result); | |
_applyParents(result); | |
//_applyLevelLoggers(result); | |
} | |
} else { | |
result = new Logger({name: name}); | |
_loggers[name] = result; | |
_applyParents(result); | |
//_applyLevelLoggers(result); | |
} | |
return result; | |
} | |
function _applyLevelLoggers(logger){ | |
var maxLevel = _levelNames.ERROR; | |
var noop = function(){}; | |
while (maxLevel > 0){ | |
var name = _levelNames[maxLevel].toLowerCase(); | |
if (logger.isEnabledFor(maxLevel)){ | |
logger[name] = _consoleMethod(name); | |
} else { | |
logger[name] = noop; | |
} | |
maxLevel--; | |
} | |
} | |
function _applyChildren(placeholder, logger){ | |
var name = logger.name, | |
namelen = name.length; | |
_.each(placeholder.loggerMap, function(v, c){ | |
if(c.parent.name.substring(0, namelen) != name){ | |
logger.parent = c.parent; | |
c.parent = logger; | |
} | |
}); | |
} | |
function _applyParents(logger){ | |
var name = logger.name, | |
i = name.lastIndexOf('.'), | |
parts = name.substring(0, i).split('.'), | |
result = null; | |
while (parts.length > 0 && !result){ | |
var substr = parts.join('.'); | |
if(!_.has(_loggers, substr)){ | |
_loggers[substr] = new PlaceHolder({logger:logger}); | |
} else { | |
var obj = _loggers[substr]; | |
if (obj instanceof Logger){ | |
result = obj; | |
} else { | |
if(obj instanceof PlaceHolder){ | |
obj.append(logger); | |
} | |
} | |
} | |
parts.pop(); | |
} | |
if (!result){ | |
result = _loggers.root; | |
} | |
logger.parent = result; | |
} | |
function _checkLevel(level){ | |
// is int? | |
if (typeof level === 'number' && level % 1 === 0){ | |
return level; | |
} | |
return _levelNames[level.toUpperCase()]; | |
} | |
// the following 2 functions courtesy of: | |
// https://github.com/pimterry/loglevel/blob/master/lib/loglevel.js#L23-L46 | |
function _consoleMethod(name){ | |
var noop = function () {}; | |
if (typeof console === 'undefined') { | |
return noop; | |
} else if (console[name] === undefined) { | |
return _bindToConsole(console, 'log') || noop; | |
} else { | |
return _bindToConsole(console, name); | |
} | |
} | |
function _bindToConsole(console, methodName) { | |
var method = console[methodName]; | |
if (method.bind === undefined) { | |
if (Function.prototype.bind === undefined) { | |
return function() { | |
method.apply(console, arguments); | |
}; | |
} else { | |
return Function.prototype.bind(console); | |
} | |
} else { | |
return method.bind(console); | |
} | |
} | |
_loggers.root = new Logger({'name': 'root', 'level':'notset'}); | |
module.exports.getLogger = getLogger; | |
module.exports.config = config; | |
}); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage
You will get this on your console:
Logs are in a hierarchy, so if the logger you request does not have a level set, it will inherit the level from it's parent:
The above will log nothing, we did not set a level on
log2
so it inherited the level fromlog1
, in this case warn, so our log of info will not pass.Calling
logging.getLogger()
with no arguments will return the root logger. With the inherited level system in play you can do this:You can also centralize your config for all of your loggers:
Enabling you to tune the logging noise activating and deactivating logging as you need.
Because the loggers exist in a hierarchy, you can apply a configuration to everything with the config as well instead of being granular: