noot
Version:
High quality, well tested, lightweight object oriented toolset for Node.js
254 lines (223 loc) • 5.53 kB
JavaScript
/**
* Dependencies
*/
require('colors');
var _ = require('lodash');
var util = require('util');
var NOOT = require('../../')('object');
/***********************************************************************************************************************
* Simple logger to display/write/send nice logs :
* - Hierarchic logging levels, choose what you want to see in your logs
* - Configurable transport method : simply override 'writeLog' method, default is console logging
*
* @class Logger
* @namespace NOOT
* @extends NOOT.Object
* @constructor
**********************************************************************************************************************/
var Logger = NOOT.Object.extend({
level: null,
transportCallback: NOOT.noop,
shouldStyle: true,
_level: null,
_styles: null,
/**
* Constructor
*/
init: function() {
this.setLevel(this.level);
this.setStyles();
},
/**
* Trace logging level
*/
trace: function() {
if (this._level <= Logger.levels.TRACE) {
return this._buildAndSend(arguments, 'trace');
}
},
/**
* Debug log level
*/
debug: function() {
if (this._level <= Logger.levels.DEBUG) {
return this._buildAndSend(arguments, 'debug');
}
},
/**
* Info log level
*/
info: function() {
if (this._level <= Logger.levels.INFO) {
return this._buildAndSend(arguments, 'info');
}
},
/**
* Warn log level
*/
warn: function() {
if (this._level <= Logger.levels.WARN) {
return this._buildAndSend(arguments, 'warn');
}
},
/**
* Error level log
*/
error: function() {
if (this._level <= Logger.levels.ERROR) {
return this._buildAndSend(arguments, 'error');
}
},
/**
* Application level log
*/
announce: function() {
if (this._level !== Logger.levels.OFF) {
return this._buildAndSend(arguments, 'announce');
}
},
/**
* High visibility log
*/
highlight: function() {
if (this._level !== Logger.levels.OFF) {
return this._buildAndSend(arguments, 'highlight');
}
},
/**
* Format message before logging
*
* @param {String} message
* @param {String} [level]
* @returns {String}
*/
formatMessage: function(message) {
return message;
},
/**
* Transport method(s)
*
* @param {String} message
* @param {String} level
* @param {Function} callback
*/
transport: function(message, level, callback) {
console.log(message);
return callback();
},
/**
* Define logging styles
*
* @param {Object} value
*/
setStyles: function(value) {
this._styles = Logger._buildStylesConfig(_.merge({}, Logger.DEFAULTS.styles, value));
},
/**
* Define logging level
*
* @param {String|Number} level
*/
setLevel: function(level) {
if (NOOT.isNone(level) || level === '') throw new Error('Missing logging level');
switch (typeof level) {
case 'string':
level = Logger.levels[level.toUpperCase()];
break;
case 'number':
level = _.find(Logger.levels, function(val) { return level === val; });
break;
default:
level = null;
}
if (NOOT.isNone(level)) throw new Error('Invalid logging level');
this._level = level;
},
/**
*
*
* @param {Array|arguments} args
* @param {String|Number} level
* @private
*/
_buildAndSend: function(args, level) {
var message = Logger._joinMessages(NOOT.makeArray(args));
message = this.formatMessage(message, level);
var styles = this._styles[level];
if (styles) {
for (var style in styles) {
if (style === 'color') message = message[styles[style]];
else message = message[style];
}
}
return this.transport(message, level, this.transportCallback);
}
}, {
/**
* String used to concatenate messages
*/
JOINER: ' ',
/**
* Levels enumeration
*/
levels: { TRACE: 0, DEBUG: 1, INFO: 2, WARN: 3, ERROR: 4, OFF: 5 },
/**
* Default values
*/
DEFAULTS: {
styles: {
trace: 'grey',
info: 'magenta',
warn: 'yellow',
error: 'red',
announce: { color: 'cyan', bold: true },
highlight: 'inverse'
}
},
/**
* Concatenate arguments into a single valid string
*
* @param {Array|arguments} args
* @returns {string}
* @private
*/
_joinMessages: function(args) {
return NOOT.makeArray(args)
.map(function(part) {
switch (NOOT.typeOf(part)) {
case 'error':
return part.stack.toString();
case 'undefined':
case 'null':
return NOOT.typeOf(part);
case 'string':
case 'number':
case 'boolean':
return part.toString();
default:
return util.inspect(part, { depth: 2 });
}
})
.join(this.JOINER);
},
/**
* Build an object containing all styles properties
*
* @param {Object} styles
* @returns {Object}
* @private
*/
_buildStylesConfig: function(styles) {
var ret = {};
for (var styleName in styles) {
ret[styleName] = NOOT.isNone(styles[styleName].color) ? { color: styles[styleName] } : styles[styleName];
ret[styleName] = _.pick(ret[styleName], ['color', 'bold', 'underline']);
_.forIn(ret[styleName], function(value, key) { if (!value) delete ret[styleName][key]; });
}
return ret;
}
});
/**
* @exports
*/
module.exports = Logger;