log.js

'use strict';
/**
 * fis 日志输出模块。
 * @namespace fis.log
 */

var util = require('util');
var translateError = require('fis3-errors');

/**
 * [级别] 全部输出
 * @name L_ALL
 * @memberOf fis.log
 */
exports.L_ALL = 0x01111;

/**
 * [级别] 输出 notice 信息
 * @name L_NOTIC
 * @memberOf fis.log
 */
exports.L_NOTIC = 0x00001;

/**
 * [级别] 输出 debug 信息
 * @name L_DEBUG
 * @memberOf fis.log
 */
exports.L_DEBUG = 0x00010;

/**
 * [级别] 输出 warning 信息
 * @name L_WARNI
 * @memberOf fis.log
 */
exports.L_WARNI = 0x00100;

/**
 * [级别] 输出 error 信息
 * @name L_ERROR
 * @memberOf fis.log
 */
exports.L_ERROR = 0x01000;

/**
 * [级别] 输出标准信息,包含: error, warning 和 notice 信息。
 * 等价于:`fis.log.L_ERROR | fis.log.L_WARNI | fis.log.L_NOTIC`
 * @name L_NORMAL
 * @memberOf fis.log
 */
exports.L_NORMAL = 0x01101;

/**
 * [级别] 配置项,默认是 `fis.log.L_NORMAL`。 可以外部配置成其他级别。
 * @example
 * // 让 fis 输出 debug 和 warning 信息。
 * fis.log.level = fis.log.L_DEBUG | fis.log.L_WARNI;
 * @name level
 * @memberOf fis.log
 */
exports.level = exports.L_NORMAL;

/**
 * 配置是否需要抛出异常。默认如果遇到错误,fis log 会直接终止进程,可以通过配置此属性为 true 修改成抛出异常。
 * @name throw
 * @memberOf fis.log
 */
exports.throw = false;

/**
 * 配置是否需要输出命令行警告音。
 * @name alert
 * @memberOf fis.log
 */
exports.alert = false;

/**
 * 获取当前时间
 * @param  {Boolean} withoutMilliseconds 是否不显示豪秒
 * @return {String}                     HH:MM:SS.ms
 * @name now
 * @memberOf fis.log
 * @function
 */
exports.now = function(withoutMilliseconds) {
  var d = new Date(),
    str;
  str = [
    d.getHours(),
    d.getMinutes(),
    d.getSeconds()
  ].join(':').replace(/\b\d\b/g, '0$&');
  if (!withoutMilliseconds) {
    str += '.' + ('00' + d.getMilliseconds()).substr(-3);
  }
  return str;
};

/**
 * 打印输出
 * @param  {strict} type [打印输出类型]
 * @param  {string} msg  [打印输出内容]
 * @param  {string} code [打印输出标识码]
 * @inner
 * @name log
 * @memberOf fis.log
 * @function
 */
function log(type, msg, code) {
  code = code || 0;
  if ((exports.level & code) > 0) {
    var listener = exports.on[type];
    if (listener) {
      listener(msg);
    }
    exports.on.any(type, msg);
  }
}

/**
 * 输出 debug 信息。
 * @example
 * fis.log.debug('I say %s, you say %s', 'YoYO', '切克闹');
 * @param  {String} msg 消息内容
 * @param {Mixed} [args...] 可变变量列表
 * @memberOf fis.log
 * @name debug
 * @function
 */
exports.debug = function(msg) {
  msg = util.format.apply(util, arguments);
  log('debug', exports.now().grey + ' ' + msg, exports.L_DEBUG);
};

/**
 * 输出 notice 信息。
 * @param  {String} msg 消息内容
 * @param {Mixed} [args...] 可变变量列表
 * @memberOf fis.log
 * @name notice
 * @function
 */

/**
 * 输出 info 信息。等价于 fis.log.notice
 * @param  {String} msg 消息内容
 * @param {Mixed} [args...] 可变变量列表
 * @memberOf fis.log
 * @name info
 * @function
 */
exports.notice = exports.info = function(msg) {
  msg = util.format.apply(util, arguments);
  log('notice', msg, exports.L_NOTIC);
};

/**
 * 输出 warning 信息。
 * @param  {String} msg 消息内容
 * @param {Mixed} [args...] 可变变量列表
 * @memberOf fis.log
 * @name warn
 * @function
 */

/**
 * 输出 warning 信息。等价于 fis.log.warn.
 * @param  {String} msg 消息内容
 * @param {Mixed} [args...] 可变变量列表
 * @memberOf fis.log
 * @name warning
 * @function
 */
exports.warning = exports.warn = function(msg) {
  msg = util.format.apply(util, arguments);
  log('warning', msg, exports.L_WARNI);
};

/**
 * 输出 error 信息。
 * @param  {String | Event} msg 消息内容
 * @param {Mixed} [args...] 可变变量列表
 * @memberOf fis.log
 * @name error
 * @function
 */
exports.error = function(err) {
  var rawMessage = err;

  if (!(err instanceof Error)) {
    err.message && (rawMessage = err.message);
    err = new Error(err.message || util.format.apply(util, arguments));
  }

  translateError(err, rawMessage);

  if (exports.alert) {
    err.message += '\u0007';
  }
  if (exports.throw) {
    throw err
  } else {
    log('error', err.message, exports.L_ERROR);
    exports.debug(err.stack);
    process.exit(1);
  }
};

/**
 * 格式化输出。完全等价于 {@link https://nodejs.org/api/util.html#util_util_format_format util.format}。
 * @memberOf fis.log
 * @name format
 * @function
 */
exports.format = function() {
  return util.format.apply(util, arguments);
};

/*
 * 打印实际执行方法集合
 * @type {Object}
 * @memberOf fis.log
 * @name on
 */
exports.on = {
  any: function(type, msg) {},
  debug: function(msg) {
    process.stdout.write('\n ' + '[DEBUG]'.grey + ' ' + msg + '\n');
  },
  notice: function(msg) {
    process.stdout.write('\n ' + '[INFO]'.cyan + ' ' + msg + '\n');
  },
  warning: function(msg) {
    process.stdout.write('\n ' + '[WARNI]'.yellow + ' ' + msg + '\n');
  },
  error: function(msg) {
    process.stdout.write('\n '+ '[ERROR]'.red +' ' + msg + '\n');
  }
};