vbauerster / mpb

multi progress bar for Go cli applications
The Unlicense
2.29k stars 123 forks source link

add write interface for print log #106

Closed zhijian-pro closed 1 year ago

zhijian-pro commented 2 years ago

We can add a write interface for the use of external log modules to solve the problem of overlapping the log and the progress bar. The following is the usage

package main

import (
    "github.com/vbauerster/mpb/v7"
    "github.com/vbauerster/mpb/v7/decor"
    "log"
    "math/rand"
    "os"
    "time"
)

func main() {
    log.Println("start")
    // initialize progress container, with custom width
    p := mpb.New(mpb.WithWidth(64))
    log.SetOutput(p)
    total := 10
    name := "Single Bar:"
    // create a single bar, which will inherit container's width
    bar := p.New(int64(total),
        // BarFillerBuilder with custom style
        mpb.BarStyle().Lbound("╢").Filler("▌").Tip("▌").Padding("░").Rbound("╟"),
        mpb.PrependDecorators(
            // display our name with one space on the right
            decor.Name(name, decor.WC{W: len(name) + 1, C: decor.DidentRight}),
            // replace ETA decorator with "done" message, OnComplete event
            decor.OnComplete(
                decor.AverageETA(decor.ET_STYLE_GO, decor.WC{W: 4}), "done",
            ),
        ),
        mpb.AppendDecorators(decor.Percentage()),
    )
    // simulating some work
    max := 100 * time.Millisecond

    for i := 0; i < total; i++ {
        time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10)
        bar.Increment()
        log.Printf("%d:%s", i, time.Now().String())
        if i == 1 {
            go func() {
                for i := 0; i < 5; i++ {
                    log.Printf("other goroutines %d:%s", i, time.Now().String())
                    time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10)
                }
            }()
        }
    }

    // wait for our bar to complete and flush
    p.Wait()
    log.SetOutput(os.Stderr)
    log.Println("end")
}

Kapture 2022-02-17 at 20 46 47

zhijian-pro commented 2 years ago

105 #84

zhijian-pro commented 2 years ago

@vbauerster what do you think?

wux1an commented 2 years ago

只导出了 cwriter/writer_posix.go 下的 clearLines 方法,Windows 平台也需要导出吧

https://github.com/vbauerster/mpb/blob/8eb62ca8e76186d5ca014b3e9f755872887effe1/cwriter/writer_windows.go#L18

wux1an commented 2 years ago

我把你的代码合并到我 fork 的仓库 https://github.com/wux1an/mpb 后,在 windows 和 linux 环境下都测试了。

linux 环境下正常,windows 环境下一定概率会把最后一行输出清除,导致少输出一行。

正常输出:

2022/04/10 10:24:12 0
2022/04/10 10:24:12 1
...
2022/04/10 10:24:13 28
2022/04/10 10:24:13 29
test   7s [==================>-------------------------------------------] 30 %

异常输出:

2022/04/10 10:24:12 0
2022/04/10 10:24:12 1
...
2022/04/10 10:24:13 28
package main

import (
    "github.com/wux1an/mpb/v7"
    "github.com/wux1an/mpb/v7/decor"
    "log"
    "time"
)

func main() {
    var writer = mpb.New(mpb.WithWidth(64))
    var bar = writer.New(
        100,
        mpb.BarStyle().Lbound("[").Filler("=").Tip(">").Padding("-").Rbound("]"),
        mpb.PrependDecorators(
            // display our name with one space on the right
            decor.Name("test", decor.WC{W: len("test") + 1, C: decor.DidentRight}),
            // replace ETA decorator with "done" message, OnComplete event
            decor.OnComplete(
                decor.AverageETA(decor.ET_STYLE_GO, decor.WC{W: 4}), "done",
            ),
        ),
        mpb.AppendDecorators(decor.Percentage()),
    )

    log.SetOutput(writer)
    for i := 0; i < 30; i++ {
        bar.Increment()
        go func() {
            log.Println(i)
        }()
        time.Sleep(100 * time.Millisecond)
    }
}
zhijian-pro commented 2 years ago

@wux1an The bug has been fixed, and the log will not be lost now.