Skip to content

Commit e58d54b

Browse files
TooTallNatethebigredgeek
authored andcommitted
Node: configurable util.inspect() options (#327)
* `formatArgs()` gets passed the args Array directly Rather than working on `arguments`. The Node.js version was for some reason turning the arguments into an Array again so it was happening twice! This should make things faster overall. * whitespace * rename `Readme.md` to `README.md` * refactor the `debug()` constructor a bit Now, debug instances are hot-enabelable. That is, you can toggle the `debug.enabled` boolean on instances to enable or disable an instance. There is still no global version of this functionality. Now all instances get a `useColors` and `colors` property, even disabled ones, in case they get enabled later on. Boot-up time impact should be negligible. * node: allow configurable `util.inspect()` options Via env variables by default. So to get more object depth, you pass the `DEBUG_DEPTH=10` env var. For the `showHidden` option, you set `DEBUG_SHOW_HIDDEN=on`. See the Node.js docs for the complete list of `util.inspect()` options: https://nodejs.org/api/util.html#util_util_inspect_object_options * README: document inspect env variables
1 parent 00f3046 commit e58d54b

File tree

4 files changed

+98
-67
lines changed

4 files changed

+98
-67
lines changed

Readme.md renamed to README.md

+23-7
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,36 @@ Then, run the program to be debugged as usual.
7979

8080
## Conventions
8181

82-
If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser".
82+
If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser".
8383

8484
## Wildcards
8585

8686
The `*` character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.
8787

8888
You can also exclude specific debuggers by prefixing them with a "-" character. For example, `DEBUG=*,-connect:*` would include all debuggers except those starting with "connect:".
8989

90+
## Environment Variables
91+
92+
When running through Node.js, you can set a few environment variables that will
93+
change the behavior of the debug logging:
94+
95+
| Name | Purpose |
96+
|-----------|-------------------------------------------------|
97+
| `DEBUG` | Enables/disabled specific debugging namespaces. |
98+
| `DEBUG_COLORS`| Whether or not to use colors in the debug output. |
99+
| `DEBUG_FD`| File descriptor to output debug logs to. Defaults to stderr. |
100+
| `DEBUG_DEPTH` | Object inspection depth. |
101+
| `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects. |
102+
103+
104+
__Note:__ The environment variables beginning with `DEBUG_` end up being
105+
converted into an Options object that gets used with `%o`/`%O` formatters.
106+
See the Node.js documentation for
107+
[`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options)
108+
for the complete list.
109+
110+
__Note:__ Certain IDEs (such as WebStorm) don't support colors on stderr. In these cases you must set `DEBUG_COLORS` to `1` and additionally change `DEBUG_FD` to `1`.
111+
90112
## Formatters
91113

92114

@@ -191,12 +213,6 @@ Example:
191213
$ DEBUG_FD=3 node your-app.js 3> whatever.log
192214
```
193215

194-
### Terminal colors
195-
196-
By default colors will only be used in a TTY. However this can be overridden by setting the environment variable `DEBUG_COLORS` to `1`.
197-
198-
Note: Certain IDEs (such as WebStorm) don't support colors on stderr. In these cases you must set `DEBUG_COLORS` to `1` and additionally change `DEBUG_FD` to `1`.
199-
200216
## Authors
201217

202218
- TJ Holowaychuk

browser.js

+2-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
/**
32
* This is the web browser implementation of `debug()`.
43
*
@@ -69,8 +68,7 @@ exports.formatters.j = function(v) {
6968
* @api public
7069
*/
7170

72-
function formatArgs() {
73-
var args = arguments;
71+
function formatArgs(args) {
7472
var useColors = this.useColors;
7573

7674
args[0] = (useColors ? '%c' : '')
@@ -101,7 +99,6 @@ function formatArgs() {
10199
});
102100

103101
args.splice(lastC, 0, c);
104-
return args;
105102
}
106103

107104
/**
@@ -172,7 +169,7 @@ exports.enable(load());
172169
* @api private
173170
*/
174171

175-
function localstorage(){
172+
function localstorage() {
176173
try {
177174
return window.localStorage;
178175
} catch (e) {}

debug.js

+19-21
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Expose `debug()` as the module.
77
*/
88

9-
exports = module.exports = debug.debug = debug;
9+
exports = module.exports = createDebug.debug = createDebug.default = createDebug;
1010
exports.coerce = coerce;
1111
exports.disable = disable;
1212
exports.enable = enable;
@@ -23,7 +23,7 @@ exports.skips = [];
2323
/**
2424
* Map of special "%n" handling functions, for the debug "format" argument.
2525
*
26-
* Valid key names are a single, lowercased letter, i.e. "n".
26+
* Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
2727
*/
2828

2929
exports.formatters = {};
@@ -66,17 +66,13 @@ function selectColor(namespace) {
6666
* @api public
6767
*/
6868

69-
function debug(namespace) {
69+
function createDebug(namespace) {
7070

71-
// define the `disabled` version
72-
function disabled() {
73-
}
74-
disabled.enabled = false;
75-
76-
// define the `enabled` version
77-
function enabled() {
71+
function debug() {
72+
// disabled?
73+
if (!debug.enabled) return;
7874

79-
var self = enabled;
75+
var self = debug;
8076

8177
// set `diff` timestamp
8278
var curr = +new Date();
@@ -86,10 +82,7 @@ function debug(namespace) {
8682
self.curr = curr;
8783
prevTime = curr;
8884

89-
// add the `color` if not set
90-
if (null == self.useColors) self.useColors = exports.useColors();
91-
if (null == self.color && self.useColors) self.color = selectColor(namespace);
92-
85+
// turn the `arguments` into a proper Array
9386
var args = new Array(arguments.length);
9487
for (var i = 0; i < args.length; i++) {
9588
args[i] = arguments[i];
@@ -120,19 +113,24 @@ function debug(namespace) {
120113
return match;
121114
});
122115

123-
// apply env-specific formatting
124-
args = exports.formatArgs.apply(self, args);
116+
// apply env-specific formatting (colors, etc.)
117+
exports.formatArgs.call(self, args);
125118

126119
var logFn = enabled.log || exports.log || console.log.bind(console);
127120
logFn.apply(self, args);
128121
}
129-
enabled.enabled = true;
130122

131-
var fn = exports.enabled(namespace) ? enabled : disabled;
123+
debug.namespace = namespace;
124+
debug.enabled = exports.enabled(namespace);
125+
debug.useColors = exports.useColors();
126+
debug.color = selectColor(namespae);
132127

133-
fn.namespace = namespace;
128+
// env-specific initialization logic for debug instances
129+
if ('function' === typeof exports.init) {
130+
exports.init(debug);
131+
}
134132

135-
return fn;
133+
return debug;
136134
}
137135

138136
/**

node.js

+54-34
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
/**
32
* Module dependencies.
43
*/
@@ -13,6 +12,7 @@ var util = require('util');
1312
*/
1413

1514
exports = module.exports = require('./debug');
15+
exports.init = init;
1616
exports.log = log;
1717
exports.formatArgs = formatArgs;
1818
exports.save = save;
@@ -25,6 +25,32 @@ exports.useColors = useColors;
2525

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

28+
/**
29+
* Build up the default `inspectOpts` object from the environment variables.
30+
*
31+
* $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js
32+
*/
33+
34+
exports.inspectOpts = Object.keys(process.env).filter(function (key) {
35+
return /^debug_/i.test(key);
36+
}).reduce(function (obj, key) {
37+
// camel-case
38+
var prop = key
39+
.substring(6)
40+
.toLowerCase()
41+
.replace(/_([a-z])/, function (_, k) { return k.toUpperCase() });
42+
43+
// coerce string value into JS value
44+
var val = process.env[key];
45+
if (/^(yes|on|true|enabled)$/i.test(val)) val = true;
46+
else if (/^(no|off|false|disabled)$/i.test(val)) val = false;
47+
else if (val === 'null') val = null;
48+
else val = Number(val);
49+
50+
obj[prop] = val;
51+
return obj;
52+
}, {});
53+
2854
/**
2955
* The file descriptor to write the `debug()` calls to.
3056
* Set the `DEBUG_FD` env variable to override with another value. i.e.:
@@ -42,39 +68,28 @@ var stream = 1 === fd ? process.stdout :
4268
*/
4369

4470
function useColors() {
45-
var debugColors = (process.env.DEBUG_COLORS || '').trim().toLowerCase();
46-
if (0 === debugColors.length) {
47-
return tty.isatty(fd);
48-
} else {
49-
return '0' !== debugColors
50-
&& 'no' !== debugColors
51-
&& 'false' !== debugColors
52-
&& 'disabled' !== debugColors;
53-
}
71+
return 'colors' in exports.inspectOpts
72+
? Boolean(exports.inspectOpts.colors)
73+
: tty.isatty(fd);
5474
}
5575

5676
/**
57-
* Map %o to `util.inspect()`, since Node doesn't do that out of the box.
77+
* Map %o to `util.inspect()`, all on a single line.
5878
*/
5979

60-
var inspect = (4 === util.inspect.length ?
61-
// node <= 0.8.x
62-
function (v, colors) {
63-
return util.inspect(v, void 0, void 0, colors);
64-
} :
65-
// node > 0.8.x
66-
function (v, colors) {
67-
return util.inspect(v, { colors: colors });
68-
}
69-
);
70-
7180
exports.formatters.o = function(v) {
72-
return inspect(v, this.useColors)
81+
this.inspectOpts.colors = this.useColors;
82+
return util.inspect(v, this.inspectOpts)
7383
.replace(/\s*\n\s*/g, ' ');
7484
};
7585

86+
/**
87+
* Map %o to `util.inspect()`, allowing multiple lines if needed.
88+
*/
89+
7690
exports.formatters.O = function(v) {
77-
return inspect(v, this.useColors);
91+
this.inspectOpts.colors = this.useColors;
92+
return util.inspect(v, this.inspectOpts);
7893
};
7994

8095
/**
@@ -83,14 +98,9 @@ exports.formatters.O = function(v) {
8398
* @api public
8499
*/
85100

86-
function formatArgs() {
87-
var len = arguments.length;
88-
var args = new Array(len);
89-
var useColors = this.useColors;
101+
function formatArgs(args) {
90102
var name = this.namespace;
91-
for (var i = 0; i < len; i++) {
92-
args[i] = arguments[i];
93-
}
103+
var useColors = this.useColors;
94104

95105
if (useColors) {
96106
var c = this.color;
@@ -102,15 +112,14 @@ function formatArgs() {
102112
args[0] = new Date().toUTCString()
103113
+ ' ' + name + ' ' + args[0];
104114
}
105-
return args;
106115
}
107116

108117
/**
109-
* Invokes `console.error()` with the specified arguments.
118+
* Invokes `util.format()` with the specified arguments and writes to `stream`.
110119
*/
111120

112121
function log() {
113-
return stream.write(util.format.apply(this, arguments) + '\n');
122+
return stream.write(util.format.apply(util, arguments) + '\n');
114123
}
115124

116125
/**
@@ -209,6 +218,17 @@ function createWritableStdioStream (fd) {
209218
return stream;
210219
}
211220

221+
/**
222+
* Init logic for `debug` instances.
223+
*
224+
* Create a new `inspectOpts` object in case `useColors` is set
225+
* differently for a particular `debug` instance.
226+
*/
227+
228+
function init (debug) {
229+
debug.inspectOpts = util._extend({}, exports.inspectOpts);
230+
}
231+
212232
/**
213233
* Enable namespaces listed in `process.env.DEBUG` initially.
214234
*/

0 commit comments

Comments
 (0)