github.com/ldez/golangci-lint@v1.10.1/pkg/timeutils/stopwatch.go (about) 1 package timeutils 2 3 import ( 4 "fmt" 5 "sort" 6 "strings" 7 "sync" 8 "time" 9 10 "github.com/golangci/golangci-lint/pkg/logutils" 11 ) 12 13 type Stopwatch struct { 14 name string 15 startedAt time.Time 16 stages map[string]time.Duration 17 log logutils.Log 18 19 sync.Mutex 20 } 21 22 func NewStopwatch(name string, log logutils.Log) *Stopwatch { 23 return &Stopwatch{ 24 name: name, 25 startedAt: time.Now(), 26 stages: map[string]time.Duration{}, 27 log: log, 28 } 29 } 30 31 type stageDuration struct { 32 name string 33 d time.Duration 34 } 35 36 func (s *Stopwatch) sprintStages() string { 37 stageDurations := []stageDuration{} 38 for n, d := range s.stages { 39 stageDurations = append(stageDurations, stageDuration{ 40 name: n, 41 d: d, 42 }) 43 } 44 sort.Slice(stageDurations, func(i, j int) bool { 45 return stageDurations[i].d > stageDurations[j].d 46 }) 47 stagesStrings := []string{} 48 for _, s := range stageDurations { 49 stagesStrings = append(stagesStrings, fmt.Sprintf("%s: %s", s.name, s.d)) 50 } 51 52 return fmt.Sprintf("stages: %s", strings.Join(stagesStrings, ", ")) 53 } 54 55 func (s *Stopwatch) Print() { 56 p := fmt.Sprintf("%s took %s", s.name, time.Since(s.startedAt)) 57 if len(s.stages) == 0 { 58 s.log.Infof("%s", p) 59 return 60 } 61 62 s.log.Infof("%s with %s", p, s.sprintStages()) 63 } 64 65 func (s *Stopwatch) PrintStages() { 66 var stagesDuration time.Duration 67 for _, s := range s.stages { 68 stagesDuration += s 69 } 70 s.log.Infof("%s took %s with %s", s.name, stagesDuration, s.sprintStages()) 71 } 72 73 func (s *Stopwatch) TrackStage(name string, f func()) { 74 startedAt := time.Now() 75 f() 76 77 s.Lock() 78 s.stages[name] += time.Since(startedAt) 79 s.Unlock() 80 }