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  }