code-intelligence.com/cifuzz@v0.40.0/internal/cmd/run/reporthandler/metrics/updating_printer.go (about) 1 package metrics 2 3 import ( 4 "fmt" 5 "io" 6 "strings" 7 "sync/atomic" 8 "time" 9 10 "github.com/gookit/color" 11 "github.com/pkg/errors" 12 "github.com/pterm/pterm" 13 14 "code-intelligence.com/cifuzz/pkg/log" 15 "code-intelligence.com/cifuzz/pkg/report" 16 ) 17 18 func NewUpdatingPrinter(output io.Writer) (*UpdatingPrinter, error) { 19 // pterm.SpinnerPrinter doesn't support specifying the output, it 20 // always uses color.output, so we have to set that. Note that this 21 // affects the default output of all methods from the pterm and 22 // color packages. 23 color.SetOutput(output) 24 25 var err error 26 p := &UpdatingPrinter{ 27 SpinnerPrinter: pterm.DefaultSpinner.WithShowTimer(false), 28 startedAt: time.Now(), 29 output: output, 30 lastMetrics: &atomic.Value{}, 31 } 32 log.ActiveUpdatingPrinter = p 33 34 p.SpinnerPrinter, err = p.SpinnerPrinter.Start() 35 if err != nil { 36 return nil, errors.WithStack(err) 37 } 38 39 p.ticker = time.NewTicker(time.Second) 40 go func() { 41 for range p.ticker.C { 42 if !p.SpinnerPrinter.IsActive { 43 break 44 } 45 p.Update() 46 } 47 }() 48 49 return p, nil 50 } 51 52 type UpdatingPrinter struct { 53 *pterm.SpinnerPrinter 54 ticker *time.Ticker 55 startedAt time.Time 56 output io.Writer 57 58 lastMetrics *atomic.Value 59 } 60 61 func (p *UpdatingPrinter) Update() { 62 lastMetrics, ok := p.lastMetrics.Load().(*report.FuzzingMetric) 63 if ok { 64 lastMetrics.SecondsSinceLastFeature += 1 65 p.lastMetrics.Store(lastMetrics) 66 } 67 p.printMetrics(lastMetrics) 68 } 69 70 func (p *UpdatingPrinter) PrintMetrics(metrics *report.FuzzingMetric) { 71 p.lastMetrics.Store(metrics) 72 p.ticker.Reset(time.Second) 73 p.printMetrics(metrics) 74 } 75 76 func (p *UpdatingPrinter) printMetrics(metrics *report.FuzzingMetric) { 77 s := fmt.Sprint( 78 MetricsToString(metrics), 79 DelimString(" ("), 80 pterm.LightYellow(time.Since(p.startedAt).Truncate(time.Second).String()), 81 DelimString(")"), 82 ) 83 p.UpdateText(s) 84 } 85 86 func (p *UpdatingPrinter) Clear() { 87 pterm.Fprinto(p.output, strings.Repeat(" ", pterm.GetTerminalWidth()), "\r") 88 }