mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 12:18:16 +00:00 
			
		
		
		
	Merge pull request #30638 from krousey/metrics_registration
Automatic merge from submit-queue Remove implicit Prometheus metrics from client **What this PR does / why we need it**: This PR starts to cut away at dependencies that the client has. **Release note**: <!-- Steps to write your release note: 1. Use the release-note-* labels to set the release note state (if you have access) 2. Enter your extended release note in the below block; leaving it blank means using the PR title as the release note. If no release note is required, just write `NONE`. --> ```release-note The implicit registration of Prometheus metrics for request count and latency have been removed, and a plug-able interface was added. If you were using our client libraries in your own binaries and want these metrics, add the following to your imports in the main package: "k8s.io/pkg/client/metrics/prometheus". ``` cc: @kubernetes/sig-api-machinery @kubernetes/sig-instrumentation @fgrzadkowski @wojtek-t
This commit is contained in:
		@@ -23,6 +23,8 @@ package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	_ "k8s.io/kubernetes/pkg/client/metrics/prometheus" // for client metric registration
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,7 @@ import (
 | 
			
		||||
 | 
			
		||||
	"k8s.io/kubernetes/cmd/kube-apiserver/app"
 | 
			
		||||
	"k8s.io/kubernetes/cmd/kube-apiserver/app/options"
 | 
			
		||||
	_ "k8s.io/kubernetes/pkg/client/metrics/prometheus" // for client metric registration
 | 
			
		||||
	"k8s.io/kubernetes/pkg/util/flag"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/util/logs"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/version/verflag"
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,7 @@ import (
 | 
			
		||||
 | 
			
		||||
	"k8s.io/kubernetes/cmd/kube-controller-manager/app"
 | 
			
		||||
	"k8s.io/kubernetes/cmd/kube-controller-manager/app/options"
 | 
			
		||||
	_ "k8s.io/kubernetes/pkg/client/metrics/prometheus" // for client metric registration
 | 
			
		||||
	"k8s.io/kubernetes/pkg/healthz"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/util/flag"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/util/logs"
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,7 @@ import (
 | 
			
		||||
	"github.com/spf13/pflag"
 | 
			
		||||
	"k8s.io/kubernetes/cmd/kube-dns/app"
 | 
			
		||||
	"k8s.io/kubernetes/cmd/kube-dns/app/options"
 | 
			
		||||
	_ "k8s.io/kubernetes/pkg/client/metrics/prometheus" // for client metric registration
 | 
			
		||||
	"k8s.io/kubernetes/pkg/util/flag"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/util/logs"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/version/verflag"
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,7 @@ import (
 | 
			
		||||
 | 
			
		||||
	"k8s.io/kubernetes/cmd/kube-proxy/app"
 | 
			
		||||
	"k8s.io/kubernetes/cmd/kube-proxy/app/options"
 | 
			
		||||
	_ "k8s.io/kubernetes/pkg/client/metrics/prometheus" // for client metric registration
 | 
			
		||||
	"k8s.io/kubernetes/pkg/healthz"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/util/flag"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/util/logs"
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@ package app
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	_ "k8s.io/kubernetes/pkg/client/metrics/prometheus" // for client metric registration
 | 
			
		||||
	"k8s.io/kubernetes/pkg/kubectl/cmd"
 | 
			
		||||
	cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/util/logs"
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,7 @@ import (
 | 
			
		||||
 | 
			
		||||
	"k8s.io/kubernetes/cmd/kubelet/app"
 | 
			
		||||
	"k8s.io/kubernetes/cmd/kubelet/app/options"
 | 
			
		||||
	_ "k8s.io/kubernetes/pkg/client/metrics/prometheus" // for client metric registration
 | 
			
		||||
	"k8s.io/kubernetes/pkg/util/flag"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/util/logs"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/version/verflag"
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,7 @@ import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"k8s.io/kubernetes/pkg/api"
 | 
			
		||||
	_ "k8s.io/kubernetes/pkg/client/metrics/prometheus" // for client metric registration
 | 
			
		||||
	"k8s.io/kubernetes/pkg/client/record"
 | 
			
		||||
	client "k8s.io/kubernetes/pkg/client/unversioned"
 | 
			
		||||
	clientset "k8s.io/kubernetes/pkg/client/unversioned/adapters/internalclientset"
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,8 @@ package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	_ "k8s.io/kubernetes/pkg/client/metrics/prometheus" // for client metric registration
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
 
 | 
			
		||||
@@ -74,6 +74,8 @@ pkg/apis/imagepolicy/install
 | 
			
		||||
pkg/api/v1
 | 
			
		||||
pkg/auth/authenticator
 | 
			
		||||
pkg/auth/authorizer/union
 | 
			
		||||
pkg/client/metrics
 | 
			
		||||
pkg/client/metrics/prometheus
 | 
			
		||||
pkg/client/testing/core
 | 
			
		||||
pkg/client/unversioned
 | 
			
		||||
pkg/client/unversioned/adapters/internalclientset
 | 
			
		||||
 
 | 
			
		||||
@@ -14,54 +14,48 @@ See the License for the specific language governing permissions and
 | 
			
		||||
limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
// Package metrics provides utilities for registering client metrics to Prometheus.
 | 
			
		||||
// Package metrics provides abstractions for registering which metrics
 | 
			
		||||
// to record.
 | 
			
		||||
package metrics
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/prometheus/client_golang/prometheus"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const restClientSubsystem = "rest_client"
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// RequestLatency is a Prometheus Summary metric type partitioned by
 | 
			
		||||
	// "verb" and "url" labels. It is used for the rest client latency metrics.
 | 
			
		||||
	RequestLatency = prometheus.NewSummaryVec(
 | 
			
		||||
		prometheus.SummaryOpts{
 | 
			
		||||
			Subsystem: restClientSubsystem,
 | 
			
		||||
			Name:      "request_latency_microseconds",
 | 
			
		||||
			Help:      "Request latency in microseconds. Broken down by verb and URL",
 | 
			
		||||
			MaxAge:    time.Hour,
 | 
			
		||||
		},
 | 
			
		||||
		[]string{"verb", "url"},
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	RequestResult = prometheus.NewCounterVec(
 | 
			
		||||
		prometheus.CounterOpts{
 | 
			
		||||
			Subsystem: restClientSubsystem,
 | 
			
		||||
			Name:      "request_status_codes",
 | 
			
		||||
			Help:      "Number of http requests, partitioned by metadata",
 | 
			
		||||
		},
 | 
			
		||||
		[]string{"code", "method", "host"},
 | 
			
		||||
	)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var registerMetrics sync.Once
 | 
			
		||||
 | 
			
		||||
// Register registers all metrics to Prometheus with
 | 
			
		||||
// respect to the RequestLatency.
 | 
			
		||||
func Register() {
 | 
			
		||||
	// Register the metrics.
 | 
			
		||||
// LatencyMetric observes client latency partitioned by verb and url.
 | 
			
		||||
type LatencyMetric interface {
 | 
			
		||||
	Observe(verb string, u url.URL, latency time.Duration)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ResultMetric counts response codes partitioned by method and host.
 | 
			
		||||
type ResultMetric interface {
 | 
			
		||||
	Increment(code string, method string, host string)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// RequestLatency is the latency metric that rest clients will update.
 | 
			
		||||
	RequestLatency LatencyMetric = noopLatency{}
 | 
			
		||||
	// RequestResult is the result metric that rest clients will update.
 | 
			
		||||
	RequestResult ResultMetric = noopResult{}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Register registers metrics for the rest client to use. This can
 | 
			
		||||
// only be called once.
 | 
			
		||||
func Register(lm LatencyMetric, rm ResultMetric) {
 | 
			
		||||
	registerMetrics.Do(func() {
 | 
			
		||||
		prometheus.MustRegister(RequestLatency)
 | 
			
		||||
		prometheus.MustRegister(RequestResult)
 | 
			
		||||
		RequestLatency = lm
 | 
			
		||||
		RequestResult = rm
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Calculates the time since the specified start in microseconds.
 | 
			
		||||
func SinceInMicroseconds(start time.Time) float64 {
 | 
			
		||||
	return float64(time.Since(start).Nanoseconds() / time.Microsecond.Nanoseconds())
 | 
			
		||||
}
 | 
			
		||||
type noopLatency struct{}
 | 
			
		||||
 | 
			
		||||
func (noopLatency) Observe(string, url.URL, time.Duration) {}
 | 
			
		||||
 | 
			
		||||
type noopResult struct{}
 | 
			
		||||
 | 
			
		||||
func (noopResult) Increment(string, string, string) {}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										76
									
								
								pkg/client/metrics/prometheus/prometheus.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								pkg/client/metrics/prometheus/prometheus.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,76 @@
 | 
			
		||||
/*
 | 
			
		||||
Copyright 2016 The Kubernetes Authors.
 | 
			
		||||
 | 
			
		||||
Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
you may not use this file except in compliance with the License.
 | 
			
		||||
You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
See the License for the specific language governing permissions and
 | 
			
		||||
limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
// Package prometheus creates and registers prometheus metrics with
 | 
			
		||||
// rest clients. To use this package, you just have to import it.
 | 
			
		||||
package prometheus
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"k8s.io/kubernetes/pkg/client/metrics"
 | 
			
		||||
 | 
			
		||||
	"github.com/prometheus/client_golang/prometheus"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const restClientSubsystem = "rest_client"
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// requestLatency is a Prometheus Summary metric type partitioned by
 | 
			
		||||
	// "verb" and "url" labels. It is used for the rest client latency metrics.
 | 
			
		||||
	requestLatency = prometheus.NewSummaryVec(
 | 
			
		||||
		prometheus.SummaryOpts{
 | 
			
		||||
			Subsystem: restClientSubsystem,
 | 
			
		||||
			Name:      "request_latency_microseconds",
 | 
			
		||||
			Help:      "Request latency in microseconds. Broken down by verb and URL",
 | 
			
		||||
			MaxAge:    time.Hour,
 | 
			
		||||
		},
 | 
			
		||||
		[]string{"verb", "url"},
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	requestResult = prometheus.NewCounterVec(
 | 
			
		||||
		prometheus.CounterOpts{
 | 
			
		||||
			Subsystem: restClientSubsystem,
 | 
			
		||||
			Name:      "request_status_codes",
 | 
			
		||||
			Help:      "Number of http requests, partitioned by metadata",
 | 
			
		||||
		},
 | 
			
		||||
		[]string{"code", "method", "host"},
 | 
			
		||||
	)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	prometheus.MustRegister(requestLatency)
 | 
			
		||||
	prometheus.MustRegister(requestResult)
 | 
			
		||||
	metrics.Register(&latencyAdapter{requestLatency}, &resultAdapter{requestResult})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type latencyAdapter struct {
 | 
			
		||||
	m *prometheus.SummaryVec
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *latencyAdapter) Observe(verb string, u url.URL, latency time.Duration) {
 | 
			
		||||
	microseconds := float64(latency) / float64(time.Microsecond)
 | 
			
		||||
	l.m.WithLabelValues(verb, u.String()).Observe(microseconds)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type resultAdapter struct {
 | 
			
		||||
	m *prometheus.CounterVec
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *resultAdapter) Increment(code, method, host string) {
 | 
			
		||||
	r.m.WithLabelValues(code, method, host).Inc()
 | 
			
		||||
}
 | 
			
		||||
@@ -58,10 +58,6 @@ var (
 | 
			
		||||
	longThrottleLatency = 50 * time.Millisecond
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	metrics.Register()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HTTPClient is an interface for testing a request object.
 | 
			
		||||
type HTTPClient interface {
 | 
			
		||||
	Do(req *http.Request) (*http.Response, error)
 | 
			
		||||
@@ -609,7 +605,7 @@ func (r *Request) URL() *url.URL {
 | 
			
		||||
// underyling object.  This means some useful request info (like the types of field
 | 
			
		||||
// selectors in use) will be lost.
 | 
			
		||||
// TODO: preserve field selector keys
 | 
			
		||||
func (r Request) finalURLTemplate() string {
 | 
			
		||||
func (r Request) finalURLTemplate() url.URL {
 | 
			
		||||
	if len(r.resourceName) != 0 {
 | 
			
		||||
		r.resourceName = "{name}"
 | 
			
		||||
	}
 | 
			
		||||
@@ -622,7 +618,8 @@ func (r Request) finalURLTemplate() string {
 | 
			
		||||
		newParams[k] = v
 | 
			
		||||
	}
 | 
			
		||||
	r.params = newParams
 | 
			
		||||
	return r.URL().String()
 | 
			
		||||
	url := r.URL()
 | 
			
		||||
	return *url
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *Request) tryThrottle() {
 | 
			
		||||
@@ -697,10 +694,10 @@ func updateURLMetrics(req *Request, resp *http.Response, err error) {
 | 
			
		||||
 | 
			
		||||
	// If we have an error (i.e. apiserver down) we report that as a metric label.
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		metrics.RequestResult.WithLabelValues(err.Error(), req.verb, url).Inc()
 | 
			
		||||
		metrics.RequestResult.Increment(err.Error(), req.verb, url)
 | 
			
		||||
	} else {
 | 
			
		||||
		//Metrics for failure codes
 | 
			
		||||
		metrics.RequestResult.WithLabelValues(strconv.Itoa(resp.StatusCode), req.verb, url).Inc()
 | 
			
		||||
		metrics.RequestResult.Increment(strconv.Itoa(resp.StatusCode), req.verb, url)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -775,7 +772,7 @@ func (r *Request) request(fn func(*http.Request, *http.Response)) error {
 | 
			
		||||
	//Metrics for total request latency
 | 
			
		||||
	start := time.Now()
 | 
			
		||||
	defer func() {
 | 
			
		||||
		metrics.RequestLatency.WithLabelValues(r.verb, r.finalURLTemplate()).Observe(metrics.SinceInMicroseconds(start))
 | 
			
		||||
		metrics.RequestLatency.Observe(r.verb, r.finalURLTemplate(), time.Since(start))
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	if r.err != nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -331,7 +331,8 @@ func TestURLTemplate(t *testing.T) {
 | 
			
		||||
	if full.String() != "http://localhost/pre1/namespaces/ns/r1/nm?p0=v0" {
 | 
			
		||||
		t.Errorf("unexpected initial URL: %s", full)
 | 
			
		||||
	}
 | 
			
		||||
	actual := r.finalURLTemplate()
 | 
			
		||||
	actualURL := r.finalURLTemplate()
 | 
			
		||||
	actual := actualURL.String()
 | 
			
		||||
	expected := "http://localhost/pre1/namespaces/%7Bnamespace%7D/r1/%7Bname%7D?p0=%7Bvalue%7D"
 | 
			
		||||
	if actual != expected {
 | 
			
		||||
		t.Errorf("unexpected URL template: %s %s", actual, expected)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user