11/*
2- Copyright 2018 The Kubernetes Authors.
2+ Copyright 2025 The Kubernetes Authors.
33
44Licensed under the Apache License, Version 2.0 (the "License");
55you may not use this file except in compliance with the License.
@@ -18,6 +18,8 @@ package metrics
1818
1919import (
2020 "context"
21+ "net/url"
22+ "time"
2123
2224 "github.com/prometheus/client_golang/prometheus"
2325 clientmetrics "k8s.io/client-go/tools/metrics"
@@ -28,7 +30,59 @@ import (
2830// from Kubernetes so that we match the core controllers.
2931
3032var (
31- // client metrics.
33+ // client metrics from https://github.com/kubernetes/kubernetes/blob/v1.33.0/staging/src/k8s.io/component-base/metrics/prometheus/restclient/metrics.go
34+ // except for rest_client_exec_plugin_* metrics which controllers wouldn't use
35+
36+ // requestLatency is a Prometheus Histogram metric type partitioned by
37+ // "verb", and "host" labels. It is used for the rest client latency metrics.
38+ requestLatency = prometheus .NewHistogramVec (
39+ prometheus.HistogramOpts {
40+ Name : "rest_client_request_duration_seconds" ,
41+ Help : "Request latency in seconds. Broken down by verb, and host." ,
42+ 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 },
43+ },
44+ []string {"verb" , "host" },
45+ )
46+
47+ // resolverLatency is a Prometheus Histogram metric type partitioned by
48+ // "host" labels. It is used for the rest client DNS resolver latency metrics.
49+ resolverLatency = prometheus .NewHistogramVec (
50+ prometheus.HistogramOpts {
51+ Name : "rest_client_dns_resolution_duration_seconds" ,
52+ Help : "DNS resolver latency in seconds. Broken down by host." ,
53+ Buckets : []float64 {0.005 , 0.025 , 0.1 , 0.25 , 0.5 , 1.0 , 2.0 , 4.0 , 8.0 , 15.0 , 30.0 },
54+ },
55+ []string {"host" },
56+ )
57+
58+ requestSize = prometheus .NewHistogramVec (
59+ prometheus.HistogramOpts {
60+ Name : "rest_client_request_size_bytes" ,
61+ Help : "Request size in bytes. Broken down by verb and host." ,
62+ // 64 bytes to 16MB
63+ Buckets : []float64 {64 , 256 , 512 , 1024 , 4096 , 16384 , 65536 , 262144 , 1048576 , 4194304 , 16777216 },
64+ },
65+ []string {"verb" , "host" },
66+ )
67+
68+ responseSize = prometheus .NewHistogramVec (
69+ prometheus.HistogramOpts {
70+ Name : "rest_client_response_size_bytes" ,
71+ Help : "Response size in bytes. Broken down by verb and host." ,
72+ // 64 bytes to 16MB
73+ Buckets : []float64 {64 , 256 , 512 , 1024 , 4096 , 16384 , 65536 , 262144 , 1048576 , 4194304 , 16777216 },
74+ },
75+ []string {"verb" , "host" },
76+ )
77+
78+ rateLimiterLatency = prometheus .NewHistogramVec (
79+ prometheus.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+ 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 },
83+ },
84+ []string {"verb" , "host" },
85+ )
3286
3387 requestResult = prometheus .NewCounterVec (
3488 prometheus.CounterOpts {
3791 },
3892 []string {"code" , "method" , "host" },
3993 )
94+
95+ requestRetry = prometheus .NewCounterVec (
96+ prometheus.CounterOpts {
97+ Name : "rest_client_request_retries_total" ,
98+ Help : "Number of request retries, partitioned by status code, verb, and host." ,
99+ },
100+ []string {"code" , "verb" , "host" },
101+ )
102+
103+ transportCacheEntries = prometheus .NewGauge (
104+ prometheus.GaugeOpts {
105+ Name : "rest_client_transport_cache_entries" ,
106+ Help : "Number of transport entries in the internal cache." ,
107+ },
108+ )
109+
110+ transportCacheCalls = prometheus .NewCounterVec (
111+ prometheus.CounterOpts {
112+ Name : "rest_client_transport_create_calls_total" ,
113+ Help : "Number of calls to get a new transport, partitioned by the result of the operation " +
114+ "hit: obtained from the cache, miss: created and added to the cache, uncacheable: created and not cached" ,
115+ },
116+ []string {"result" },
117+ )
40118)
41119
42120func init () {
@@ -46,26 +124,101 @@ func init() {
46124// registerClientMetrics sets up the client latency metrics from client-go.
47125func registerClientMetrics () {
48126 // register the metrics with our registry
49- Registry .MustRegister (requestResult )
127+ Registry .MustRegister (requestResult ,
128+ requestLatency ,
129+ resolverLatency ,
130+ requestSize ,
131+ responseSize ,
132+ rateLimiterLatency ,
133+ requestRetry ,
134+ transportCacheEntries ,
135+ transportCacheCalls ,
136+ )
50137
51138 // register the metrics with client-go
52139 clientmetrics .Register (clientmetrics.RegisterOpts {
53- RequestResult : & resultAdapter {metric : requestResult },
140+ RequestResult : & requestResultAdapter {metric : requestResult },
141+ RequestLatency : & requestLatencyAdapter {metric : requestLatency },
142+ ResolverLatency : & resolverLatencyAdapter {metric : resolverLatency },
143+ RequestSize : & requestSizeAdapter {metric : requestSize },
144+ ResponseSize : & responseSizeAdapter {metric : responseSize },
145+ RateLimiterLatency : & rateLimiterLatencyAdapter {metric : rateLimiterLatency },
146+ RequestRetry : & requestRetryAdapter {metric : requestRetry },
147+ TransportCacheEntries : & transportCacheEntriesAdapter {metric : transportCacheEntries },
148+ TransportCreateCalls : & transportCreateCallsAdapter {metric : transportCacheCalls },
54149 })
55150}
56151
57- // this section contains adapters, implementations, and other sundry organic, artisanally
58- // hand-crafted syntax trees required to convince client-go that it actually wants to let
59- // someone use its metrics.
152+ // Prometheus adapters for client-go metrics hooks.
153+
154+ type requestResultAdapter struct {
155+ metric * prometheus.CounterVec
156+ }
157+
158+ func (r * requestResultAdapter ) Increment (_ context.Context , code , method , host string ) {
159+ r .metric .WithLabelValues (code , method , host ).Inc ()
160+ }
161+
162+ type requestLatencyAdapter struct {
163+ metric * prometheus.HistogramVec
164+ }
165+
166+ func (l * requestLatencyAdapter ) Observe (_ context.Context , verb string , u url.URL , latency time.Duration ) {
167+ l .metric .WithLabelValues (verb , u .Host ).Observe (latency .Seconds ())
168+ }
169+
170+ type resolverLatencyAdapter struct {
171+ metric * prometheus.HistogramVec
172+ }
173+
174+ func (r * resolverLatencyAdapter ) Observe (_ context.Context , host string , latency time.Duration ) {
175+ r .metric .WithLabelValues (host ).Observe (latency .Seconds ())
176+ }
177+
178+ type requestSizeAdapter struct {
179+ metric * prometheus.HistogramVec
180+ }
181+
182+ func (s * requestSizeAdapter ) Observe (_ context.Context , verb string , host string , size float64 ) {
183+ s .metric .WithLabelValues (verb , host ).Observe (size )
184+ }
185+
186+ type responseSizeAdapter struct {
187+ metric * prometheus.HistogramVec
188+ }
189+
190+ func (s * responseSizeAdapter ) Observe (_ context.Context , verb string , host string , size float64 ) {
191+ s .metric .WithLabelValues (verb , host ).Observe (size )
192+ }
193+
194+ type rateLimiterLatencyAdapter struct {
195+ metric * prometheus.HistogramVec
196+ }
60197
61- // Client metrics adapters (method #1 for client-go metrics),
62- // copied (more-or-less directly) from k8s.io/kubernetes setup code
63- // (which isn't anywhere in an easily-importable place).
198+ func ( l * rateLimiterLatencyAdapter ) Observe ( _ context. Context , verb string , u url. URL , latency time. Duration ) {
199+ l . metric . WithLabelValues ( verb , u . Host ). Observe ( latency . Seconds ())
200+ }
64201
65- type resultAdapter struct {
202+ type requestRetryAdapter struct {
66203 metric * prometheus.CounterVec
67204}
68205
69- func (r * resultAdapter ) Increment (_ context.Context , code , method , host string ) {
206+ func (r * requestRetryAdapter ) IncrementRetry (_ context.Context , code string , method string , host string ) {
70207 r .metric .WithLabelValues (code , method , host ).Inc ()
71208}
209+
210+ type transportCacheEntriesAdapter struct {
211+ metric prometheus.Gauge
212+ }
213+
214+ func (t * transportCacheEntriesAdapter ) Observe (value int ) {
215+ t .metric .Set (float64 (value ))
216+ }
217+
218+ type transportCreateCallsAdapter struct {
219+ metric * prometheus.CounterVec
220+ }
221+
222+ func (t * transportCreateCallsAdapter ) Increment (result string ) {
223+ t .metric .WithLabelValues (result ).Inc ()
224+ }
0 commit comments