github.com/cilium/cilium@v1.16.2/pkg/k8s/watchers/metrics.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package watchers 5 6 import ( 7 "context" 8 "net/url" 9 "strings" 10 11 k8s_metrics "k8s.io/client-go/tools/metrics" 12 "k8s.io/client-go/util/workqueue" 13 14 k8smetrics "github.com/cilium/cilium/pkg/k8s/metrics" 15 "github.com/cilium/cilium/pkg/metrics" 16 "github.com/cilium/cilium/pkg/time" 17 ) 18 19 func init() { 20 // The client-go Register function can be called only once, 21 // but there's a possibility that another package calls it and 22 // registers the client-go metrics on its own registry. 23 // The metrics of one who called the init first will take effect, 24 // and which one wins depends on the order of package initialization. 25 // Currently, controller-runtime also calls it in its init function 26 // because there's an indirect dependency on controller-runtime. 27 // Given the possibility that controller-runtime wins, we should set 28 // the adapters directly to override the metrics registration of 29 // controller-runtime as well as calling Register function. 30 // Without calling Register function here, controller-runtime will have 31 // a chance to override our metrics registration. 32 registerOps := k8s_metrics.RegisterOpts{ 33 ClientCertExpiry: nil, 34 ClientCertRotationAge: nil, 35 RequestLatency: &requestLatencyAdapter{}, 36 RateLimiterLatency: &rateLimiterLatencyAdapter{}, 37 RequestResult: &resultAdapter{}, 38 } 39 k8s_metrics.Register(registerOps) 40 k8s_metrics.RequestLatency = registerOps.RequestLatency 41 k8s_metrics.RateLimiterLatency = registerOps.RateLimiterLatency 42 k8s_metrics.RequestResult = registerOps.RequestResult 43 44 workqueue.SetProvider(workqueueMetricsProvider{}) 45 } 46 47 type workqueueMetricsProvider struct{} 48 49 func (workqueueMetricsProvider) NewDepthMetric(name string) workqueue.GaugeMetric { 50 return metrics.WorkQueueDepth.WithLabelValues(name) 51 } 52 53 func (workqueueMetricsProvider) NewAddsMetric(name string) workqueue.CounterMetric { 54 return metrics.WorkQueueAddsTotal.WithLabelValues(name) 55 } 56 57 func (workqueueMetricsProvider) NewLatencyMetric(name string) workqueue.HistogramMetric { 58 return metrics.WorkQueueLatency.WithLabelValues(name) 59 } 60 61 func (workqueueMetricsProvider) NewWorkDurationMetric(name string) workqueue.HistogramMetric { 62 return metrics.WorkQueueDuration.WithLabelValues(name) 63 } 64 65 func (workqueueMetricsProvider) NewUnfinishedWorkSecondsMetric(name string) workqueue.SettableGaugeMetric { 66 return metrics.WorkQueueUnfinishedWork.WithLabelValues(name) 67 } 68 69 func (workqueueMetricsProvider) NewLongestRunningProcessorSecondsMetric(name string) workqueue.SettableGaugeMetric { 70 return metrics.WorkQueueLongestRunningProcessor.WithLabelValues(name) 71 } 72 73 func (workqueueMetricsProvider) NewRetriesMetric(name string) workqueue.CounterMetric { 74 return metrics.WorkQueueRetries.WithLabelValues(name) 75 } 76 77 // requestLatencyAdapter implements the LatencyMetric interface from k8s client-go package 78 type requestLatencyAdapter struct{} 79 80 func (*requestLatencyAdapter) Observe(_ context.Context, verb string, u url.URL, latency time.Duration) { 81 metrics.KubernetesAPIInteractions.WithLabelValues(u.Path, verb).Observe(latency.Seconds()) 82 } 83 84 // rateLimiterLatencyAdapter implements the LatencyMetric interface from k8s client-go package 85 type rateLimiterLatencyAdapter struct{} 86 87 func (c *rateLimiterLatencyAdapter) Observe(_ context.Context, verb string, u url.URL, latency time.Duration) { 88 metrics.KubernetesAPIRateLimiterLatency.WithLabelValues(u.Path, verb).Observe(latency.Seconds()) 89 } 90 91 // resultAdapter implements the ResultMetric interface from k8s client-go package 92 type resultAdapter struct{} 93 94 func (r *resultAdapter) Increment(_ context.Context, code, method, host string) { 95 metrics.KubernetesAPICallsTotal.WithLabelValues(host, method, code).Inc() 96 // The 'code' is set to '<error>' in case an error is returned from k8s 97 // more info: 98 // https://github.com/kubernetes/client-go/blob/v0.18.0-rc.1/rest/request.go#L700-L703 99 if code != "<error>" { 100 // Consider success only if status code is 2xx 101 if strings.HasPrefix(code, "2") { 102 k8smetrics.LastSuccessInteraction.Reset() 103 } 104 } 105 k8smetrics.LastInteraction.Reset() 106 }