Remove implicit Prometheus metrics from client

pull/6/head
Kris 2016-08-15 11:31:44 -07:00
parent ea805efa4f
commit 8d6ce0dcc6
14 changed files with 129 additions and 48 deletions

View File

@ -23,6 +23,8 @@ package main
import ( import (
"os" "os"
_ "k8s.io/kubernetes/pkg/client/metrics/prometheus" // for client metric registration
) )
func main() { func main() {

View File

@ -26,6 +26,7 @@ import (
"k8s.io/kubernetes/cmd/kube-apiserver/app" "k8s.io/kubernetes/cmd/kube-apiserver/app"
"k8s.io/kubernetes/cmd/kube-apiserver/app/options" "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/flag"
"k8s.io/kubernetes/pkg/util/logs" "k8s.io/kubernetes/pkg/util/logs"
"k8s.io/kubernetes/pkg/version/verflag" "k8s.io/kubernetes/pkg/version/verflag"

View File

@ -26,6 +26,7 @@ import (
"k8s.io/kubernetes/cmd/kube-controller-manager/app" "k8s.io/kubernetes/cmd/kube-controller-manager/app"
"k8s.io/kubernetes/cmd/kube-controller-manager/app/options" "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/healthz"
"k8s.io/kubernetes/pkg/util/flag" "k8s.io/kubernetes/pkg/util/flag"
"k8s.io/kubernetes/pkg/util/logs" "k8s.io/kubernetes/pkg/util/logs"

View File

@ -20,6 +20,7 @@ import (
"github.com/spf13/pflag" "github.com/spf13/pflag"
"k8s.io/kubernetes/cmd/kube-dns/app" "k8s.io/kubernetes/cmd/kube-dns/app"
"k8s.io/kubernetes/cmd/kube-dns/app/options" "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/flag"
"k8s.io/kubernetes/pkg/util/logs" "k8s.io/kubernetes/pkg/util/logs"
"k8s.io/kubernetes/pkg/version/verflag" "k8s.io/kubernetes/pkg/version/verflag"

View File

@ -22,6 +22,7 @@ import (
"k8s.io/kubernetes/cmd/kube-proxy/app" "k8s.io/kubernetes/cmd/kube-proxy/app"
"k8s.io/kubernetes/cmd/kube-proxy/app/options" "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/healthz"
"k8s.io/kubernetes/pkg/util/flag" "k8s.io/kubernetes/pkg/util/flag"
"k8s.io/kubernetes/pkg/util/logs" "k8s.io/kubernetes/pkg/util/logs"

View File

@ -19,6 +19,7 @@ package app
import ( import (
"os" "os"
_ "k8s.io/kubernetes/pkg/client/metrics/prometheus" // for client metric registration
"k8s.io/kubernetes/pkg/kubectl/cmd" "k8s.io/kubernetes/pkg/kubectl/cmd"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/util/logs" "k8s.io/kubernetes/pkg/util/logs"

View File

@ -26,6 +26,7 @@ import (
"k8s.io/kubernetes/cmd/kubelet/app" "k8s.io/kubernetes/cmd/kubelet/app"
"k8s.io/kubernetes/cmd/kubelet/app/options" "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/flag"
"k8s.io/kubernetes/pkg/util/logs" "k8s.io/kubernetes/pkg/util/logs"
"k8s.io/kubernetes/pkg/version/verflag" "k8s.io/kubernetes/pkg/version/verflag"

View File

@ -20,6 +20,7 @@ import (
"fmt" "fmt"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
_ "k8s.io/kubernetes/pkg/client/metrics/prometheus" // for client metric registration
"k8s.io/kubernetes/pkg/client/record" "k8s.io/kubernetes/pkg/client/record"
client "k8s.io/kubernetes/pkg/client/unversioned" client "k8s.io/kubernetes/pkg/client/unversioned"
clientset "k8s.io/kubernetes/pkg/client/unversioned/adapters/internalclientset" clientset "k8s.io/kubernetes/pkg/client/unversioned/adapters/internalclientset"

View File

@ -19,6 +19,8 @@ package main
import ( import (
"os" "os"
_ "k8s.io/kubernetes/pkg/client/metrics/prometheus" // for client metric registration
) )
func main() { func main() {

View File

@ -74,6 +74,8 @@ pkg/apis/imagepolicy/install
pkg/api/v1 pkg/api/v1
pkg/auth/authenticator pkg/auth/authenticator
pkg/auth/authorizer/union pkg/auth/authorizer/union
pkg/client/metrics
pkg/client/metrics/prometheus
pkg/client/testing/core pkg/client/testing/core
pkg/client/unversioned pkg/client/unversioned
pkg/client/unversioned/adapters/internalclientset pkg/client/unversioned/adapters/internalclientset

View File

@ -14,54 +14,48 @@ See the License for the specific language governing permissions and
limitations under the License. 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 package metrics
import ( import (
"net/url"
"sync" "sync"
"time" "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 var registerMetrics sync.Once
// Register registers all metrics to Prometheus with // LatencyMetric observes client latency partitioned by verb and url.
// respect to the RequestLatency. type LatencyMetric interface {
func Register() { Observe(verb string, u url.URL, latency time.Duration)
// Register the metrics. }
// 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() { registerMetrics.Do(func() {
prometheus.MustRegister(RequestLatency) RequestLatency = lm
prometheus.MustRegister(RequestResult) RequestResult = rm
}) })
} }
// Calculates the time since the specified start in microseconds. type noopLatency struct{}
func SinceInMicroseconds(start time.Time) float64 {
return float64(time.Since(start).Nanoseconds() / time.Microsecond.Nanoseconds()) func (noopLatency) Observe(string, url.URL, time.Duration) {}
}
type noopResult struct{}
func (noopResult) Increment(string, string, string) {}

View 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()
}

View File

@ -58,10 +58,6 @@ var (
longThrottleLatency = 50 * time.Millisecond longThrottleLatency = 50 * time.Millisecond
) )
func init() {
metrics.Register()
}
// HTTPClient is an interface for testing a request object. // HTTPClient is an interface for testing a request object.
type HTTPClient interface { type HTTPClient interface {
Do(req *http.Request) (*http.Response, error) 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 // underyling object. This means some useful request info (like the types of field
// selectors in use) will be lost. // selectors in use) will be lost.
// TODO: preserve field selector keys // TODO: preserve field selector keys
func (r Request) finalURLTemplate() string { func (r Request) finalURLTemplate() url.URL {
if len(r.resourceName) != 0 { if len(r.resourceName) != 0 {
r.resourceName = "{name}" r.resourceName = "{name}"
} }
@ -622,7 +618,8 @@ func (r Request) finalURLTemplate() string {
newParams[k] = v newParams[k] = v
} }
r.params = newParams r.params = newParams
return r.URL().String() url := r.URL()
return *url
} }
func (r *Request) tryThrottle() { 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 we have an error (i.e. apiserver down) we report that as a metric label.
if err != nil { if err != nil {
metrics.RequestResult.WithLabelValues(err.Error(), req.verb, url).Inc() metrics.RequestResult.Increment(err.Error(), req.verb, url)
} else { } else {
//Metrics for failure codes //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 //Metrics for total request latency
start := time.Now() start := time.Now()
defer func() { 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 { if r.err != nil {

View File

@ -331,7 +331,8 @@ func TestURLTemplate(t *testing.T) {
if full.String() != "http://localhost/pre1/namespaces/ns/r1/nm?p0=v0" { if full.String() != "http://localhost/pre1/namespaces/ns/r1/nm?p0=v0" {
t.Errorf("unexpected initial URL: %s", full) 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" expected := "http://localhost/pre1/namespaces/%7Bnamespace%7D/r1/%7Bname%7D?p0=%7Bvalue%7D"
if actual != expected { if actual != expected {
t.Errorf("unexpected URL template: %s %s", actual, expected) t.Errorf("unexpected URL template: %s %s", actual, expected)