diff --git a/Readme.md b/README.md similarity index 83% rename from Readme.md rename to README.md index 7ee4d081..e46d8f22 100644 --- a/Readme.md +++ b/README.md @@ -79,7 +79,7 @@ Then, run the program to be debugged as usual. ## Conventions - 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". + 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". ## Wildcards @@ -87,6 +87,28 @@ Then, run the program to be debugged as usual. 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:". +## Environment Variables + + When running through Node.js, you can set a few environment variables that will + change the behavior of the debug logging: + +| Name | Purpose | +|-----------|-------------------------------------------------| +| `DEBUG` | Enables/disabled specific debugging namespaces. | +| `DEBUG_COLORS`| Whether or not to use colors in the debug output. | +| `DEBUG_FD`| File descriptor to output debug logs to. Defaults to stderr. | +| `DEBUG_DEPTH` | Object inspection depth. | +| `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects. | + + + __Note:__ The environment variables beginning with `DEBUG_` end up being + converted into an Options object that gets used with `%o`/`%O` formatters. + See the Node.js documentation for + [`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options) + for the complete list. + + __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`. + ## Formatters @@ -191,12 +213,6 @@ Example: $ DEBUG_FD=3 node your-app.js 3> whatever.log ``` -### Terminal colors - - By default colors will only be used in a TTY. However this can be overridden by setting the environment variable `DEBUG_COLORS` to `1`. - - 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`. - ## Authors - TJ Holowaychuk diff --git a/browser.js b/browser.js index 3f63ab23..2963b23c 100644 --- a/browser.js +++ b/browser.js @@ -1,4 +1,3 @@ - /** * This is the web browser implementation of `debug()`. * @@ -69,8 +68,7 @@ exports.formatters.j = function(v) { * @api public */ -function formatArgs() { - var args = arguments; +function formatArgs(args) { var useColors = this.useColors; args[0] = (useColors ? '%c' : '') @@ -101,7 +99,6 @@ function formatArgs() { }); args.splice(lastC, 0, c); - return args; } /** @@ -172,7 +169,7 @@ exports.enable(load()); * @api private */ -function localstorage(){ +function localstorage() { try { return window.localStorage; } catch (e) {} diff --git a/debug.js b/debug.js index 6664947c..fc634f7e 100644 --- a/debug.js +++ b/debug.js @@ -6,7 +6,7 @@ * Expose `debug()` as the module. */ -exports = module.exports = debug.debug = debug; +exports = module.exports = createDebug.debug = createDebug.default = createDebug; exports.coerce = coerce; exports.disable = disable; exports.enable = enable; @@ -23,7 +23,7 @@ exports.skips = []; /** * Map of special "%n" handling functions, for the debug "format" argument. * - * Valid key names are a single, lowercased letter, i.e. "n". + * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". */ exports.formatters = {}; @@ -66,17 +66,13 @@ function selectColor(namespace) { * @api public */ -function debug(namespace) { +function createDebug(namespace) { - // define the `disabled` version - function disabled() { - } - disabled.enabled = false; - - // define the `enabled` version - function enabled() { + function debug() { + // disabled? + if (!debug.enabled) return; - var self = enabled; + var self = debug; // set `diff` timestamp var curr = +new Date(); @@ -86,10 +82,7 @@ function debug(namespace) { self.curr = curr; prevTime = curr; - // add the `color` if not set - if (null == self.useColors) self.useColors = exports.useColors(); - if (null == self.color && self.useColors) self.color = selectColor(namespace); - + // turn the `arguments` into a proper Array var args = new Array(arguments.length); for (var i = 0; i < args.length; i++) { args[i] = arguments[i]; @@ -120,19 +113,24 @@ function debug(namespace) { return match; }); - // apply env-specific formatting - args = exports.formatArgs.apply(self, args); + // apply env-specific formatting (colors, etc.) + exports.formatArgs.call(self, args); var logFn = enabled.log || exports.log || console.log.bind(console); logFn.apply(self, args); } - enabled.enabled = true; - var fn = exports.enabled(namespace) ? enabled : disabled; + debug.namespace = namespace; + debug.enabled = exports.enabled(namespace); + debug.useColors = exports.useColors(); + debug.color = selectColor(namespae); - fn.namespace = namespace; + // env-specific initialization logic for debug instances + if ('function' === typeof exports.init) { + exports.init(debug); + } - return fn; + return debug; } /** diff --git a/node.js b/node.js index 1f5cd7ed..15bf55af 100644 --- a/node.js +++ b/node.js @@ -1,4 +1,3 @@ - /** * Module dependencies. */ @@ -13,6 +12,7 @@ var util = require('util'); */ exports = module.exports = require('./debug'); +exports.init = init; exports.log = log; exports.formatArgs = formatArgs; exports.save = save; @@ -25,6 +25,32 @@ exports.useColors = useColors; exports.colors = [6, 2, 3, 4, 5, 1]; +/** + * Build up the default `inspectOpts` object from the environment variables. + * + * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js + */ + +exports.inspectOpts = Object.keys(process.env).filter(function (key) { + return /^debug_/i.test(key); +}).reduce(function (obj, key) { + // camel-case + var prop = key + .substring(6) + .toLowerCase() + .replace(/_([a-z])/, function (_, k) { return k.toUpperCase() }); + + // coerce string value into JS value + var val = process.env[key]; + if (/^(yes|on|true|enabled)$/i.test(val)) val = true; + else if (/^(no|off|false|disabled)$/i.test(val)) val = false; + else if (val === 'null') val = null; + else val = Number(val); + + obj[prop] = val; + return obj; +}, {}); + /** * The file descriptor to write the `debug()` calls to. * Set the `DEBUG_FD` env variable to override with another value. i.e.: @@ -42,39 +68,28 @@ var stream = 1 === fd ? process.stdout : */ function useColors() { - var debugColors = (process.env.DEBUG_COLORS || '').trim().toLowerCase(); - if (0 === debugColors.length) { - return tty.isatty(fd); - } else { - return '0' !== debugColors - && 'no' !== debugColors - && 'false' !== debugColors - && 'disabled' !== debugColors; - } + return 'colors' in exports.inspectOpts + ? Boolean(exports.inspectOpts.colors) + : tty.isatty(fd); } /** - * Map %o to `util.inspect()`, since Node doesn't do that out of the box. + * Map %o to `util.inspect()`, all on a single line. */ -var inspect = (4 === util.inspect.length ? - // node <= 0.8.x - function (v, colors) { - return util.inspect(v, void 0, void 0, colors); - } : - // node > 0.8.x - function (v, colors) { - return util.inspect(v, { colors: colors }); - } -); - exports.formatters.o = function(v) { - return inspect(v, this.useColors) + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts) .replace(/\s*\n\s*/g, ' '); }; +/** + * Map %o to `util.inspect()`, allowing multiple lines if needed. + */ + exports.formatters.O = function(v) { - return inspect(v, this.useColors); + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts); }; /** @@ -83,14 +98,9 @@ exports.formatters.O = function(v) { * @api public */ -function formatArgs() { - var len = arguments.length; - var args = new Array(len); - var useColors = this.useColors; +function formatArgs(args) { var name = this.namespace; - for (var i = 0; i < len; i++) { - args[i] = arguments[i]; - } + var useColors = this.useColors; if (useColors) { var c = this.color; @@ -102,15 +112,14 @@ function formatArgs() { args[0] = new Date().toUTCString() + ' ' + name + ' ' + args[0]; } - return args; } /** - * Invokes `console.error()` with the specified arguments. + * Invokes `util.format()` with the specified arguments and writes to `stream`. */ function log() { - return stream.write(util.format.apply(this, arguments) + '\n'); + return stream.write(util.format.apply(util, arguments) + '\n'); } /** @@ -209,6 +218,17 @@ function createWritableStdioStream (fd) { return stream; } +/** + * Init logic for `debug` instances. + * + * Create a new `inspectOpts` object in case `useColors` is set + * differently for a particular `debug` instance. + */ + +function init (debug) { + debug.inspectOpts = util._extend({}, exports.inspectOpts); +} + /** * Enable namespaces listed in `process.env.DEBUG` initially. */