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  }