debug.js简介

在之前我已经写过一篇文章使用Nodejs自带的Debug模块调试代码,虽然很好用,但是只支持高版本的Nodejs版本,而且命令比较多,操作起来略繁琐,今天来介绍一款轻量的debug的工具,它模仿的就是nodejs的内置debug模块,并且同时支持Nodejs和浏览器端,而且支持彩色化输出,一目了然。

安装使用

使用npm进行安装:

npm install debug --save

使用方法:

var debug = require('debug')('namespace');
debug('你要输出的内容')

然后在命令行中运行:

DEBUG=namespace1,namespace2 node yourscript.js

就会看到一条彩色的输出了。

注意,在windows中,需要如下设置

set DEBUG=*,-not_this

如果是PowerShell的话则如下设置:

$env:DEBUG = "*,-not_this"

命名空间色彩

每一个debug的实例都有一个颜色,它是根据它的命名空间进行生成的。这在输出debug信息的时候可以很方便地可视化辨认出哪一行属于哪一个实例。

在nodejs中,当stderr是一个tty的时候才能输出颜色,同时应该安装supports-color模块,否则debug之后使用少量的基本颜色来输出信息。

在浏览器中,在webkit浏览器开发者工具或者Firebug中都是可以彩色化输出的。

毫秒级别的执行间隔输出

你可以在输出信息中清晰地看到debug()方法的执行毫秒级别时间。当stdout不是tty的时候,会使用toISOString()输出时间。

通用规定

如果你在一个或多个库中使用了debug.js,你应当使用你的库名字作为命名空间,这样开发者就可以很方便地切换debug模块而不用猜测名字。如果你的一个模块中有很多个debuggers,你应该把模块作为前缀名,然后使用:分割模块名和debuggers名字。例如,connect中的bodyparser应该命名为:connect:bodyparser。如果你添加了*在你的名字后面,它将会一直在启用状态无视DEBUG的环境设置,你可以使用它作为平常的输出或者debug的输出。

通配符

*可以作为统配符,匹配所有的debuggers模块。例如你有这些debuggers,connect:bodyparserconnect:compressconnect:session等,你只需要设置DEBUG=*即可启用所有的debuggers模块。

你还可以使用-进行排除一些debuggers模块,例如DEBUG=*,-connect-bodyparser将会启用所有的debuggers模块,忽略connect-bodyparser模块。

Nodejs中的环境变量设置

变量名 作用
DEBUG 启用或禁用一些debugger
DEBUG_HIDE_DATE 隐藏时间输出
DEBUG_COLORS 是否在输出中使用彩色化
DEBUG_DEPTH 对象的检测深度
DEBUG_SHOW_HIDDEN 显示检测对象的隐藏属性

格式化输出

debug.js使用printf-style的格式化输出,下面是一些支持的格式化输出选项。

Formatter Representation
%O 多行输出一个对象
%o 单行输出一个对象
%s 字符串
%d 数字
%j JSON 当有[Circular]参数时会替换循环嵌套引用
%% 百分号

如果你想要自定义格式化输出的化,可以通过扩展debug.formatters属性,例如:

const createDebug = require('debug')
createDebug.formatters.h = (v) => {
  return v.toString('hex')
}
// …elsewhere
const debug = createDebug('foo')
debug('this is hex: %h', new Buffer('hello world'))
//   foo this is hex: 68656c6c6f20776f726c6421 +0ms

浏览器支持

你可以使用 browserify进行构建,或者使用现成的构建debug.js

Debug的启用状态是通过localStroage来保存的:

localStorage.debug = '*'

如下是一个浏览器端使用debug.js的例子:

<!DOCTYPE html>
<html>
  <head>
    <title>debug()</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <script src="./debug.js"></script>
    <script>
      debug.enable('*')
      for (var i=0; i < debug.colors.length; i++) {
        const d = debug('example:' + i);
        d('The color is %o', d.color);
      }
    </script>
    <style type="text/css">
      body {
        padding-top: 100px;
        text-align: center;
        font-family: sans-serif;
      }
    </style>
  </head>
  <body>
    打开
    <strong>开发者工具</strong>
    查看 <code>debug</code> 输出结果
  </body>
</html>

打开开发者工具即可看到结果:

输出流

默认地debug将会输出到stderr,但是你可以手动配置改变每个debug模块通过覆盖log方法:

var debug = require('debug');
var error = debug('app:error');
// by default stderr is used
error('goes to stderr!');
var log = debug('app:log');
// set this namespace to log via console.log
log.log = console.log.bind(console); // don't forget to bind to console!
log('goes to stdout');
error('still goes to stderr!');
// set all output to go via console.info
// overrides all per-namespace log settings
debug.log = console.info.bind(console);
error('now goes to stdout via console.info');
log('still goes to stdout, but via console.info now');

动态启用禁用

你可以使用enable()方法动态的启用或者禁用debug模块(会覆盖环境变量):

let debug = require('debug');
console.log(1, debug.enabled('test'));
debug.enable('test');
console.log(2, debug.enabled('test'));
debug.disable();
console.log(3, debug.enabled('test'));

将会输出如下结果:

1 false
2 true
3 false

检测debug目标是否被启用

const debug = require('debug')('http');
if (debug.enabled) {
  // do stuff...
}

示例

app.js代码如下:

var debug = require('debug')('http')
  , http = require('http')
  , name = 'My App';
// fake app
debug('booting %o', name);
http.createServer(function(req, res){
  debug(req.method + ' ' + req.url);
  res.end('hello\n');
}).listen(3000, function(){
  debug('listening');
});
// fake worker of some kind
require('./worker');

worker.js代码如下:

var a = require('debug')('worker:a')
  , b = require('debug')('worker:b');
function work() {
  a('doing lots of uninteresting work');
  setTimeout(work, Math.random() * 1000);
}
work();
function workb() {
  b('doing some work');
  setTimeout(workb, Math.random() * 2000);
}
workb();

如下是显示结果: