1
16
17 package restclient
18
19 import (
20 "context"
21 "fmt"
22 "math"
23 "net/url"
24 "time"
25
26 "k8s.io/client-go/tools/metrics"
27 k8smetrics "k8s.io/component-base/metrics"
28 "k8s.io/component-base/metrics/legacyregistry"
29 )
30
31 var (
32
33
34 requestLatency = k8smetrics.NewHistogramVec(
35 &k8smetrics.HistogramOpts{
36 Name: "rest_client_request_duration_seconds",
37 Help: "Request latency in seconds. Broken down by verb, and host.",
38 StabilityLevel: k8smetrics.ALPHA,
39 Buckets: []float64{0.005, 0.025, 0.1, 0.25, 0.5, 1.0, 2.0, 4.0, 8.0, 15.0, 30.0, 60.0},
40 },
41 []string{"verb", "host"},
42 )
43
44
45
46 resolverLatency = k8smetrics.NewHistogramVec(
47 &k8smetrics.HistogramOpts{
48 Name: "rest_client_dns_resolution_duration_seconds",
49 Help: "DNS resolver latency in seconds. Broken down by host.",
50 StabilityLevel: k8smetrics.ALPHA,
51 Buckets: []float64{0.005, 0.025, 0.1, 0.25, 0.5, 1.0, 2.0, 4.0, 8.0, 15.0, 30.0},
52 },
53 []string{"host"},
54 )
55
56 requestSize = k8smetrics.NewHistogramVec(
57 &k8smetrics.HistogramOpts{
58 Name: "rest_client_request_size_bytes",
59 Help: "Request size in bytes. Broken down by verb and host.",
60 StabilityLevel: k8smetrics.ALPHA,
61
62 Buckets: []float64{64, 256, 512, 1024, 4096, 16384, 65536, 262144, 1048576, 4194304, 16777216},
63 },
64 []string{"verb", "host"},
65 )
66
67 responseSize = k8smetrics.NewHistogramVec(
68 &k8smetrics.HistogramOpts{
69 Name: "rest_client_response_size_bytes",
70 Help: "Response size in bytes. Broken down by verb and host.",
71 StabilityLevel: k8smetrics.ALPHA,
72
73 Buckets: []float64{64, 256, 512, 1024, 4096, 16384, 65536, 262144, 1048576, 4194304, 16777216},
74 },
75 []string{"verb", "host"},
76 )
77
78 rateLimiterLatency = k8smetrics.NewHistogramVec(
79 &k8smetrics.HistogramOpts{
80 Name: "rest_client_rate_limiter_duration_seconds",
81 Help: "Client side rate limiter latency in seconds. Broken down by verb, and host.",
82 StabilityLevel: k8smetrics.ALPHA,
83 Buckets: []float64{0.005, 0.025, 0.1, 0.25, 0.5, 1.0, 2.0, 4.0, 8.0, 15.0, 30.0, 60.0},
84 },
85 []string{"verb", "host"},
86 )
87
88 requestResult = k8smetrics.NewCounterVec(
89 &k8smetrics.CounterOpts{
90 Name: "rest_client_requests_total",
91 StabilityLevel: k8smetrics.ALPHA,
92 Help: "Number of HTTP requests, partitioned by status code, method, and host.",
93 },
94 []string{"code", "method", "host"},
95 )
96
97 requestRetry = k8smetrics.NewCounterVec(
98 &k8smetrics.CounterOpts{
99 Name: "rest_client_request_retries_total",
100 StabilityLevel: k8smetrics.ALPHA,
101 Help: "Number of request retries, partitioned by status code, verb, and host.",
102 },
103 []string{"code", "verb", "host"},
104 )
105
106 execPluginCertTTLAdapter = &expiryToTTLAdapter{}
107
108 execPluginCertTTL = k8smetrics.NewGaugeFunc(
109 &k8smetrics.GaugeOpts{
110 Name: "rest_client_exec_plugin_ttl_seconds",
111 Help: "Gauge of the shortest TTL (time-to-live) of the client " +
112 "certificate(s) managed by the auth exec plugin. The value " +
113 "is in seconds until certificate expiry (negative if " +
114 "already expired). If auth exec plugins are unused or manage no " +
115 "TLS certificates, the value will be +INF.",
116 StabilityLevel: k8smetrics.ALPHA,
117 },
118 func() float64 {
119 if execPluginCertTTLAdapter.e == nil {
120 return math.Inf(1)
121 }
122 return execPluginCertTTLAdapter.e.Sub(time.Now()).Seconds()
123 },
124 )
125
126 execPluginCertRotation = k8smetrics.NewHistogram(
127 &k8smetrics.HistogramOpts{
128 Name: "rest_client_exec_plugin_certificate_rotation_age",
129 Help: "Histogram of the number of seconds the last auth exec " +
130 "plugin client certificate lived before being rotated. " +
131 "If auth exec plugin client certificates are unused, " +
132 "histogram will contain no data.",
133
134
135
136
137
138
139 StabilityLevel: k8smetrics.ALPHA,
140 Buckets: []float64{
141 600,
142 1800,
143 3600,
144 14400,
145 86400,
146 604800,
147 2592000,
148 7776000,
149 15552000,
150 31104000,
151 124416000,
152 },
153 },
154 )
155
156 execPluginCalls = k8smetrics.NewCounterVec(
157 &k8smetrics.CounterOpts{
158 StabilityLevel: k8smetrics.ALPHA,
159 Name: "rest_client_exec_plugin_call_total",
160 Help: "Number of calls to an exec plugin, partitioned by the type of " +
161 "event encountered (no_error, plugin_execution_error, plugin_not_found_error, " +
162 "client_internal_error) and an optional exit code. The exit code will " +
163 "be set to 0 if and only if the plugin call was successful.",
164 },
165 []string{"code", "call_status"},
166 )
167
168 transportCacheEntries = k8smetrics.NewGauge(
169 &k8smetrics.GaugeOpts{
170 Name: "rest_client_transport_cache_entries",
171 StabilityLevel: k8smetrics.ALPHA,
172 Help: "Number of transport entries in the internal cache.",
173 },
174 )
175
176 transportCacheCalls = k8smetrics.NewCounterVec(
177 &k8smetrics.CounterOpts{
178 Name: "rest_client_transport_create_calls_total",
179 StabilityLevel: k8smetrics.ALPHA,
180 Help: "Number of calls to get a new transport, partitioned by the result of the operation " +
181 "hit: obtained from the cache, miss: created and added to the cache, uncacheable: created and not cached",
182 },
183 []string{"result"},
184 )
185 )
186
187 func init() {
188
189 legacyregistry.MustRegister(requestLatency)
190 legacyregistry.MustRegister(requestSize)
191 legacyregistry.MustRegister(responseSize)
192 legacyregistry.MustRegister(rateLimiterLatency)
193 legacyregistry.MustRegister(requestResult)
194 legacyregistry.MustRegister(requestRetry)
195 legacyregistry.RawMustRegister(execPluginCertTTL)
196 legacyregistry.MustRegister(execPluginCertRotation)
197 legacyregistry.MustRegister(execPluginCalls)
198 legacyregistry.MustRegister(transportCacheEntries)
199 legacyregistry.MustRegister(transportCacheCalls)
200 metrics.Register(metrics.RegisterOpts{
201 ClientCertExpiry: execPluginCertTTLAdapter,
202 ClientCertRotationAge: &rotationAdapter{m: execPluginCertRotation},
203 RequestLatency: &latencyAdapter{m: requestLatency},
204 ResolverLatency: &resolverLatencyAdapter{m: resolverLatency},
205 RequestSize: &sizeAdapter{m: requestSize},
206 ResponseSize: &sizeAdapter{m: responseSize},
207 RateLimiterLatency: &latencyAdapter{m: rateLimiterLatency},
208 RequestResult: &resultAdapter{requestResult},
209 RequestRetry: &retryAdapter{requestRetry},
210 ExecPluginCalls: &callsAdapter{m: execPluginCalls},
211 TransportCacheEntries: &transportCacheAdapter{m: transportCacheEntries},
212 TransportCreateCalls: &transportCacheCallsAdapter{m: transportCacheCalls},
213 })
214 }
215
216 type latencyAdapter struct {
217 m *k8smetrics.HistogramVec
218 }
219
220 func (l *latencyAdapter) Observe(ctx context.Context, verb string, u url.URL, latency time.Duration) {
221 l.m.WithContext(ctx).WithLabelValues(verb, u.Host).Observe(latency.Seconds())
222 }
223
224 type resolverLatencyAdapter struct {
225 m *k8smetrics.HistogramVec
226 }
227
228 func (l *resolverLatencyAdapter) Observe(ctx context.Context, host string, latency time.Duration) {
229 l.m.WithContext(ctx).WithLabelValues(host).Observe(latency.Seconds())
230 }
231
232 type sizeAdapter struct {
233 m *k8smetrics.HistogramVec
234 }
235
236 func (s *sizeAdapter) Observe(ctx context.Context, verb string, host string, size float64) {
237 s.m.WithContext(ctx).WithLabelValues(verb, host).Observe(size)
238 }
239
240 type resultAdapter struct {
241 m *k8smetrics.CounterVec
242 }
243
244 func (r *resultAdapter) Increment(ctx context.Context, code, method, host string) {
245 r.m.WithContext(ctx).WithLabelValues(code, method, host).Inc()
246 }
247
248 type expiryToTTLAdapter struct {
249 e *time.Time
250 }
251
252 func (e *expiryToTTLAdapter) Set(expiry *time.Time) {
253 e.e = expiry
254 }
255
256 type rotationAdapter struct {
257 m *k8smetrics.Histogram
258 }
259
260 func (r *rotationAdapter) Observe(d time.Duration) {
261 r.m.Observe(d.Seconds())
262 }
263
264 type callsAdapter struct {
265 m *k8smetrics.CounterVec
266 }
267
268 func (r *callsAdapter) Increment(code int, callStatus string) {
269 r.m.WithLabelValues(fmt.Sprintf("%d", code), callStatus).Inc()
270 }
271
272 type retryAdapter struct {
273 m *k8smetrics.CounterVec
274 }
275
276 func (r *retryAdapter) IncrementRetry(ctx context.Context, code, method, host string) {
277 r.m.WithContext(ctx).WithLabelValues(code, method, host).Inc()
278 }
279
280 type transportCacheAdapter struct {
281 m *k8smetrics.Gauge
282 }
283
284 func (t *transportCacheAdapter) Observe(value int) {
285 t.m.Set(float64(value))
286 }
287
288 type transportCacheCallsAdapter struct {
289 m *k8smetrics.CounterVec
290 }
291
292 func (t *transportCacheCallsAdapter) Increment(result string) {
293 t.m.WithLabelValues(result).Inc()
294 }
295
View as plain text