Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to work with logging and progress bar in a node.js CLI application?

Context

In the Node.js application, I use:

  • node-progress for progress bar
  • winston for logging

The CLI application will display a progress bar when building files. During the build operation, sometimes information/errors need to be logged to the console. This disturbs the progress bar in that:

  • the info/error logs to the console immediately after the progress bar and not on a newline
  • the progress bar gets printed again after the logs have finished, resulting in multiple progress bars printed in the console

Illustration of the console:

[===========----------------------] 11 / 33 builtwarn: something wrong here.
[=============--------------------] 13 / 33 builtwarn: something wrong here.
warn: example warning that continues here.
error:  some stacktrace
[=================================] 33 / 33 built

Question

Is there a way to ensure that the progress bar is not disturbed and any information logs to the console are printed above/below the bar? Such that only one progress bar is shown.

I understand that there's a interrupt method in node-progress, but I am not sure how to use that with winston.

I would imagine this to be a fairly common scenario in CLI applications so any suggestions/ideas of how to do it via other dependencies/approaches are appreciated too!

like image 683
Yong Avatar asked Jul 02 '26 12:07

Yong


1 Answers

I make a progress bar class myself.
You can print a \r to clear last line on the screen.
Then print you log.
After that, print a \n, make sure new progress bar will not clear you log.

class MyProgress {
    constructor(total,str_left,str_right){
        this.str_left=".";
        this.str_right=" ";
        if(str_left)this.str_left=str_left;
        if(str_right)this.str_right=str_right;
        this.total = total;
        this.current=0;
        this.strtotal=60;//progress bar width。
    }
    update(current){
        this.current++;
        if(current)this.current=current;        
        var dots=this.str_left.repeat(parseInt( (this.current % this.total) /this.total*this.strtotal));
        var left = this.strtotal - parseInt( (this.current % this.total) /this.total*this.strtotal);
        var empty = this.str_right.repeat(left);
        process.stdout.write(`\r[${dots}${empty}] ${parseInt(this.current/this.total * 100)}% [${this.total}-${this.current}]`);
        //if(this.total <= this.current){ this.current=0; }//
    }   
}
function print(params,...other){
    process.stdout.write("\r");
    console.log(params,...other);//
    process.stdout.write("\n");
}
like image 86
Jimmy Wu Avatar answered Jul 04 '26 02:07

Jimmy Wu



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!