1package flow 2 3import ( 4 "sync" 5 "time" 6) 7 8// MeterRegistry is a registry for named meters. 9type MeterRegistry struct { 10 meters sync.Map 11} 12 13// Get gets (or creates) a meter by name. 14func (r *MeterRegistry) Get(name string) *Meter { 15 if m, ok := r.meters.Load(name); ok { 16 return m.(*Meter) 17 } 18 m, _ := r.meters.LoadOrStore(name, NewMeter()) 19 return m.(*Meter) 20} 21 22// FindIdle finds all meters that haven't been used since the given time. 23func (r *MeterRegistry) FindIdle(since time.Time) []string { 24 var idle []string 25 r.walkIdle(since, func(key interface{}) { 26 idle = append(idle, key.(string)) 27 }) 28 return idle 29} 30 31// TrimIdle trims that haven't been updated since the given time. Returns the 32// number of timers trimmed. 33func (r *MeterRegistry) TrimIdle(since time.Time) (trimmed int) { 34 // keep these as interfaces to avoid allocating when calling delete. 35 var idle []interface{} 36 r.walkIdle(since, func(key interface{}) { 37 idle = append(idle, since) 38 }) 39 for _, i := range idle { 40 r.meters.Delete(i) 41 } 42 return len(idle) 43} 44 45func (r *MeterRegistry) walkIdle(since time.Time, cb func(key interface{})) { 46 // Yes, this is a global lock. However, all taking this does is pause 47 // snapshotting. 48 globalSweeper.snapshotMu.RLock() 49 defer globalSweeper.snapshotMu.RUnlock() 50 51 r.meters.Range(func(k, v interface{}) bool { 52 // So, this _is_ slightly inaccurate. 53 if v.(*Meter).snapshot.LastUpdate.Before(since) { 54 cb(k) 55 } 56 return true 57 }) 58} 59 60// Remove removes the named meter from the registry. 61// 62// Note: The only reason to do this is to save a bit of memory. Unused meters 63// don't consume any CPU (after they go idle). 64func (r *MeterRegistry) Remove(name string) { 65 r.meters.Delete(name) 66} 67 68// ForEach calls the passed function for each registered meter. 69func (r *MeterRegistry) ForEach(iterFunc func(string, *Meter)) { 70 r.meters.Range(func(k, v interface{}) bool { 71 iterFunc(k.(string), v.(*Meter)) 72 return true 73 }) 74} 75 76// Clear removes all meters from the registry. 77func (r *MeterRegistry) Clear() { 78 r.meters.Range(func(k, v interface{}) bool { 79 r.meters.Delete(k) 80 return true 81 }) 82} 83