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 * * @param {String} originalPath * @param {String} newPath * @param {String} originalTarget * @param {String} newTarget * @return {String} */ 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('') }