package crono import ( "fmt" "os" "time" "github.com/jedib0t/go-pretty/v6/table" ) type Timing struct { Msg string Elapsed time.Duration } type Crono struct { Begin time.Time Cursor time.Time Timings []Timing } // new cronograph with autostart. func New() *Crono { c := new(Crono) c.Timings = make([]Timing, 0) c.Begin = time.Now() c.Cursor = c.Begin return c } // restart the crono // keeps the begin time. func (c *Crono) Restart() { c.Cursor = time.Now() } // push a mark. func (c *Crono) Mark(msg string) { c.Timings = append(c.Timings, Timing{msg, c.GetElapsed()}) } // push a mark and restart the cursor time. func (c *Crono) MarkAndRestart(msg string) { c.Mark(msg) c.Restart() } // time in seconds since last start // it doesn't restart the crono. func (c *Crono) GetElapsed() time.Duration { return time.Since(c.Cursor) } // total time sice start. func (c *Crono) Total() time.Duration { return time.Since(c.Begin) } func (c *Crono) Table() { t := table.NewWriter() t.SetOutputMirror(os.Stdout) t.AppendHeader(table.Row{"#", "Description", "Elapsed"}) for i, e := range c.Timings { t.AppendRow([]interface{}{i, e.Msg, durationToString(e.Elapsed)}) } t.AppendSeparator() t.AppendFooter(table.Row{"", "Total", durationToString(c.Total())}) t.Render() } func durationToString(t time.Duration) string { timeString := fmt.Sprintf("%dms", t.Milliseconds()) if t.Seconds() > 3 { timeString += " !!!" } else if t.Seconds() > 2 { timeString += " .!!" } else if t.Seconds() > 1 { timeString += " ..!" } else { timeString += " ..." } return timeString }