var util = require('util'); var _ = require('lodash'); var loggerInstance; var defaultProvider = { log: console.log, debug: console.log, // use .log(); since console does not have .debug() info: console.info, warn: console.warn, error: console.error }; // log level 'weight' var LEVELS = { debug: 10, info: 20, warn: 30, error: 50, silent: 80 }; module.exports = { // singleton getInstance: function() { if (!loggerInstance) { loggerInstance = new Logger(); } return loggerInstance; }, getArrow: getArrow }; function Logger() { var logLevel; var provider; var api = { log: log, debug: debug, info: info, warn: warn, error: error, setLevel: function(v) { if (isValidLevel(v)) { logLevel = v; } }, setProvider: function(fn) { if (fn && isValidProvider(fn)) { provider = fn(defaultProvider); } } }; init(); return api; function init() { api.setLevel('info'); api.setProvider(function() { return defaultProvider; }); } // log will log messages, regardless of logLevels function log() { provider.log(_interpolate.apply(null, arguments)); } function debug() { if (_showLevel('debug')) { provider.debug(_interpolate.apply(null, arguments)); } } function info() { if (_showLevel('info')) { provider.info(_interpolate.apply(null, arguments)); } } function warn() { if (_showLevel('warn')) { provider.warn(_interpolate.apply(null, arguments)); } } function error() { if (_showLevel('error')) { provider.error(_interpolate.apply(null, arguments)); } } /** * Decide to log or not to log, based on the log levels 'weight' * @param {String} showLevel [debug, info, warn, error, silent] * @return {Boolean} */ function _showLevel(showLevel) { var result = false; var currentLogLevel = LEVELS[logLevel]; if (currentLogLevel && (currentLogLevel <= LEVELS[showLevel])) { result = true; } return result; } // make sure logged messages and its data are return interpolated // make it possible for additional log data, such date/time or custom prefix. function _interpolate() { var fn = _.spread(util.format); var result = fn(_.slice(arguments)); return result; } function isValidProvider(fnProvider) { var result = true; if (fnProvider && !_.isFunction(fnProvider)) { throw new Error('[HPM] Log provider config error. Expecting a function.'); } return result; } function isValidLevel(levelName) { var validLevels = _.keys(LEVELS); var isValid = _.includes(validLevels, levelName); if (!isValid) { throw new Error('[HPM] Log level error. Invalid logLevel.'); } return isValid; } } /** * -> normal proxy * => router * ~> pathRewrite * ≈> router + pathRewrite */ function getArrow(originalPath, newPath, originalTarget, newTarget) { var arrow = ['>']; var isNewTarget = (originalTarget !== newTarget); // router var isNewPath = (originalPath !== newPath); // pathRewrite if (isNewPath && !isNewTarget) {arrow.unshift('~');} else if (!isNewPath && isNewTarget) {arrow.unshift('=');} else if (isNewPath && isNewTarget) {arrow.unshift('≈');} else {arrow.unshift('-');} return arrow.join(''); }