動機
動的に変わる値を確認のためにとりあえずconsole.log()なんかで出していると、コンソール出力がずっと下に流れて行って目で追えなかったり。
topコマンドみたいにコンソール上で値が更新され続けるのやってみたい、ということでやってみた。
やりたいこと
定期的に変化する値をずっと同じ行で更新し続けて眺めたい。
でもエラーとか不定期に発生するログも見たいのでそういうのも確認できるようにしたい。
やったこと
単にreadlineのmoveCursor(), clearLine()を駆使しただけです。
MultiLineConsoleUpdaterクラスをインスタンス化すると、1秒間隔でprocess.memoryUsage()の値をコンソール上で更新し続けます。
log()メソッドに文字列を渡せば、それは普通にconsole.log()した時のように出力されます。
MultiLineConsoleUpdater.js
const readline = require('readline');
class MultiLineConsoleUpdater {
constructor() {
/** @private */
this.regularLines = 4;
/** @private */
this.logQueue = [];
process.stdout.write(Array(this.regularLines + 1).join('\n'));
setInterval(this.writePeriodically.bind(this), 1000);
}
/** @private */
clearAndWrite(text) {
readline.clearLine(process.stdout);
process.stdout.write(text);
}
/** @private */
writePeriodically() {
readline.moveCursor(process.stdout, 0, -this.regularLines);
readline.cursorTo(process.stdout, 0);
// write irregular logs
while (this.logQueue.length > 0) {
this.clearAndWrite(this.logQueue.shift());
}
// write regular logs
// e.g. memory usage
const { rss, heapTotal, heapUsed } = process.memoryUsage();
this.clearAndWrite('##### Memory Usage #####\n');
this.clearAndWrite(`rss: ${rss}\n`);
this.clearAndWrite(`heapTotal: ${heapTotal}\n`);
this.clearAndWrite(`third line: ${heapUsed}\n`);
}
log(text) {
this.logQueue.push(`${text}\n`);
}
}
// ##### usage sample #####
let debugCounter = 0;
const w = new MultiLineConsoleUpdater();
setInterval(() => {
w.log(`This is an irregular log: ${debugCounter}`);
debugCounter += 1;
}, 3000);
上を実行すると以下のように出力されます。
This is an irregular log: 0
This is an irregular log: 1
This is an irregular log: 3
This is an irregular log: 4
This is an irregular log: 5
##### Memory Usage #####
rss: 26599424
heapTotal: 10522624
third line: 4620904
メモリ使用量は常に最下部で更新され続けており、その上にlog()で出力した"This is irregular log: n"は3秒間隔で追加されていきます。