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