github.com/treeverse/lakefs@v1.24.1-0.20240520134607-95648127bfb0/pkg/testutil/stress/stats.go (about) 1 package stress 2 3 import ( 4 "fmt" 5 "time" 6 ) 7 8 type collectorRequest int 9 10 const ( 11 collectorRequestStats collectorRequest = iota 12 collectorRequestHistogram 13 ) 14 15 type Stats struct { 16 TotalCompleted int64 17 TotalErrors int64 18 CurrentCompleted int64 19 CurrentInterval time.Duration 20 } 21 22 func (s *Stats) String() string { 23 return fmt.Sprintf("completed: %d, errors: %d, current rate: %.2f done/second", 24 s.TotalCompleted, s.TotalErrors, 25 float64(s.CurrentCompleted)/s.CurrentInterval.Seconds()) 26 } 27 28 type ResultCollector struct { 29 // Results is the channel workers should write their output to 30 Results chan Result 31 32 // for getting data out using methods 33 requests chan collectorRequest 34 stats chan *Stats 35 histograms chan *Histogram 36 37 // collected stats 38 lastFlush time.Time 39 histogram *Histogram 40 totalCompleted int64 41 totalErrors int64 42 currentCompleted int64 43 } 44 45 func (rc *ResultCollector) flushCurrent() *Stats { 46 return &Stats{ 47 TotalCompleted: rc.totalCompleted, 48 TotalErrors: rc.totalErrors, 49 CurrentCompleted: rc.currentCompleted, 50 CurrentInterval: time.Since(rc.lastFlush), 51 } 52 } 53 54 func (rc *ResultCollector) Stats() *Stats { 55 rc.requests <- collectorRequestStats 56 return <-rc.stats 57 } 58 59 func (rc *ResultCollector) Histogram() *Histogram { 60 rc.requests <- collectorRequestHistogram 61 return <-rc.histograms 62 } 63 64 func (rc *ResultCollector) Collect() { 65 for { 66 select { 67 case result := <-rc.Results: 68 rc.totalCompleted++ 69 rc.currentCompleted++ 70 if result.Error != nil { 71 rc.totalErrors++ 72 } else { 73 rc.histogram.Add(result.Took.Milliseconds()) 74 } 75 case request := <-rc.requests: 76 switch request { 77 case collectorRequestHistogram: 78 rc.histograms <- rc.histogram.Clone() 79 case collectorRequestStats: 80 rc.stats <- rc.flushCurrent() 81 rc.currentCompleted = 0 82 rc.lastFlush = time.Now() 83 } 84 } 85 } 86 } 87 88 var DefaultHistogramBuckets = []int64{1, 2, 5, 7, 10, 15, 25, 50, 75, 100, 250, 350, 500, 750, 1000, 5000} 89 90 func NewResultCollector(workerResults chan Result) *ResultCollector { 91 return &ResultCollector{ 92 Results: workerResults, 93 requests: make(chan collectorRequest), 94 stats: make(chan *Stats), 95 histograms: make(chan *Histogram), 96 lastFlush: time.Now(), 97 histogram: NewHistogram(DefaultHistogramBuckets), 98 } 99 }