node.js debug模块浅析及改进

来源:互联网 发布:js正则替换指定字符串 编辑:程序博客网 时间:2024/05/22 06:05

    • debug模块简介
    • 源码简单分析
      • namespace
      • createDebug
      • formatArgs
      • selectColor
    • debug模块的不足之处
    • 改进
    • Github

debug模块简介

debug模块是node.js上比较流行的一个开源日志工具。
使用如下代码即可安装:

$ npm install debug

在需要使用的文件里添加如下代码即可使用:

const testDebugger = require("debug")("log");testDebugger("this is test");

再用node执行该文件,即可在控制台上获得如下一条类似于下面的输出:

Fri, 30 Jun 2017 02:26:02 GMT log this is test

记得要在node命令前加上DEBUG=”log”,不然是看不见这条日志的。

源码简单分析

namespace

const testDebugger = require("debug")("log");testDebugger("this is test");

namespace是debug模块用来区分每一条日志的来源的东西,如例子中的log。它紧跟着时间戳出现在日志中,告诉用户这条日志的来源。
如上面的代码,调用testDebugger函数所产生的所有日志都将绑定在log这个namespace下。
为什么要折腾这么一个namespace呢?是为了方便在不同的环境下,选择哪些日志可以输出。指定namespace的命令,就是前文中的DEBUG="log"。这里就指定了只有log这个namespace下的日志会被输出。再宽泛一点,可以使用通配符DEBUG="*"来选择输出所有日志。

createDebug

在debug.js中可以找到这样的一行代码

exports = module.exports = createDebug.debug = createDebug['default'] = createDebug;

它将createDebug方法暴露出来。即,当你require("debug")时,获得的就是createDebug函数。
createDebug函数里主要做了一件事情,就是在函数内部建立了一个名为debug的函数,并将其返回。其实就是高阶函数。
这个debug函数的代码不长,几十行,主要做了以下几件事情:

  • 计算时间偏移量
  • 处理输入参数并对其进行格式化。和console.log()一样,debug模块创建出的日志函数同样支持格式处理符号,如%s %d %c等。
  • 初始化这个日志函数,绑定相关的信息。主要是两个,一个是namespace的绑定,一个是颜色的绑定。

formatArgs

这个函数是用来格式化参数的。代码如下

function formatArgs(args) {  var name = this.namespace;  var useColors = this.useColors;  if (useColors) {    var c = this.color;    var prefix = '  \u001b[3' + c + ';1m' + name + ' ' + '\u001b[0m';    args[0] = prefix + args[0].split('\n').join('\n' + prefix);    args.push('\u001b[3' + c + 'm+' + exports.humanize(this.diff) + '\u001b[0m');  } else {    args[0] = new Date().toUTCString()      + ' ' + name + ' ' + args[0];  }}

首先是从this对象上拉取这条日志的namespace和颜色信息。
如果这个日志被配置为彩色输出,即this.useColors === true的,那么就按照namespace + 日志内容 + 时间偏移量的格式输出。
否则就按照UTC绝对时间 + namespace + 日志内容 输出。

selectColor

function selectColor(namespace) {  var hash = 0, i;  for (i in namespace) {    hash  = ((hash << 5) - hash) + namespace.charCodeAt(i);    hash |= 0; // Convert to 32bit integer  }  return exports.colors[Math.abs(hash) % exports.colors.length];}

由于ANSI color的格式大概是\u001b[31m这样的,变化的部分只有数字31的最后一位。
作者将几个颜色的末位数字存储在了这个数组里:

exports.colors = [6, 2, 3, 4, 5, 1];

然后通过这个selectColor函数去对输入字符串(就是namespace)做一次散列,输出一个1~6之间的数字,从而决定它的颜色。
同样的字符串的散列值是固定的,所以同一个namespace对应的颜色也是一样的。
同时由于散列本身的特性,不同的namespace的颜色很可能是不一样的。

debug模块的不足之处

debug模块在使用过程中,有如下几点不能满足应用需要。

  • namespace的设定不够灵活,缺少日志级别的功能。更多的时候需要指定LOG LEVEL而不是LOG NAME。
  • 开启颜色选项以后,日志的输出格式变成了时间偏移量,显得很奇怪.
  • 时间显示格式为UTCString,可读性很差且浪费磁盘空间

改进

  • createDebug函数的namespace用作日志Level(DBG, MSG, WARN, ERR),并为每种级别的日志分配相应的颜色。新增一个参数作为日志来源提示。
  • 启用日志颜色时格式修改为和无颜色时一样的格式
  • 时间显示格式修改为年月日+时间

最后的log格式如下:

2017-07-03T08:27:41 ServiceName   [MSG]  HTTPS Listening on 0.0.0.0:8088

Github

git clone git@github.com:Shawn-ye/debug.git
原创粉丝点击