colored bunyan CLI output, and --color option
This commit is contained in:
parent
0f02707429
commit
92a2e9d005
2 changed files with 74 additions and 17 deletions
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
## bunyan 0.6.5 (not yet released)
|
## bunyan 0.6.5 (not yet released)
|
||||||
|
|
||||||
|
- ANSI coloring output from `bunyan` CLI tool (for the default output mode/style).
|
||||||
|
Also add the '--color' option to force coloring if the output stream is not
|
||||||
|
a TTY, e.g. `cat my.log | bunyan --color | less -R`.
|
||||||
- Add 'level' field to log record before custom fields for that record. This just
|
- Add 'level' field to log record before custom fields for that record. This just
|
||||||
means that the raw record JSON will show the 'level' field earlier, which is a bit
|
means that the raw record JSON will show the 'level' field earlier, which is a bit
|
||||||
nicer for raw reading.
|
nicer for raw reading.
|
||||||
|
|
88
bin/bunyan
88
bin/bunyan
|
@ -48,10 +48,13 @@ var levelFromName = {
|
||||||
};
|
};
|
||||||
var nameFromLevel = {};
|
var nameFromLevel = {};
|
||||||
var upperNameFromLevel = {};
|
var upperNameFromLevel = {};
|
||||||
|
var upperPaddedNameFromLevel = {};
|
||||||
Object.keys(levelFromName).forEach(function (name) {
|
Object.keys(levelFromName).forEach(function (name) {
|
||||||
var lvl = levelFromName[name];
|
var lvl = levelFromName[name];
|
||||||
nameFromLevel[lvl] = name;
|
nameFromLevel[lvl] = name;
|
||||||
upperNameFromLevel[lvl] = name.toUpperCase();
|
upperNameFromLevel[lvl] = name.toUpperCase();
|
||||||
|
upperPaddedNameFromLevel[lvl] = (
|
||||||
|
name.length === 4 ? ' ' : '') + name.toUpperCase();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -132,6 +135,8 @@ function printHelp() {
|
||||||
util.puts(" -h, --help print this help info and exit");
|
util.puts(" -h, --help print this help info and exit");
|
||||||
util.puts(" --version print version of this command and exit");
|
util.puts(" --version print version of this command and exit");
|
||||||
util.puts("");
|
util.puts("");
|
||||||
|
util.puts(" --color Colorize output. Defaults to try if output");
|
||||||
|
util.puts(" stream is a TTY.");
|
||||||
util.puts(" -o, --output MODE");
|
util.puts(" -o, --output MODE");
|
||||||
util.puts(" Specify an output mode/format. One of");
|
util.puts(" Specify an output mode/format. One of");
|
||||||
util.puts(" paul: (the default) pretty")
|
util.puts(" paul: (the default) pretty")
|
||||||
|
@ -160,7 +165,7 @@ function parseArgv(argv) {
|
||||||
var parsed = {
|
var parsed = {
|
||||||
args: [],
|
args: [],
|
||||||
help: false,
|
help: false,
|
||||||
quiet: false,
|
color: process.stdout.isTTY,
|
||||||
outputMode: OM_PAUL,
|
outputMode: OM_PAUL,
|
||||||
jsonIndent: 2
|
jsonIndent: 2
|
||||||
};
|
};
|
||||||
|
@ -202,9 +207,8 @@ function parseArgv(argv) {
|
||||||
case "--version":
|
case "--version":
|
||||||
parsed.version = true;
|
parsed.version = true;
|
||||||
break;
|
break;
|
||||||
case "-q":
|
case "--color":
|
||||||
case "--quiet":
|
parsed.color = true;
|
||||||
parsed.quiet = true;
|
|
||||||
break;
|
break;
|
||||||
case "-o":
|
case "-o":
|
||||||
case "--output":
|
case "--output":
|
||||||
|
@ -244,10 +248,45 @@ function isInteger(s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
|
||||||
|
// Suggested colors (some are unreadable in common cases):
|
||||||
|
// - Good: cyan, yellow (limited use), grey, bold, green, magenta, red
|
||||||
|
// - Bad: blue (not visible on cmd.exe)
|
||||||
|
var colors = {
|
||||||
|
'bold' : [1, 22],
|
||||||
|
'italic' : [3, 23],
|
||||||
|
'underline' : [4, 24],
|
||||||
|
'inverse' : [7, 27],
|
||||||
|
'white' : [37, 39],
|
||||||
|
'grey' : [90, 39],
|
||||||
|
'black' : [30, 39],
|
||||||
|
'blue' : [34, 39],
|
||||||
|
'cyan' : [36, 39],
|
||||||
|
'green' : [32, 39],
|
||||||
|
'magenta' : [35, 39],
|
||||||
|
'red' : [31, 39],
|
||||||
|
'yellow' : [33, 39]
|
||||||
|
};
|
||||||
|
|
||||||
|
function stylizeWithColor(str, color) {
|
||||||
|
var codes = colors[color];
|
||||||
|
if (codes) {
|
||||||
|
return '\033[' + codes[0] + 'm' + str +
|
||||||
|
'\033[' + codes[1] + 'm';
|
||||||
|
} else {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function stylizeWithoutColor(str, color) {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print out a single result, considering input options.
|
* Print out a single result, considering input options.
|
||||||
*/
|
*/
|
||||||
function handleLogLine(line, opts) {
|
function handleLogLine(line, opts, stylize) {
|
||||||
// Handle non-JSON lines.
|
// Handle non-JSON lines.
|
||||||
var rec;
|
var rec;
|
||||||
if (!line) {
|
if (!line) {
|
||||||
|
@ -275,7 +314,7 @@ function handleLogLine(line, opts) {
|
||||||
// If 'err' and 'err.stack' then show that.
|
// If 'err' and 'err.stack' then show that.
|
||||||
delete rec.v;
|
delete rec.v;
|
||||||
|
|
||||||
var time = rec.time;
|
var time = stylize('[' + rec.time + ']', 'XXX');
|
||||||
delete rec.time;
|
delete rec.time;
|
||||||
|
|
||||||
var nameStr = rec.name;
|
var nameStr = rec.name;
|
||||||
|
@ -289,7 +328,18 @@ function handleLogLine(line, opts) {
|
||||||
nameStr += '/' + rec.pid;
|
nameStr += '/' + rec.pid;
|
||||||
delete rec.pid;
|
delete rec.pid;
|
||||||
|
|
||||||
var level = (upperNameFromLevel[rec.level] || "<level " + rec.level + ">");
|
var level = (upperPaddedNameFromLevel[rec.level] || "LVL" + rec.level);
|
||||||
|
if (opts.color) {
|
||||||
|
var colorFromLevel = {
|
||||||
|
10: 'grey', // TRACE
|
||||||
|
20: 'grey', // DEBUG
|
||||||
|
30: 'cyan', // INFO
|
||||||
|
40: 'magenta', // WARN
|
||||||
|
50: 'red', // ERROR
|
||||||
|
60: 'inverse', // FATAL
|
||||||
|
}
|
||||||
|
level = stylize(level, colorFromLevel[rec.level])
|
||||||
|
}
|
||||||
delete rec.level;
|
delete rec.level;
|
||||||
|
|
||||||
var src = "";
|
var src = "";
|
||||||
|
@ -319,10 +369,12 @@ function handleLogLine(line, opts) {
|
||||||
}
|
}
|
||||||
delete rec.latency;
|
delete rec.latency;
|
||||||
|
|
||||||
onelineMsg = ' ' + rec.msg;
|
var onelineMsg;
|
||||||
if (rec.msg.indexOf('\n') !== -1) {
|
if (rec.msg.indexOf('\n') !== -1) {
|
||||||
onelineMsg = '';
|
onelineMsg = '';
|
||||||
details.push(indent(rec.msg));
|
details.push(indent(stylize(rec.msg, 'cyan')));
|
||||||
|
} else {
|
||||||
|
onelineMsg = ' ' + stylize(rec.msg, 'cyan');
|
||||||
}
|
}
|
||||||
delete rec.msg;
|
delete rec.msg;
|
||||||
|
|
||||||
|
@ -396,9 +448,11 @@ function handleLogLine(line, opts) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extras = (extras.length ? ' (' + extras.join(', ') + ')' : '');
|
extras = stylize(
|
||||||
details = (details.length ? details.join('\n --\n') + '\n' : '');
|
(extras.length ? ' (' + extras.join(', ') + ')' : ''), 'grey');
|
||||||
emit(format("[%s] %s: %s on %s%s:%s%s\n%s",
|
details = stylize(
|
||||||
|
(details.length ? details.join('\n --\n') + '\n' : ''), 'grey');
|
||||||
|
emit(format("%s %s: %s on %s%s:%s%s\n%s",
|
||||||
time,
|
time,
|
||||||
level,
|
level,
|
||||||
nameStr,
|
nameStr,
|
||||||
|
@ -419,8 +473,7 @@ function handleLogLine(line, opts) {
|
||||||
|
|
||||||
case OM_SIMPLE:
|
case OM_SIMPLE:
|
||||||
// <http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/SimpleLayout.html>
|
// <http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/SimpleLayout.html>
|
||||||
emit(format("%s - %s",
|
emit(format("%s - %s", upperNameFromLevel[rec.level] || "LVL" + rec.level,
|
||||||
upperNameFromLevel[rec.level] || "???",
|
|
||||||
rec.msg));
|
rec.msg));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -490,6 +543,7 @@ function main(argv) {
|
||||||
util.puts("bunyan " + getVersion());
|
util.puts("bunyan " + getVersion());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
var stylize = (opts.color ? stylizeWithColor : stylizeWithoutColor);
|
||||||
|
|
||||||
var leftover = ""; // Left-over partial line from last chunk.
|
var leftover = ""; // Left-over partial line from last chunk.
|
||||||
var stdin = process.openStdin();
|
var stdin = process.openStdin();
|
||||||
|
@ -503,18 +557,18 @@ function main(argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (length > 1) {
|
if (length > 1) {
|
||||||
handleLogLine(leftover + lines[0], opts);
|
handleLogLine(leftover + lines[0], opts, stylize);
|
||||||
}
|
}
|
||||||
leftover = lines.pop();
|
leftover = lines.pop();
|
||||||
length -= 1;
|
length -= 1;
|
||||||
for (var i=1; i < length; i++) {
|
for (var i=1; i < length; i++) {
|
||||||
handleLogLine(lines[i], opts);
|
handleLogLine(lines[i], opts, stylize);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
stdin.on('end', function () {
|
stdin.on('end', function () {
|
||||||
if (leftover) {
|
if (leftover) {
|
||||||
handleLogLine(leftover, opts);
|
handleLogLine(leftover, opts, stylize);
|
||||||
leftover = '';
|
leftover = '';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue