...
1
16
17 package metrics
18
19 import (
20 "fmt"
21
22 "github.com/blang/semver/v4"
23 "github.com/prometheus/client_golang/prometheus"
24 )
25
26
27
28 type StableCollector interface {
29 prometheus.Collector
30
31
32
33 DescribeWithStability(chan<- *Desc)
34
35
36 CollectWithStability(chan<- Metric)
37
38
39 Create(version *semver.Version, self StableCollector) bool
40
41
42 ClearState()
43
44
45 HiddenMetrics() []string
46 }
47
48
49
50
51 type BaseStableCollector struct {
52 descriptors map[string]*Desc
53 registerable map[string]*Desc
54 hidden map[string]*Desc
55 self StableCollector
56 }
57
58
59
60 func (bsc *BaseStableCollector) DescribeWithStability(ch chan<- *Desc) {
61 panic(fmt.Errorf("custom collector should over-write DescribeWithStability method"))
62 }
63
64
65
66 func (bsc *BaseStableCollector) Describe(ch chan<- *prometheus.Desc) {
67 for _, d := range bsc.registerable {
68 ch <- d.toPrometheusDesc()
69 }
70 }
71
72
73
74 func (bsc *BaseStableCollector) CollectWithStability(ch chan<- Metric) {
75 panic(fmt.Errorf("custom collector should over-write CollectWithStability method"))
76 }
77
78
79 func (bsc *BaseStableCollector) Collect(ch chan<- prometheus.Metric) {
80 mch := make(chan Metric)
81
82 go func() {
83 bsc.self.CollectWithStability(mch)
84 close(mch)
85 }()
86
87 for m := range mch {
88
89 if m == nil {
90 continue
91 }
92
93 ch <- prometheus.Metric(m)
94 }
95 }
96
97 func (bsc *BaseStableCollector) add(d *Desc) {
98 if len(d.fqName) == 0 {
99 panic("nameless metrics will be not allowed")
100 }
101
102 if bsc.descriptors == nil {
103 bsc.descriptors = make(map[string]*Desc)
104 }
105
106 if _, exist := bsc.descriptors[d.fqName]; exist {
107 panic(fmt.Sprintf("duplicate metrics (%s) will be not allowed", d.fqName))
108 }
109
110 bsc.descriptors[d.fqName] = d
111 }
112
113
114 func (bsc *BaseStableCollector) init(self StableCollector) {
115 bsc.self = self
116
117 dch := make(chan *Desc)
118
119
120 go func() {
121 bsc.self.DescribeWithStability(dch)
122 close(dch)
123 }()
124
125 for d := range dch {
126 bsc.add(d)
127 }
128 }
129
130 func (bsc *BaseStableCollector) trackRegistrableDescriptor(d *Desc) {
131 if bsc.registerable == nil {
132 bsc.registerable = make(map[string]*Desc)
133 }
134
135 bsc.registerable[d.fqName] = d
136 }
137
138 func (bsc *BaseStableCollector) trackHiddenDescriptor(d *Desc) {
139 if bsc.hidden == nil {
140 bsc.hidden = make(map[string]*Desc)
141 }
142
143 bsc.hidden[d.fqName] = d
144 }
145
146
147
148
149 func (bsc *BaseStableCollector) Create(version *semver.Version, self StableCollector) bool {
150 bsc.init(self)
151
152 for _, d := range bsc.descriptors {
153 d.create(version)
154 if d.IsHidden() {
155 bsc.trackHiddenDescriptor(d)
156 } else {
157 bsc.trackRegistrableDescriptor(d)
158 }
159 }
160
161 if len(bsc.registerable) > 0 {
162 return true
163 }
164
165 return false
166 }
167
168
169
170 func (bsc *BaseStableCollector) ClearState() {
171 for _, d := range bsc.descriptors {
172 d.ClearState()
173 }
174
175 bsc.descriptors = nil
176 bsc.registerable = nil
177 bsc.hidden = nil
178 bsc.self = nil
179 }
180
181
182 func (bsc *BaseStableCollector) HiddenMetrics() (fqNames []string) {
183 for i := range bsc.hidden {
184 fqNames = append(fqNames, bsc.hidden[i].fqName)
185 }
186 return
187 }
188
189
190 var _ StableCollector = &BaseStableCollector{}
191
View as plain text