1 package watcher
2
3 import (
4 "fmt"
5
6 "github.com/prometheus/client_golang/prometheus"
7 "github.com/prometheus/client_golang/prometheus/promauto"
8 log "github.com/sirupsen/logrus"
9 )
10
11 type (
12 metricsVecs struct {
13 labelNames []string
14 subscribers *prometheus.GaugeVec
15 updates *prometheus.CounterVec
16 }
17
18 metrics struct {
19 labels prometheus.Labels
20 subscribers prometheus.Gauge
21 updates prometheus.Counter
22 }
23
24 endpointsMetricsVecs struct {
25 metricsVecs
26 pods *prometheus.GaugeVec
27 exists *prometheus.GaugeVec
28 }
29
30 endpointsMetrics struct {
31 metrics
32 pods prometheus.Gauge
33 exists prometheus.Gauge
34 }
35 )
36
37 var (
38 informer_lag_seconds_buckets = []float64{
39 0.5,
40 1,
41 2.5,
42 5,
43 10,
44 25,
45 50,
46 100,
47 250,
48 1000,
49 }
50 endpointsInformerLag = promauto.NewHistogram(
51 prometheus.HistogramOpts{
52 Name: "endpoints_informer_lag_seconds",
53 Help: "The amount of time between when an Endpoints resource is updated and when an informer observes it",
54 Buckets: informer_lag_seconds_buckets,
55 },
56 )
57
58 endpointsliceInformerLag = promauto.NewHistogram(
59 prometheus.HistogramOpts{
60 Name: "endpointslices_informer_lag_seconds",
61 Help: "The amount of time between when an EndpointSlice resource is updated and when an informer observes it",
62 Buckets: informer_lag_seconds_buckets,
63 },
64 )
65
66 serviceInformerLag = promauto.NewHistogram(
67 prometheus.HistogramOpts{
68 Name: "services_informer_lag_seconds",
69 Help: "The amount of time between when a Service resource is updated and when an informer observes it",
70 Buckets: informer_lag_seconds_buckets,
71 },
72 )
73
74 serverInformerLag = promauto.NewHistogram(
75 prometheus.HistogramOpts{
76 Name: "servers_informer_lag_seconds",
77 Help: "The amount of time between when a Server resource is updated and when an informer observes it",
78 Buckets: informer_lag_seconds_buckets,
79 },
80 )
81
82 podInformerLag = promauto.NewHistogram(
83 prometheus.HistogramOpts{
84 Name: "pods_informer_lag_seconds",
85 Help: "The amount of time between when a Pod resource is updated and when an informer observes it",
86 Buckets: informer_lag_seconds_buckets,
87 },
88 )
89
90 externalWorkloadInformerLag = promauto.NewHistogram(
91 prometheus.HistogramOpts{
92 Name: "externalworkload_informer_lag_seconds",
93 Help: "The amount of time between when an ExternalWorkload resource is updated and when an informer observes it",
94 Buckets: informer_lag_seconds_buckets,
95 },
96 )
97
98 serviceProfileInformerLag = promauto.NewHistogram(
99 prometheus.HistogramOpts{
100 Name: "serviceprofiles_informer_lag_seconds",
101 Help: "The amount of time between when a ServiceProfile resource is updated and when an informer observes it",
102 Buckets: informer_lag_seconds_buckets,
103 },
104 )
105 )
106
107 func newMetricsVecs(name string, labels []string) metricsVecs {
108 subscribers := promauto.NewGaugeVec(
109 prometheus.GaugeOpts{
110 Name: fmt.Sprintf("%s_subscribers", name),
111 Help: fmt.Sprintf("A gauge for the current number of subscribers to a %s.", name),
112 },
113 labels,
114 )
115
116 updates := promauto.NewCounterVec(
117 prometheus.CounterOpts{
118 Name: fmt.Sprintf("%s_updates", name),
119 Help: fmt.Sprintf("A counter for number of updates to a %s.", name),
120 },
121 labels,
122 )
123
124 return metricsVecs{
125 labelNames: labels,
126 subscribers: subscribers,
127 updates: updates,
128 }
129 }
130
131 func endpointsLabels(cluster, namespace, service, port string, hostname string) prometheus.Labels {
132 return prometheus.Labels{
133 "cluster": cluster,
134 "namespace": namespace,
135 "service": service,
136 "port": port,
137 "hostname": hostname,
138 }
139 }
140
141 func labelNames(labels prometheus.Labels) []string {
142 names := []string{}
143 for label := range labels {
144 names = append(names, label)
145 }
146 return names
147 }
148
149 func newEndpointsMetricsVecs() endpointsMetricsVecs {
150 labels := labelNames(endpointsLabels("", "", "", "", ""))
151 vecs := newMetricsVecs("endpoints", labels)
152
153 pods := promauto.NewGaugeVec(
154 prometheus.GaugeOpts{
155 Name: "endpoints_pods",
156 Help: "A gauge for the current number of pods in a endpoints.",
157 },
158 labels,
159 )
160
161 exists := promauto.NewGaugeVec(
162 prometheus.GaugeOpts{
163 Name: "endpoints_exists",
164 Help: "A gauge which is 1 if the endpoints exists and 0 if it does not.",
165 },
166 labels,
167 )
168
169 return endpointsMetricsVecs{
170 metricsVecs: vecs,
171 pods: pods,
172 exists: exists,
173 }
174 }
175
176 func (mv metricsVecs) newMetrics(labels prometheus.Labels) metrics {
177 return metrics{
178 labels: labels,
179 subscribers: mv.subscribers.With(labels),
180 updates: mv.updates.With(labels),
181 }
182 }
183
184 func (emv endpointsMetricsVecs) newEndpointsMetrics(labels prometheus.Labels) endpointsMetrics {
185 metrics := emv.newMetrics(labels)
186 return endpointsMetrics{
187 metrics: metrics,
188 pods: emv.pods.With(labels),
189 exists: emv.exists.With(labels),
190 }
191 }
192
193 func (emv endpointsMetricsVecs) unregister(labels prometheus.Labels) {
194 if !emv.metricsVecs.subscribers.Delete(labels) {
195 log.Warnf("unable to delete endpoints_subscribers metric with labels %s", labels)
196 }
197 if !emv.metricsVecs.updates.Delete(labels) {
198 log.Warnf("unable to delete endpoints_updates metric with labels %s", labels)
199 }
200 if !emv.pods.Delete(labels) {
201 log.Warnf("unable to delete endpoints_pods metric with labels %s", labels)
202 }
203 if !emv.exists.Delete(labels) {
204 log.Warnf("unable to delete endpoints_exists metric with labels %s", labels)
205 }
206 }
207
208 func (m metrics) setSubscribers(n int) {
209 m.subscribers.Set(float64(n))
210 }
211
212 func (m metrics) incUpdates() {
213 m.updates.Inc()
214 }
215
216 func (em endpointsMetrics) setPods(n int) {
217 em.pods.Set(float64(n))
218 }
219
220 func (em endpointsMetrics) setExists(exists bool) {
221 if exists {
222 em.exists.Set(1.0)
223 } else {
224 em.exists.Set(0.0)
225 }
226 }
227
View as plain text