From 639312c0e24c606365d41c98d95d163913a209fc Mon Sep 17 00:00:00 2001 From: Yesphet Date: Mon, 2 Sep 2024 18:35:04 +0800 Subject: [PATCH 1/2] modify(metrics): expose RegisterClientMetrics to register other client-go metrics --- pkg/metrics/client_go_adapter.go | 36 +++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/pkg/metrics/client_go_adapter.go b/pkg/metrics/client_go_adapter.go index ff28998c44..302c68c419 100644 --- a/pkg/metrics/client_go_adapter.go +++ b/pkg/metrics/client_go_adapter.go @@ -18,6 +18,8 @@ package metrics import ( "context" + "sync" + "time" "github.com/prometheus/client_golang/prometheus" clientmetrics "k8s.io/client-go/tools/metrics" @@ -37,20 +39,30 @@ var ( }, []string{"code", "method", "host"}, ) + + clientMetricsRegisterOnce = sync.Once{} ) func init() { - registerClientMetrics() -} - -// registerClientMetrics sets up the client latency metrics from client-go. -func registerClientMetrics() { // register the metrics with our registry Registry.MustRegister(requestResult) - // register the metrics with client-go - clientmetrics.Register(clientmetrics.RegisterOpts{ - RequestResult: &resultAdapter{metric: requestResult}, + time.AfterFunc(30*time.Second, func() { + RegisterClientMetrics(clientmetrics.RegisterOpts{}) + }) +} + +// RegisterClientMetrics sets up the client latency metrics from client-go. Since clientmetrics.Register can only be +// called once, you MUST call this method if you want to register other client-go metrics within the first 30 seconds +// of a binaries lifetime, or it will get called without other metrics. +func RegisterClientMetrics(opts clientmetrics.RegisterOpts) { + clientMetricsRegisterOnce.Do(func() { + opts.RequestResult = &resultAdapter{ + metric: requestResult, + customMetric: opts.RequestResult, + } + // register the metrics with client-go + clientmetrics.Register(opts) }) } @@ -63,9 +75,13 @@ func registerClientMetrics() { // (which isn't anywhere in an easily-importable place). type resultAdapter struct { - metric *prometheus.CounterVec + metric *prometheus.CounterVec + customMetric clientmetrics.ResultMetric } -func (r *resultAdapter) Increment(_ context.Context, code, method, host string) { +func (r *resultAdapter) Increment(ctx context.Context, code, method, host string) { r.metric.WithLabelValues(code, method, host).Inc() + if r.customMetric != nil { + r.customMetric.Increment(ctx, code, method, host) + } } From d34b8bc0f2efdad5a0fdf6795aba9d7bce16679e Mon Sep 17 00:00:00 2001 From: Yesphet Date: Tue, 8 Oct 2024 11:21:52 +0800 Subject: [PATCH 2/2] mod: add ClientGoMetricsRegisterOpts to metrics server Options and register client-go metrics in NewServer instead of init function --- pkg/metrics/client_go_adapter.go | 33 ++++++++++---------------------- pkg/metrics/server/server.go | 6 ++++++ 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/pkg/metrics/client_go_adapter.go b/pkg/metrics/client_go_adapter.go index 302c68c419..c6e95f29b9 100644 --- a/pkg/metrics/client_go_adapter.go +++ b/pkg/metrics/client_go_adapter.go @@ -18,8 +18,6 @@ package metrics import ( "context" - "sync" - "time" "github.com/prometheus/client_golang/prometheus" clientmetrics "k8s.io/client-go/tools/metrics" @@ -39,31 +37,24 @@ var ( }, []string{"code", "method", "host"}, ) - - clientMetricsRegisterOnce = sync.Once{} ) func init() { // register the metrics with our registry Registry.MustRegister(requestResult) - - time.AfterFunc(30*time.Second, func() { - RegisterClientMetrics(clientmetrics.RegisterOpts{}) - }) } -// RegisterClientMetrics sets up the client latency metrics from client-go. Since clientmetrics.Register can only be -// called once, you MUST call this method if you want to register other client-go metrics within the first 30 seconds -// of a binaries lifetime, or it will get called without other metrics. +// RegisterClientMetrics sets up metrics from client-go. +// Notice that clientmetrics.Register can only be called once, so only the RegisterOpts from the first call to this +// function will take effect. func RegisterClientMetrics(opts clientmetrics.RegisterOpts) { - clientMetricsRegisterOnce.Do(func() { + if opts.RequestResult == nil { opts.RequestResult = &resultAdapter{ - metric: requestResult, - customMetric: opts.RequestResult, + metric: requestResult, } - // register the metrics with client-go - clientmetrics.Register(opts) - }) + } + // register the metrics with client-go + clientmetrics.Register(opts) } // this section contains adapters, implementations, and other sundry organic, artisanally @@ -75,13 +66,9 @@ func RegisterClientMetrics(opts clientmetrics.RegisterOpts) { // (which isn't anywhere in an easily-importable place). type resultAdapter struct { - metric *prometheus.CounterVec - customMetric clientmetrics.ResultMetric + metric *prometheus.CounterVec } -func (r *resultAdapter) Increment(ctx context.Context, code, method, host string) { +func (r *resultAdapter) Increment(_ context.Context, code, method, host string) { r.metric.WithLabelValues(code, method, host).Inc() - if r.customMetric != nil { - r.customMetric.Increment(ctx, code, method, host) - } } diff --git a/pkg/metrics/server/server.go b/pkg/metrics/server/server.go index 5eb0c62a72..5914c8d275 100644 --- a/pkg/metrics/server/server.go +++ b/pkg/metrics/server/server.go @@ -30,6 +30,7 @@ import ( "github.com/go-logr/logr" "github.com/prometheus/client_golang/prometheus/promhttp" "k8s.io/client-go/rest" + clientmetrics "k8s.io/client-go/tools/metrics" certutil "k8s.io/client-go/util/cert" "sigs.k8s.io/controller-runtime/pkg/certwatcher" @@ -82,6 +83,9 @@ type Options struct { // endpoint by setting this field to filters.WithAuthenticationAndAuthorization. FilterProvider func(c *rest.Config, httpClient *http.Client) (Filter, error) + // ClientGoMetricsRegisterOpts contains the options used to register client-go metrics. + ClientGoMetricsRegisterOpts clientmetrics.RegisterOpts + // CertDir is the directory that contains the server key and certificate. Defaults to // /k8s-metrics-server/serving-certs. // @@ -138,6 +142,8 @@ func NewServer(o Options, config *rest.Config, httpClient *http.Client) (Server, } } + metrics.RegisterClientMetrics(o.ClientGoMetricsRegisterOpts) + return &defaultServer{ metricsFilter: metricsFilter, options: o,