mirror of
https://github.com/renovatebot/renovate.git
synced 2025-02-04 02:46:25 +00:00
Refactor bunyan CLI stream (#328)
* Install chalk * Use chalk for colours * Strip back code * Refactor * remove end
This commit is contained in:
parent
7b39f1e115
commit
c96b21a9a2
2 changed files with 18 additions and 196 deletions
|
@ -1,215 +1,36 @@
|
||||||
// Code copied from https://github.com/hadfieldn/node-bunyan-prettystream and heavily edited
|
// Code derived from https://github.com/hadfieldn/node-bunyan-RenovateStream and heavily edited
|
||||||
// Neither fork nor original repo appear to be maintained
|
// Neither fork nor original repo appear to be maintained
|
||||||
|
|
||||||
const Stream = require('stream').Stream;
|
const Stream = require('stream').Stream;
|
||||||
const util = require('util');
|
const util = require('util');
|
||||||
|
const chalk = require('chalk');
|
||||||
|
|
||||||
const format = util.format;
|
const levels = {
|
||||||
|
10: chalk.gray('TRACE'),
|
||||||
const colors = {
|
20: chalk.blue('DEBUG'),
|
||||||
bold: [1, 22],
|
30: chalk.green(' INFO'),
|
||||||
italic: [3, 23],
|
40: chalk.magenta(' WARN'),
|
||||||
underline: [4, 24],
|
50: chalk.red('ERROR'),
|
||||||
inverse: [7, 27],
|
60: chalk.bgRed('FATAL'),
|
||||||
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],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const levelFromName = {
|
function RenovateStream() {
|
||||||
trace: 10,
|
|
||||||
debug: 20,
|
|
||||||
info: 30,
|
|
||||||
warn: 40,
|
|
||||||
error: 50,
|
|
||||||
fatal: 60,
|
|
||||||
};
|
|
||||||
|
|
||||||
const colorFromLevel = {
|
|
||||||
10: 'grey', // TRACE
|
|
||||||
20: 'blue', // DEBUG
|
|
||||||
30: 'green', // INFO
|
|
||||||
40: 'magenta', // WARN
|
|
||||||
50: 'red', // ERROR
|
|
||||||
60: 'inverse', // FATAL
|
|
||||||
};
|
|
||||||
|
|
||||||
const upperPaddedNameFromLevel = {};
|
|
||||||
|
|
||||||
Object.keys(levelFromName).forEach(name => {
|
|
||||||
const lvl = levelFromName[name];
|
|
||||||
upperPaddedNameFromLevel[lvl] =
|
|
||||||
(name.length === 4 ? ' ' : '') + name.toUpperCase();
|
|
||||||
});
|
|
||||||
|
|
||||||
function PrettyStream() {
|
|
||||||
const self = this;
|
|
||||||
|
|
||||||
this.readable = true;
|
this.readable = true;
|
||||||
this.writable = true;
|
this.writable = true;
|
||||||
this.isTTY = false;
|
|
||||||
|
|
||||||
Stream.call(this);
|
Stream.call(this);
|
||||||
|
|
||||||
function stylize(str, inputColor) {
|
|
||||||
if (!str) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
let color = inputColor;
|
|
||||||
|
|
||||||
if (!self.isTTY) {
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!color) {
|
|
||||||
color = 'white';
|
|
||||||
}
|
|
||||||
|
|
||||||
const codes = colors[color];
|
|
||||||
if (codes) {
|
|
||||||
return `\x1B[${codes[0]}m${str}\x1B[${codes[1]}m`;
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
function indent(s) {
|
|
||||||
return ` ${s.split(/\r?\n/).join('\n ')}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function extractLevel(rec) {
|
|
||||||
const level = upperPaddedNameFromLevel[rec.level] || `LVL${rec.level}`;
|
|
||||||
return stylize(level, colorFromLevel[rec.level]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isSingleLineMsg(rec) {
|
|
||||||
return rec.msg.indexOf('\n') === -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
function extractMsg(rec) {
|
|
||||||
return rec.msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
function extractError(rec) {
|
|
||||||
if (rec.err && rec.err.stack) {
|
|
||||||
return rec.err.stack;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function extractCustomDetails(rec) {
|
|
||||||
const skip = [
|
|
||||||
'name',
|
|
||||||
'hostname',
|
|
||||||
'pid',
|
|
||||||
'level',
|
|
||||||
'component',
|
|
||||||
'msg',
|
|
||||||
'time',
|
|
||||||
'v',
|
|
||||||
'src',
|
|
||||||
'err',
|
|
||||||
'client_req',
|
|
||||||
'client_res',
|
|
||||||
'req',
|
|
||||||
'res',
|
|
||||||
];
|
|
||||||
|
|
||||||
const details = [];
|
|
||||||
const extras = {};
|
|
||||||
|
|
||||||
Object.keys(rec).forEach(key => {
|
|
||||||
if (skip.indexOf(key) === -1) {
|
|
||||||
let value = rec[key];
|
|
||||||
if (typeof value === 'undefined') value = '';
|
|
||||||
let stringified = false;
|
|
||||||
if (typeof value === 'function') {
|
|
||||||
value = '[Function]';
|
|
||||||
stringified = true;
|
|
||||||
} else if (typeof value !== 'string') {
|
|
||||||
value = JSON.stringify(value, null, 2);
|
|
||||||
stringified = true;
|
|
||||||
}
|
|
||||||
if (value.indexOf('\n') !== -1 || value.length > 50) {
|
|
||||||
details.push(`${key}: ${value}`);
|
|
||||||
} else if (
|
|
||||||
!stringified &&
|
|
||||||
(value.indexOf(' ') !== -1 || value.length === 0)
|
|
||||||
) {
|
|
||||||
extras[key] = JSON.stringify(value);
|
|
||||||
} else {
|
|
||||||
extras[key] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
details,
|
|
||||||
extras,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function applyDetails(results, details, extras) {
|
|
||||||
if (results) {
|
|
||||||
results.details.forEach(d => {
|
|
||||||
details.push(indent(d));
|
|
||||||
});
|
|
||||||
Object.keys(results.extras).forEach(k => {
|
|
||||||
extras.push(`${k}=${results.extras[k]}`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.formatRecord = function formatRecord(rec) {
|
this.formatRecord = function formatRecord(rec) {
|
||||||
let details = [];
|
const level = levels[rec.level];
|
||||||
let extras = [];
|
const msg = `${rec.msg.split(/\r?\n/).join('\n ')}`;
|
||||||
|
return util.format('%s: %s\n', level, msg);
|
||||||
const level = extractLevel(rec);
|
|
||||||
|
|
||||||
const msg = isSingleLineMsg(rec) ? extractMsg(rec) : '';
|
|
||||||
if (!msg) {
|
|
||||||
details.push(indent(extractMsg(rec)));
|
|
||||||
}
|
|
||||||
|
|
||||||
const error = extractError(rec);
|
|
||||||
if (error) {
|
|
||||||
details.push(indent(error));
|
|
||||||
}
|
|
||||||
|
|
||||||
applyDetails(extractCustomDetails(rec), details, extras);
|
|
||||||
|
|
||||||
extras = stylize(extras.length ? ` (${extras.join(', ')})` : '');
|
|
||||||
details = stylize(details.length ? `${details.join('\n --\n')}\n` : '');
|
|
||||||
|
|
||||||
return format('%s: %s%s\n%s', level, msg, extras, details);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
util.inherits(PrettyStream, Stream);
|
util.inherits(RenovateStream, Stream);
|
||||||
|
|
||||||
PrettyStream.prototype.write = function write(data) {
|
RenovateStream.prototype.write = function write(data) {
|
||||||
if (typeof data === 'string') {
|
this.emit('data', this.formatRecord(data));
|
||||||
this.emit('data', this.formatRecord(JSON.parse(data)));
|
|
||||||
} else if (typeof data === 'object') {
|
|
||||||
this.emit('data', this.formatRecord(data));
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
PrettyStream.prototype.end = function end() {
|
module.exports = RenovateStream;
|
||||||
this.emit('end');
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Track if we're piping into a TTY.
|
|
||||||
PrettyStream.prototype.pipe = function pipe(dest, options) {
|
|
||||||
this.isTTY = dest.isTTY;
|
|
||||||
return Stream.prototype.pipe.call(this, dest, options);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = PrettyStream;
|
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bunyan": "1.8.10",
|
"bunyan": "1.8.10",
|
||||||
|
"chalk": "1.1.3",
|
||||||
"changelog": "1.3.0",
|
"changelog": "1.3.0",
|
||||||
"commander": "2.9.0",
|
"commander": "2.9.0",
|
||||||
"gh-got": "6.0.0",
|
"gh-got": "6.0.0",
|
||||||
|
|
Loading…
Reference in a new issue