github.com/status-im/status-go@v1.1.0/waku/common/stats.go (about) 1 package common 2 3 import ( 4 "sync" 5 "time" 6 7 "github.com/ethereum/go-ethereum/rlp" 8 "github.com/status-im/status-go/eth-node/types" 9 ) 10 11 type Measure struct { 12 Timestamp int64 13 Size uint64 14 } 15 16 type StatsTracker struct { 17 Uploads []Measure 18 Downloads []Measure 19 20 statsMutex sync.Mutex 21 } 22 23 const measurementPeriod = 15 * time.Second 24 25 func measure(input interface{}) (*Measure, error) { 26 b, err := rlp.EncodeToBytes(input) 27 if err != nil { 28 return nil, err 29 } 30 return &Measure{ 31 Timestamp: time.Now().UnixNano(), 32 Size: uint64(len(b)), 33 }, nil 34 35 } 36 37 func (s *StatsTracker) AddUpload(input interface{}) { 38 go func(input interface{}) { 39 m, err := measure(input) 40 if err != nil { 41 return 42 } 43 44 s.statsMutex.Lock() 45 defer s.statsMutex.Unlock() 46 s.Uploads = append(s.Uploads, *m) 47 }(input) 48 } 49 50 func (s *StatsTracker) AddDownload(input interface{}) { 51 go func(input interface{}) { 52 m, err := measure(input) 53 if err != nil { 54 return 55 } 56 57 s.statsMutex.Lock() 58 defer s.statsMutex.Unlock() 59 s.Downloads = append(s.Downloads, *m) 60 }(input) 61 } 62 63 func (s *StatsTracker) AddUploadBytes(size uint64) { 64 go func(size uint64) { 65 m := Measure{ 66 Timestamp: time.Now().UnixNano(), 67 Size: size, 68 } 69 70 s.statsMutex.Lock() 71 defer s.statsMutex.Unlock() 72 s.Uploads = append(s.Uploads, m) 73 }(size) 74 } 75 76 func (s *StatsTracker) AddDownloadBytes(size uint64) { 77 go func(size uint64) { 78 m := Measure{ 79 Timestamp: time.Now().UnixNano(), 80 Size: size, 81 } 82 83 s.statsMutex.Lock() 84 defer s.statsMutex.Unlock() 85 s.Downloads = append(s.Downloads, m) 86 }(size) 87 } 88 89 func calculateAverage(measures []Measure, minTime int64) (validMeasures []Measure, rate uint64) { 90 for _, m := range measures { 91 if m.Timestamp > minTime { 92 // Only use recent measures 93 validMeasures = append(validMeasures, m) 94 rate += m.Size 95 } 96 } 97 98 rate /= (uint64(measurementPeriod) / uint64(1*time.Second)) 99 return 100 } 101 102 func (s *StatsTracker) GetRatePerSecond() (uploadRate uint64, downloadRate uint64) { 103 s.statsMutex.Lock() 104 defer s.statsMutex.Unlock() 105 minTime := time.Now().Add(-measurementPeriod).UnixNano() 106 s.Uploads, uploadRate = calculateAverage(s.Uploads, minTime) 107 s.Downloads, downloadRate = calculateAverage(s.Downloads, minTime) 108 return 109 } 110 111 func (s *StatsTracker) GetStats() types.StatsSummary { 112 uploadRate, downloadRate := s.GetRatePerSecond() 113 summary := types.StatsSummary{ 114 UploadRate: uploadRate, 115 DownloadRate: downloadRate, 116 } 117 return summary 118 }