-
Notifications
You must be signed in to change notification settings - Fork 1
/
registry.go
120 lines (94 loc) · 2.07 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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package statter
import (
"errors"
"sync"
"time"
)
type registry struct {
mu sync.Mutex
root *Statter
statters map[string]*Statter
done chan struct{}
wg sync.WaitGroup
}
func newRegistry(root *Statter, d time.Duration) *registry {
name, tags := mergeDescriptors("", root.cfg.separator, root.prefix, nil, root.tags)
k := newKey(name, tags)
defer putKey(k)
reg := ®istry{
root: root,
statters: map[string]*Statter{
k.SafeString(): root,
},
done: make(chan struct{}),
}
reg.wg.Add(1)
go reg.runReportLoop(d)
return reg
}
func (r *registry) runReportLoop(d time.Duration) {
defer r.wg.Done()
tick := time.NewTicker(d)
defer tick.Stop()
for {
select {
case <-r.done:
return
case <-tick.C:
}
r.report()
}
}
func (r *registry) report() {
r.mu.Lock()
defer r.mu.Unlock()
for _, s := range r.statters {
s.report()
}
}
// SubStatter returns a unique sub statter.
func (r *registry) SubStatter(parent *Statter, prefix string, tags []Tag) *Statter {
name, tags := mergeDescriptors(parent.prefix, parent.cfg.separator, prefix, parent.tags, tags)
k := newKey(name, tags)
defer putKey(k)
r.mu.Lock()
defer r.mu.Unlock()
if s, ok := r.statters[k.String()]; ok {
return s
}
s := &Statter{
cfg: parent.cfg,
reg: r,
r: parent.r,
hr: parent.hr,
tr: parent.tr,
pool: parent.pool,
prefix: name,
tags: tags,
}
r.statters[k.SafeString()] = s
return s
}
// Close closes the registry if the caller is the root statter,
// otherwise an error is returned.
func (r *registry) Close(caller *Statter) error {
if caller != r.root {
return errors.New("close cannot be called from a sub-statter")
}
close(r.done)
r.wg.Wait()
r.report()
return nil
}
func mergeDescriptors(prefix, sep, name string, baseTags, tags []Tag) (string, []Tag) {
switch {
case prefix != "" && name != "":
name = prefix + sep + name
case name == "":
name = prefix
}
newTags := make([]Tag, 0, len(baseTags)+len(tags))
newTags = append(newTags, baseTags...)
newTags = append(newTags, tags...)
return name, newTags
}