Skip to content

Commit dd32a4c

Browse files
committed
Make console logging function configurable.
Split log() into 2 methods: formatArgs() and log(), allowing log to be overridden on a per-namespace or global level. Global log settings trump per-namespace settings.
1 parent 613065a commit dd32a4c

File tree

7 files changed

+138
-54
lines changed

7 files changed

+138
-54
lines changed

Readme.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,32 @@ setInterval(function(){
9696

9797
![](https://cloud.githubusercontent.com/assets/71256/3139768/b98c5fd8-e8ef-11e3-862a-f7253b6f47c6.png)
9898

99+
### stderr vs stdout
100+
101+
You can set an alternative logging method per-namespace by overriding the `log` method on a per-namespace or globally:
102+
103+
Example _stderr.js_:
104+
105+
```js
106+
var debug = require('../');
107+
var log = debug('app:log');
108+
109+
// by default console.log is used
110+
log('goes to stdout!');
111+
112+
var error = debug('app:error');
113+
// set this namespace to log via console.error
114+
error.log = console.error.bind(console); // don't forget to bind to console!
115+
error('goes to stderr');
116+
log('still goes to stdout!');
117+
118+
// set all output to go via console.warn
119+
// overrides all per-namespace log settings
120+
debug.log = console.warn.bind(console);
121+
log('now goes to stderr via console.warn');
122+
error('still goes to stderr, but via console.warn now');
123+
```
124+
99125
## Authors
100126

101127
- TJ Holowaychuk

browser.js

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
exports = module.exports = require('./debug');
99
exports.log = log;
10+
exports.formatArgs = formatArgs;
1011
exports.save = save;
1112
exports.load = load;
1213
exports.useColors = useColors;
@@ -47,14 +48,14 @@ exports.formatters.j = function(v) {
4748
return JSON.stringify(v);
4849
};
4950

51+
5052
/**
51-
* Invokes `console.log()` when available.
52-
* No-op when `console.log` is not a "function".
53+
* Colorize log arguments if enabled.
5354
*
5455
* @api public
5556
*/
5657

57-
function log() {
58+
function formatArgs() {
5859
var args = arguments;
5960
var useColors = this.useColors;
6061

@@ -65,33 +66,43 @@ function log() {
6566
+ (useColors ? '%c ' : ' ')
6667
+ '+' + exports.humanize(this.diff);
6768

68-
if (useColors) {
69-
var c = 'color: ' + this.color;
70-
args = [args[0], c, ''].concat(Array.prototype.slice.call(args, 1));
71-
72-
// the final "%c" is somewhat tricky, because there could be other
73-
// arguments passed either before or after the %c, so we need to
74-
// figure out the correct index to insert the CSS into
75-
var index = 0;
76-
var lastC = 0;
77-
args[0].replace(/%[a-z%]/g, function(match) {
78-
if ('%%' === match) return;
79-
index++;
80-
if ('%c' === match) {
81-
// we only are interested in the *last* %c
82-
// (the user may have provided their own)
83-
lastC = index;
84-
}
85-
});
86-
87-
args.splice(lastC, 0, c);
88-
}
69+
if (!useColors) return args
70+
71+
var c = 'color: ' + this.color;
72+
args = [args[0], c, ''].concat(Array.prototype.slice.call(args, 1));
73+
74+
// the final "%c" is somewhat tricky, because there could be other
75+
// arguments passed either before or after the %c, so we need to
76+
// figure out the correct index to insert the CSS into
77+
var index = 0;
78+
var lastC = 0;
79+
args[0].replace(/%[a-z%]/g, function(match) {
80+
if ('%%' === match) return;
81+
index++;
82+
if ('%c' === match) {
83+
// we only are interested in the *last* %c
84+
// (the user may have provided their own)
85+
lastC = index;
86+
}
87+
});
88+
89+
args.splice(lastC, 0, c);
90+
return args;
91+
}
8992

93+
/**
94+
* Invokes `console.log()` when available.
95+
* No-op when `console.log` is not a "function".
96+
*
97+
* @api public
98+
*/
99+
100+
function log() {
90101
// This hackery is required for IE8,
91102
// where the `console.log` function doesn't have 'apply'
92103
return 'object' == typeof console
93104
&& 'function' == typeof console.log
94-
&& Function.prototype.apply.call(console.log, console, args);
105+
&& Function.prototype.apply.call(console.log, console, arguments);
95106
}
96107

97108
/**

debug.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,11 @@ function debug(namespace) {
110110
return match;
111111
});
112112

113-
exports.log.apply(self, args);
113+
if ('function' === typeof exports.formatArgs) {
114+
args = exports.formatArgs.apply(self, args);
115+
}
116+
var logFn = exports.log || enabled.log || console.log.bind(console);
117+
logFn.apply(self, args);
114118
}
115119
enabled.enabled = true;
116120

dist/debug.js

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
exports = module.exports = _dereq_('./debug');
1010
exports.log = log;
11+
exports.formatArgs = formatArgs;
1112
exports.save = save;
1213
exports.load = load;
1314
exports.useColors = useColors;
@@ -48,14 +49,14 @@ exports.formatters.j = function(v) {
4849
return JSON.stringify(v);
4950
};
5051

52+
5153
/**
52-
* Invokes `console.log()` when available.
53-
* No-op when `console.log` is not a "function".
54+
* Colorize log arguments if enabled.
5455
*
5556
* @api public
5657
*/
5758

58-
function log() {
59+
function formatArgs() {
5960
var args = arguments;
6061
var useColors = this.useColors;
6162

@@ -66,33 +67,43 @@ function log() {
6667
+ (useColors ? '%c ' : ' ')
6768
+ '+' + exports.humanize(this.diff);
6869

69-
if (useColors) {
70-
var c = 'color: ' + this.color;
71-
args = [args[0], c, ''].concat(Array.prototype.slice.call(args, 1));
70+
if (!useColors) return args
71+
72+
var c = 'color: ' + this.color;
73+
args = [args[0], c, ''].concat(Array.prototype.slice.call(args, 1));
74+
75+
// the final "%c" is somewhat tricky, because there could be other
76+
// arguments passed either before or after the %c, so we need to
77+
// figure out the correct index to insert the CSS into
78+
var index = 0;
79+
var lastC = 0;
80+
args[0].replace(/%[a-z%]/g, function(match) {
81+
if ('%%' === match) return;
82+
index++;
83+
if ('%c' === match) {
84+
// we only are interested in the *last* %c
85+
// (the user may have provided their own)
86+
lastC = index;
87+
}
88+
});
7289

73-
// the final "%c" is somewhat tricky, because there could be other
74-
// arguments passed either before or after the %c, so we need to
75-
// figure out the correct index to insert the CSS into
76-
var index = 0;
77-
var lastC = 0;
78-
args[0].replace(/%[a-z%]/g, function(match) {
79-
if ('%%' === match) return;
80-
index++;
81-
if ('%c' === match) {
82-
// we only are interested in the *last* %c
83-
// (the user may have provided their own)
84-
lastC = index;
85-
}
86-
});
90+
args.splice(lastC, 0, c);
91+
return args;
92+
}
8793

88-
args.splice(lastC, 0, c);
89-
}
94+
/**
95+
* Invokes `console.log()` when available.
96+
* No-op when `console.log` is not a "function".
97+
*
98+
* @api public
99+
*/
90100

101+
function log() {
91102
// This hackery is required for IE8,
92103
// where the `console.log` function doesn't have 'apply'
93104
return 'object' == typeof console
94105
&& 'function' == typeof console.log
95-
&& Function.prototype.apply.call(console.log, console, args);
106+
&& Function.prototype.apply.call(console.log, console, arguments);
96107
}
97108

98109
/**
@@ -246,7 +257,11 @@ function debug(namespace) {
246257
return match;
247258
});
248259

249-
exports.log.apply(self, args);
260+
if ('function' === typeof exports.formatArgs) {
261+
args = exports.formatArgs.apply(self, args);
262+
}
263+
var logFn = exports.log || enabled.log || console.log.bind(console);
264+
logFn.apply(self, args);
250265
}
251266
enabled.enabled = true;
252267

example/browser.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
var a = debug('worker:a');
1111
var b = debug('worker:b');
1212

13+
// set all output to go via console.info
14+
// instead of console.log
15+
debug.log = console.info.bind(console);
16+
1317
setInterval(function(){
1418
a('doing some work');
1519
}, 1000);

example/stderr.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
var debug = require('../');
2+
var log = debug('app:log');
3+
4+
// by default console.log is used
5+
log('goes to stdout!');
6+
7+
var error = debug('app:error');
8+
// set this namespace to log via console.error
9+
error.log = console.error.bind(console); // don't forget to bind to console!
10+
error('goes to stderr');
11+
log('still goes to stdout!');
12+
13+
// set all output to go via console.warn
14+
// overrides all per-namespace log settings
15+
debug.log = console.warn.bind(console);
16+
log('now goes to stderr via console.warn');
17+
error('still goes to stderr, but via console.warn now');

node.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ var util = require('util');
1414

1515
exports = module.exports = require('./debug');
1616
exports.log = log;
17+
exports.formatArgs = formatArgs;
1718
exports.save = save;
1819
exports.load = load;
1920
exports.useColors = useColors;
@@ -50,13 +51,12 @@ exports.formatters.o = function(v) {
5051
};
5152

5253
/**
53-
* Invokes `console.log()` with the specified arguments,
54-
* after adding ANSI color escape codes if enabled.
54+
* Adds ANSI color escape codes if enabled.
5555
*
5656
* @api public
5757
*/
5858

59-
function log() {
59+
function formatArgs() {
6060
var args = arguments;
6161
var useColors = this.useColors;
6262
var name = this.namespace;
@@ -72,8 +72,15 @@ function log() {
7272
args[0] = new Date().toUTCString()
7373
+ ' ' + name + ' ' + args[0];
7474
}
75+
return args;
76+
}
77+
78+
/**
79+
* Invokes `console.log()` with the specified arguments.
80+
*/
7581

76-
console.log.apply(console, args);
82+
function log() {
83+
return console.log.apply(console, arguments);
7784
}
7885

7986
/**

0 commit comments

Comments
 (0)