diff options
Diffstat (limited to 'vendor/github.com/prometheus/client_golang/prometheus/promhttp')
9 files changed, 19 insertions, 1190 deletions
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_1_7.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_1_7.go deleted file mode 100644 index 5e38c7ca4..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_1_7.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2017 The Prometheus 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. - -// +build !go1.8 - -package promhttp - -import ( - "io" - "net/http" -) - -func newDelegator(w http.ResponseWriter) delegator { - d := &responseWriterDelegator{ResponseWriter: w} - - _, cn := w.(http.CloseNotifier) - _, fl := w.(http.Flusher) - _, hj := w.(http.Hijacker) - _, rf := w.(io.ReaderFrom) - if cn && fl && hj && rf { - return &fancyDelegator{d} - } - - return d -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_1_8.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_1_8.go deleted file mode 100644 index 98b565096..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_1_8.go +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2017 The Prometheus 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. - -// +build go1.8 - -package promhttp - -import ( - "io" - "net/http" -) - -// newDelegator handles the four different methods of upgrading a -// http.ResponseWriter to delegator. -func newDelegator(w http.ResponseWriter) delegator { - d := &responseWriterDelegator{ResponseWriter: w} - - _, cn := w.(http.CloseNotifier) - _, fl := w.(http.Flusher) - _, hj := w.(http.Hijacker) - _, ps := w.(http.Pusher) - _, rf := w.(io.ReaderFrom) - - // Check for the four most common combination of interfaces a - // http.ResponseWriter might implement. - switch { - case cn && fl && hj && rf && ps: - // All interfaces. - return &fancyPushDelegator{ - fancyDelegator: &fancyDelegator{d}, - p: &pushDelegator{d}, - } - case cn && fl && hj && rf: - // All interfaces, except http.Pusher. - return &fancyDelegator{d} - case ps: - // Just http.Pusher. - return &pushDelegator{d} - } - - return d -} - -type fancyPushDelegator struct { - p *pushDelegator - - *fancyDelegator -} - -func (f *fancyPushDelegator) Push(target string, opts *http.PushOptions) error { - return f.p.Push(target, opts) -} - -type pushDelegator struct { - *responseWriterDelegator -} - -func (f *pushDelegator) Push(target string, opts *http.PushOptions) error { - return f.ResponseWriter.(http.Pusher).Push(target, opts) -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go index 4c70a7af6..b6dd5a266 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go @@ -11,24 +11,21 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package promhttp provides tooling around HTTP servers and clients. +// Copyright (c) 2013, The Prometheus Authors +// All rights reserved. // -// First, the package allows the creation of http.Handler instances to expose -// Prometheus metrics via HTTP. promhttp.Handler acts on the -// prometheus.DefaultGatherer. With HandlerFor, you can create a handler for a -// custom registry or anything that implements the Gatherer interface. It also -// allows the creation of handlers that act differently on errors or allow to -// log errors. -// -// Second, the package provides tooling to instrument instances of http.Handler -// via middleware. Middleware wrappers follow the naming scheme -// InstrumentHandlerX, where X describes the intended use of the middleware. -// See each function's doc comment for specific details. +// Use of this source code is governed by a BSD-style license that can be found +// in the LICENSE file. + +// Package promhttp contains functions to create http.Handler instances to +// expose Prometheus metrics via HTTP. In later versions of this package, it +// will also contain tooling to instrument instances of http.Handler and +// http.RoundTripper. // -// Finally, the package allows for an http.RoundTripper to be instrumented via -// middleware. Middleware wrappers follow the naming scheme -// InstrumentRoundTripperX, where X describes the intended use of the -// middleware. See each function's doc comment for specific details. +// promhttp.Handler acts on the prometheus.DefaultGatherer. With HandlerFor, +// you can create a handler for a custom registry or anything that implements +// the Gatherer interface. It also allows to create handlers that act +// differently on errors or allow to log errors. package promhttp import ( diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http_test.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http_test.go index 413ff7baa..d4a7d4a7b 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http_test.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http_test.go @@ -11,6 +11,12 @@ // See the License for the specific language governing permissions and // limitations under the License. +// Copyright (c) 2013, The Prometheus Authors +// All rights reserved. +// +// Use of this source code is governed by a BSD-style license that can be found +// in the LICENSE file. + package promhttp import ( diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go deleted file mode 100644 index 1cf21f217..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2017 The Prometheus 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 promhttp - -import ( - "net/http" - "time" - - "github.com/prometheus/client_golang/prometheus" -) - -// The RoundTripperFunc type is an adapter to allow the use of ordinary -// functions as RoundTrippers. If f is a function with the appropriate -// signature, RountTripperFunc(f) is a RoundTripper that calls f. -type RoundTripperFunc func(req *http.Request) (*http.Response, error) - -// RoundTrip implements the RoundTripper interface. -func (rt RoundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error) { - return rt(r) -} - -// InstrumentRoundTripperInFlight is a middleware that wraps the provided -// http.RoundTripper. It sets the provided prometheus.Gauge to the number of -// requests currently handled by the wrapped http.RoundTripper. -// -// See the example for ExampleInstrumentRoundTripperDuration for example usage. -func InstrumentRoundTripperInFlight(gauge prometheus.Gauge, next http.RoundTripper) RoundTripperFunc { - return RoundTripperFunc(func(r *http.Request) (*http.Response, error) { - gauge.Inc() - defer gauge.Dec() - return next.RoundTrip(r) - }) -} - -// InstrumentRoundTripperCounter is a middleware that wraps the provided -// http.RoundTripper to observe the request result with the provided CounterVec. -// The CounterVec must have zero, one, or two labels. The only allowed label -// names are "code" and "method". The function panics if any other instance -// labels are provided. Partitioning of the CounterVec happens by HTTP status -// code and/or HTTP method if the respective instance label names are present -// in the CounterVec. For unpartitioned counting, use a CounterVec with -// zero labels. -// -// If the wrapped RoundTripper panics or returns a non-nil error, the Counter -// is not incremented. -// -// See the example for ExampleInstrumentRoundTripperDuration for example usage. -func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.RoundTripper) RoundTripperFunc { - code, method := checkLabels(counter) - - return RoundTripperFunc(func(r *http.Request) (*http.Response, error) { - resp, err := next.RoundTrip(r) - if err == nil { - counter.With(labels(code, method, r.Method, resp.StatusCode)).Inc() - } - return resp, err - }) -} - -// InstrumentRoundTripperDuration is a middleware that wraps the provided -// http.RoundTripper to observe the request duration with the provided ObserverVec. -// The ObserverVec must have zero, one, or two labels. The only allowed label -// names are "code" and "method". The function panics if any other instance -// labels are provided. The Observe method of the Observer in the ObserverVec -// is called with the request duration in seconds. Partitioning happens by HTTP -// status code and/or HTTP method if the respective instance label names are -// present in the ObserverVec. For unpartitioned observations, use an -// ObserverVec with zero labels. Note that partitioning of Histograms is -// expensive and should be used judiciously. -// -// If the wrapped RoundTripper panics or returns a non-nil error, no values are -// reported. -func InstrumentRoundTripperDuration(obs prometheus.ObserverVec, next http.RoundTripper) RoundTripperFunc { - code, method := checkLabels(obs) - - return RoundTripperFunc(func(r *http.Request) (*http.Response, error) { - start := time.Now() - resp, err := next.RoundTrip(r) - if err == nil { - obs.With(labels(code, method, r.Method, resp.StatusCode)).Observe(time.Since(start).Seconds()) - } - return resp, err - }) -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client_1_8.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client_1_8.go deleted file mode 100644 index b51d91052..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client_1_8.go +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2017 The Prometheus 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. - -// +build go1.8 - -package promhttp - -import ( - "context" - "crypto/tls" - "net/http" - "net/http/httptrace" - "time" -) - -// InstrumentTrace is used to offer flexibility in instrumenting the available -// httptrace.ClientTrace hook functions. Each function is passed a float64 -// representing the time in seconds since the start of the http request. A user -// may choose to use separately buckets Histograms, or implement custom -// instance labels on a per function basis. -type InstrumentTrace struct { - GotConn func(float64) - PutIdleConn func(float64) - GotFirstResponseByte func(float64) - Got100Continue func(float64) - DNSStart func(float64) - DNSDone func(float64) - ConnectStart func(float64) - ConnectDone func(float64) - TLSHandshakeStart func(float64) - TLSHandshakeDone func(float64) - WroteHeaders func(float64) - Wait100Continue func(float64) - WroteRequest func(float64) -} - -// InstrumentRoundTripperTrace is a middleware that wraps the provided -// RoundTripper and reports times to hook functions provided in the -// InstrumentTrace struct. Hook functions that are not present in the provided -// InstrumentTrace struct are ignored. Times reported to the hook functions are -// time since the start of the request. Note that partitioning of Histograms -// is expensive and should be used judiciously. -// -// For hook functions that receive an error as an argument, no observations are -// made in the event of a non-nil error value. -// -// See the example for ExampleInstrumentRoundTripperDuration for example usage. -func InstrumentRoundTripperTrace(it *InstrumentTrace, next http.RoundTripper) RoundTripperFunc { - return RoundTripperFunc(func(r *http.Request) (*http.Response, error) { - start := time.Now() - - trace := &httptrace.ClientTrace{ - GotConn: func(_ httptrace.GotConnInfo) { - if it.GotConn != nil { - it.GotConn(time.Since(start).Seconds()) - } - }, - PutIdleConn: func(err error) { - if err != nil { - return - } - if it.PutIdleConn != nil { - it.PutIdleConn(time.Since(start).Seconds()) - } - }, - DNSStart: func(_ httptrace.DNSStartInfo) { - if it.DNSStart != nil { - it.DNSStart(time.Since(start).Seconds()) - } - }, - DNSDone: func(_ httptrace.DNSDoneInfo) { - if it.DNSStart != nil { - it.DNSStart(time.Since(start).Seconds()) - } - }, - ConnectStart: func(_, _ string) { - if it.ConnectStart != nil { - it.ConnectStart(time.Since(start).Seconds()) - } - }, - ConnectDone: func(_, _ string, err error) { - if err != nil { - return - } - if it.ConnectDone != nil { - it.ConnectDone(time.Since(start).Seconds()) - } - }, - GotFirstResponseByte: func() { - if it.GotFirstResponseByte != nil { - it.GotFirstResponseByte(time.Since(start).Seconds()) - } - }, - Got100Continue: func() { - if it.Got100Continue != nil { - it.Got100Continue(time.Since(start).Seconds()) - } - }, - TLSHandshakeStart: func() { - if it.TLSHandshakeStart != nil { - it.TLSHandshakeStart(time.Since(start).Seconds()) - } - }, - TLSHandshakeDone: func(_ tls.ConnectionState, err error) { - if err != nil { - return - } - if it.TLSHandshakeDone != nil { - it.TLSHandshakeDone(time.Since(start).Seconds()) - } - }, - WroteHeaders: func() { - if it.WroteHeaders != nil { - it.WroteHeaders(time.Since(start).Seconds()) - } - }, - Wait100Continue: func() { - if it.Wait100Continue != nil { - it.Wait100Continue(time.Since(start).Seconds()) - } - }, - WroteRequest: func(_ httptrace.WroteRequestInfo) { - if it.WroteRequest != nil { - it.WroteRequest(time.Since(start).Seconds()) - } - }, - } - r = r.WithContext(httptrace.WithClientTrace(context.Background(), trace)) - - return next.RoundTrip(r) - }) -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client_1_8_test.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client_1_8_test.go deleted file mode 100644 index 7e3f5229f..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client_1_8_test.go +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright 2017 The Prometheus 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. - -// +build go1.8 - -package promhttp - -import ( - "log" - "net/http" - "testing" - "time" - - "github.com/prometheus/client_golang/prometheus" -) - -func TestClientMiddlewareAPI(t *testing.T) { - client := http.DefaultClient - client.Timeout = 1 * time.Second - - reg := prometheus.NewRegistry() - - inFlightGauge := prometheus.NewGauge(prometheus.GaugeOpts{ - Name: "client_in_flight_requests", - Help: "A gauge of in-flight requests for the wrapped client.", - }) - - counter := prometheus.NewCounterVec( - prometheus.CounterOpts{ - Name: "client_api_requests_total", - Help: "A counter for requests from the wrapped client.", - }, - []string{"code", "method"}, - ) - - dnsLatencyVec := prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Name: "dns_duration_seconds", - Help: "Trace dns latency histogram.", - Buckets: []float64{.005, .01, .025, .05}, - }, - []string{"event"}, - ) - - tlsLatencyVec := prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Name: "tls_duration_seconds", - Help: "Trace tls latency histogram.", - Buckets: []float64{.05, .1, .25, .5}, - }, - []string{"event"}, - ) - - histVec := prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Name: "request_duration_seconds", - Help: "A histogram of request latencies.", - Buckets: prometheus.DefBuckets, - }, - []string{"method"}, - ) - - reg.MustRegister(counter, tlsLatencyVec, dnsLatencyVec, histVec, inFlightGauge) - - trace := &InstrumentTrace{ - DNSStart: func(t float64) { - dnsLatencyVec.WithLabelValues("dns_start") - }, - DNSDone: func(t float64) { - dnsLatencyVec.WithLabelValues("dns_done") - }, - TLSHandshakeStart: func(t float64) { - tlsLatencyVec.WithLabelValues("tls_handshake_start") - }, - TLSHandshakeDone: func(t float64) { - tlsLatencyVec.WithLabelValues("tls_handshake_done") - }, - } - - client.Transport = InstrumentRoundTripperInFlight(inFlightGauge, - InstrumentRoundTripperCounter(counter, - InstrumentRoundTripperTrace(trace, - InstrumentRoundTripperDuration(histVec, http.DefaultTransport), - ), - ), - ) - - resp, err := client.Get("http://google.com") - if err != nil { - t.Fatalf("%v", err) - } - defer resp.Body.Close() -} - -func ExampleInstrumentRoundTripperDuration() { - client := http.DefaultClient - client.Timeout = 1 * time.Second - - inFlightGauge := prometheus.NewGauge(prometheus.GaugeOpts{ - Name: "client_in_flight_requests", - Help: "A gauge of in-flight requests for the wrapped client.", - }) - - counter := prometheus.NewCounterVec( - prometheus.CounterOpts{ - Name: "client_api_requests_total", - Help: "A counter for requests from the wrapped client.", - }, - []string{"code", "method"}, - ) - - // dnsLatencyVec uses custom buckets based on expected dns durations. - // It has an instance label "event", which is set in the - // DNSStart and DNSDonehook functions defined in the - // InstrumentTrace struct below. - dnsLatencyVec := prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Name: "dns_duration_seconds", - Help: "Trace dns latency histogram.", - Buckets: []float64{.005, .01, .025, .05}, - }, - []string{"event"}, - ) - - // tlsLatencyVec uses custom buckets based on expected tls durations. - // It has an instance label "event", which is set in the - // TLSHandshakeStart and TLSHandshakeDone hook functions defined in the - // InstrumentTrace struct below. - tlsLatencyVec := prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Name: "tls_duration_seconds", - Help: "Trace tls latency histogram.", - Buckets: []float64{.05, .1, .25, .5}, - }, - []string{"event"}, - ) - - // histVec has no labels, making it a zero-dimensional ObserverVec. - histVec := prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Name: "request_duration_seconds", - Help: "A histogram of request latencies.", - Buckets: prometheus.DefBuckets, - }, - []string{}, - ) - - // Register all of the metrics in the standard registry. - prometheus.MustRegister(counter, tlsLatencyVec, dnsLatencyVec, histVec, inFlightGauge) - - // Define functions for the available httptrace.ClientTrace hook - // functions that we want to instrument. - trace := &InstrumentTrace{ - DNSStart: func(t float64) { - dnsLatencyVec.WithLabelValues("dns_start") - }, - DNSDone: func(t float64) { - dnsLatencyVec.WithLabelValues("dns_done") - }, - TLSHandshakeStart: func(t float64) { - tlsLatencyVec.WithLabelValues("tls_handshake_start") - }, - TLSHandshakeDone: func(t float64) { - tlsLatencyVec.WithLabelValues("tls_handshake_done") - }, - } - - // Wrap the default RoundTripper with middleware. - roundTripper := InstrumentRoundTripperInFlight(inFlightGauge, - InstrumentRoundTripperCounter(counter, - InstrumentRoundTripperTrace(trace, - InstrumentRoundTripperDuration(histVec, http.DefaultTransport), - ), - ), - ) - - // Set the RoundTripper on our client. - client.Transport = roundTripper - - resp, err := client.Get("http://google.com") - if err != nil { - log.Printf("error: %v", err) - } - defer resp.Body.Close() -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go deleted file mode 100644 index 1beab4b42..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go +++ /dev/null @@ -1,473 +0,0 @@ -// Copyright 2017 The Prometheus 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 promhttp - -import ( - "bufio" - "io" - "net" - "net/http" - "strconv" - "strings" - "time" - - dto "github.com/prometheus/client_model/go" - - "github.com/prometheus/client_golang/prometheus" -) - -// magicString is used for the hacky label test in checkLabels. Remove once fixed. -const magicString = "zZgWfBxLqvG8kc8IMv3POi2Bb0tZI3vAnBx+gBaFi9FyPzB/CzKUer1yufDa" - -// InstrumentHandlerInFlight is a middleware that wraps the provided -// http.Handler. It sets the provided prometheus.Gauge to the number of -// requests currently handled by the wrapped http.Handler. -// -// See the example for InstrumentHandlerDuration for example usage. -func InstrumentHandlerInFlight(g prometheus.Gauge, next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - g.Inc() - defer g.Dec() - next.ServeHTTP(w, r) - }) -} - -// InstrumentHandlerDuration is a middleware that wraps the provided -// http.Handler to observe the request duration with the provided ObserverVec. -// The ObserverVec must have zero, one, or two labels. The only allowed label -// names are "code" and "method". The function panics if any other instance -// labels are provided. The Observe method of the Observer in the ObserverVec -// is called with the request duration in seconds. Partitioning happens by HTTP -// status code and/or HTTP method if the respective instance label names are -// present in the ObserverVec. For unpartitioned observations, use an -// ObserverVec with zero labels. Note that partitioning of Histograms is -// expensive and should be used judiciously. -// -// If the wrapped Handler does not set a status code, a status code of 200 is assumed. -// -// If the wrapped Handler panics, no values are reported. -func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc { - code, method := checkLabels(obs) - - if code { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - now := time.Now() - d := newDelegator(w) - next.ServeHTTP(d, r) - - obs.With(labels(code, method, r.Method, d.Status())).Observe(time.Since(now).Seconds()) - }) - } - - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - now := time.Now() - next.ServeHTTP(w, r) - obs.With(labels(code, method, r.Method, 0)).Observe(time.Since(now).Seconds()) - }) -} - -// InstrumentHandlerCounter is a middleware that wraps the provided -// http.Handler to observe the request result with the provided CounterVec. -// The CounterVec must have zero, one, or two labels. The only allowed label -// names are "code" and "method". The function panics if any other instance -// labels are provided. Partitioning of the CounterVec happens by HTTP status -// code and/or HTTP method if the respective instance label names are present -// in the CounterVec. For unpartitioned counting, use a CounterVec with -// zero labels. -// -// If the wrapped Handler does not set a status code, a status code of 200 is assumed. -// -// If the wrapped Handler panics, the Counter is not incremented. -// -// See the example for InstrumentHandlerDuration for example usage. -func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler) http.HandlerFunc { - code, method := checkLabels(counter) - - if code { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - d := newDelegator(w) - next.ServeHTTP(d, r) - counter.With(labels(code, method, r.Method, d.Status())).Inc() - }) - } - - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - next.ServeHTTP(w, r) - counter.With(labels(code, method, r.Method, 0)).Inc() - }) -} - -// InstrumentHandlerRequestSize is a middleware that wraps the provided -// http.Handler to observe the request size with the provided ObserverVec. -// The ObserverVec must have zero, one, or two labels. The only allowed label -// names are "code" and "method". The function panics if any other instance -// labels are provided. The Observe method of the Observer in the ObserverVec -// is called with the request size in bytes. Partitioning happens by HTTP -// status code and/or HTTP method if the respective instance label names are -// present in the ObserverVec. For unpartitioned observations, use an -// ObserverVec with zero labels. Note that partitioning of Histograms is -// expensive and should be used judiciously. -// -// If the wrapped Handler does not set a status code, a status code of 200 is assumed. -// -// If the wrapped Handler panics, no values are reported. -// -// See the example for InstrumentHandlerDuration for example usage. -func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc { - code, method := checkLabels(obs) - - if code { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - d := newDelegator(w) - next.ServeHTTP(d, r) - size := computeApproximateRequestSize(r) - obs.With(labels(code, method, r.Method, d.Status())).Observe(float64(size)) - }) - } - - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - next.ServeHTTP(w, r) - size := computeApproximateRequestSize(r) - obs.With(labels(code, method, r.Method, 0)).Observe(float64(size)) - }) -} - -// InstrumentHandlerResponseSize is a middleware that wraps the provided -// http.Handler to observe the response size with the provided ObserverVec. -// The ObserverVec must have zero, one, or two labels. The only allowed label -// names are "code" and "method". The function panics if any other instance -// labels are provided. The Observe method of the Observer in the ObserverVec -// is called with the response size in bytes. Partitioning happens by HTTP -// status code and/or HTTP method if the respective instance label names are -// present in the ObserverVec. For unpartitioned observations, use an -// ObserverVec with zero labels. Note that partitioning of Histograms is -// expensive and should be used judiciously. -// -// If the wrapped Handler does not set a status code, a status code of 200 is assumed. -// -// If the wrapped Handler panics, no values are reported. -// -// See the example for InstrumentHandlerDuration for example usage. -func InstrumentHandlerResponseSize(obs prometheus.ObserverVec, next http.Handler) http.Handler { - code, method := checkLabels(obs) - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - d := newDelegator(w) - next.ServeHTTP(d, r) - obs.With(labels(code, method, r.Method, d.Status())).Observe(float64(d.Written())) - }) -} - -func checkLabels(c prometheus.Collector) (code bool, method bool) { - // TODO(beorn7): Remove this hacky way to check for instance labels - // once Descriptors can have their dimensionality queried. - var ( - desc *prometheus.Desc - pm dto.Metric - ) - - descc := make(chan *prometheus.Desc, 1) - c.Describe(descc) - - select { - case desc = <-descc: - default: - panic("no description provided by collector") - } - select { - case <-descc: - panic("more than one description provided by collector") - default: - } - - close(descc) - - if _, err := prometheus.NewConstMetric(desc, prometheus.UntypedValue, 0); err == nil { - return - } - if m, err := prometheus.NewConstMetric(desc, prometheus.UntypedValue, 0, magicString); err == nil { - if err := m.Write(&pm); err != nil { - panic("error checking metric for labels") - } - for _, label := range pm.Label { - name, value := label.GetName(), label.GetValue() - if value != magicString { - continue - } - switch name { - case "code": - code = true - case "method": - method = true - default: - panic("metric partitioned with non-supported labels") - } - return - } - panic("previously set label not found – this must never happen") - } - if m, err := prometheus.NewConstMetric(desc, prometheus.UntypedValue, 0, magicString, magicString); err == nil { - if err := m.Write(&pm); err != nil { - panic("error checking metric for labels") - } - for _, label := range pm.Label { - name, value := label.GetName(), label.GetValue() - if value != magicString { - continue - } - if name == "code" || name == "method" { - continue - } - panic("metric partitioned with non-supported labels") - } - code = true - method = true - return - } - panic("metric partitioned with non-supported labels") -} - -// emptyLabels is a one-time allocation for non-partitioned metrics to avoid -// unnecessary allocations on each request. -var emptyLabels = prometheus.Labels{} - -func labels(code, method bool, reqMethod string, status int) prometheus.Labels { - if !(code || method) { - return emptyLabels - } - labels := prometheus.Labels{} - - if code { - labels["code"] = sanitizeCode(status) - } - if method { - labels["method"] = sanitizeMethod(reqMethod) - } - - return labels -} - -func computeApproximateRequestSize(r *http.Request) int { - s := 0 - if r.URL != nil { - s += len(r.URL.String()) - } - - s += len(r.Method) - s += len(r.Proto) - for name, values := range r.Header { - s += len(name) - for _, value := range values { - s += len(value) - } - } - s += len(r.Host) - - // N.B. r.Form and r.MultipartForm are assumed to be included in r.URL. - - if r.ContentLength != -1 { - s += int(r.ContentLength) - } - return s -} - -func sanitizeMethod(m string) string { - switch m { - case "GET", "get": - return "get" - case "PUT", "put": - return "put" - case "HEAD", "head": - return "head" - case "POST", "post": - return "post" - case "DELETE", "delete": - return "delete" - case "CONNECT", "connect": - return "connect" - case "OPTIONS", "options": - return "options" - case "NOTIFY", "notify": - return "notify" - default: - return strings.ToLower(m) - } -} - -// If the wrapped http.Handler has not set a status code, i.e. the value is -// currently 0, santizeCode will return 200, for consistency with behavior in -// the stdlib. -func sanitizeCode(s int) string { - switch s { - case 100: - return "100" - case 101: - return "101" - - case 200, 0: - return "200" - case 201: - return "201" - case 202: - return "202" - case 203: - return "203" - case 204: - return "204" - case 205: - return "205" - case 206: - return "206" - - case 300: - return "300" - case 301: - return "301" - case 302: - return "302" - case 304: - return "304" - case 305: - return "305" - case 307: - return "307" - - case 400: - return "400" - case 401: - return "401" - case 402: - return "402" - case 403: - return "403" - case 404: - return "404" - case 405: - return "405" - case 406: - return "406" - case 407: - return "407" - case 408: - return "408" - case 409: - return "409" - case 410: - return "410" - case 411: - return "411" - case 412: - return "412" - case 413: - return "413" - case 414: - return "414" - case 415: - return "415" - case 416: - return "416" - case 417: - return "417" - case 418: - return "418" - - case 500: - return "500" - case 501: - return "501" - case 502: - return "502" - case 503: - return "503" - case 504: - return "504" - case 505: - return "505" - - case 428: - return "428" - case 429: - return "429" - case 431: - return "431" - case 511: - return "511" - - default: - return strconv.Itoa(s) - } -} - -type delegator interface { - Status() int - Written() int64 - - http.ResponseWriter -} - -type responseWriterDelegator struct { - http.ResponseWriter - - handler, method string - status int - written int64 - wroteHeader bool -} - -func (r *responseWriterDelegator) Status() int { - return r.status -} - -func (r *responseWriterDelegator) Written() int64 { - return r.written -} - -func (r *responseWriterDelegator) WriteHeader(code int) { - r.status = code - r.wroteHeader = true - r.ResponseWriter.WriteHeader(code) -} - -func (r *responseWriterDelegator) Write(b []byte) (int, error) { - if !r.wroteHeader { - r.WriteHeader(http.StatusOK) - } - n, err := r.ResponseWriter.Write(b) - r.written += int64(n) - return n, err -} - -type fancyDelegator struct { - *responseWriterDelegator -} - -func (r *fancyDelegator) CloseNotify() <-chan bool { - return r.ResponseWriter.(http.CloseNotifier).CloseNotify() -} - -func (r *fancyDelegator) Hijack() (net.Conn, *bufio.ReadWriter, error) { - return r.ResponseWriter.(http.Hijacker).Hijack() -} - -func (r *fancyDelegator) Flush() { - r.ResponseWriter.(http.Flusher).Flush() -} - -func (r *fancyDelegator) ReadFrom(re io.Reader) (int64, error) { - if !r.wroteHeader { - r.WriteHeader(http.StatusOK) - } - n, err := r.ResponseWriter.(io.ReaderFrom).ReadFrom(re) - r.written += n - return n, err -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server_test.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server_test.go deleted file mode 100644 index ca9f4bf3c..000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server_test.go +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright 2017 The Prometheus 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 promhttp - -import ( - "log" - "net/http" - "net/http/httptest" - "testing" - - "github.com/prometheus/client_golang/prometheus" -) - -func TestMiddlewareAPI(t *testing.T) { - reg := prometheus.NewRegistry() - - inFlightGauge := prometheus.NewGauge(prometheus.GaugeOpts{ - Name: "in_flight_requests", - Help: "A gauge of requests currently being served by the wrapped handler.", - }) - - counter := prometheus.NewCounterVec( - prometheus.CounterOpts{ - Name: "api_requests_total", - Help: "A counter for requests to the wrapped handler.", - }, - []string{"code", "method"}, - ) - - histVec := prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Name: "response_duration_seconds", - Help: "A histogram of request latencies.", - Buckets: prometheus.DefBuckets, - ConstLabels: prometheus.Labels{"handler": "api"}, - }, - []string{"method"}, - ) - - responseSize := prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Name: "push_request_size_bytes", - Help: "A histogram of request sizes for requests.", - Buckets: []float64{200, 500, 900, 1500}, - }, - []string{}, - ) - - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte("OK")) - }) - - reg.MustRegister(inFlightGauge, counter, histVec, responseSize) - - chain := InstrumentHandlerInFlight(inFlightGauge, - InstrumentHandlerCounter(counter, - InstrumentHandlerDuration(histVec, - InstrumentHandlerResponseSize(responseSize, handler), - ), - ), - ) - - r, _ := http.NewRequest("GET", "www.example.com", nil) - w := httptest.NewRecorder() - chain.ServeHTTP(w, r) -} - -func ExampleInstrumentHandlerDuration() { - inFlightGauge := prometheus.NewGauge(prometheus.GaugeOpts{ - Name: "in_flight_requests", - Help: "A gauge of requests currently being served by the wrapped handler.", - }) - - counter := prometheus.NewCounterVec( - prometheus.CounterOpts{ - Name: "api_requests_total", - Help: "A counter for requests to the wrapped handler.", - }, - []string{"code", "method"}, - ) - - // pushVec and pullVec are partitioned by the HTTP method and use custom - // buckets based on the expected request duration. ConstLabels are used - // to set a handler label to mark pushVec as tracking the durations for - // pushes and pullVec as tracking the durations for pulls. Note that - // Name, Help, and Buckets need to be the same for consistency, so we - // use the same HistogramOpts after just modifying the ConstLabels. - histogramOpts := prometheus.HistogramOpts{ - Name: "request_duration_seconds", - Help: "A histogram of latencies for requests.", - Buckets: []float64{.25, .5, 1, 2.5, 5, 10}, - ConstLabels: prometheus.Labels{"handler": "push"}, - } - pushVec := prometheus.NewHistogramVec( - histogramOpts, - []string{"method"}, - ) - histogramOpts.ConstLabels = prometheus.Labels{"handler": "pull"} - pullVec := prometheus.NewHistogramVec( - histogramOpts, - []string{"method"}, - ) - - // responseSize has no labels, making it a zero-dimensional - // ObserverVec. - responseSize := prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Name: "response_size_bytes", - Help: "A histogram of response sizes for requests.", - Buckets: []float64{200, 500, 900, 1500}, - }, - []string{}, - ) - - // Create the handlers that will be wrapped by the middleware. - pushHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte("Push")) - }) - pullHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte("Pull")) - }) - - // Register all of the metrics in the standard registry. - prometheus.MustRegister(inFlightGauge, counter, pullVec, pushVec, responseSize) - - // Wrap the pushHandler with our shared middleware, but use the - // endpoint-specific pushVec with InstrumentHandlerDuration. - pushChain := InstrumentHandlerInFlight(inFlightGauge, - InstrumentHandlerCounter(counter, - InstrumentHandlerDuration(pushVec, - InstrumentHandlerResponseSize(responseSize, pushHandler), - ), - ), - ) - - // Wrap the pushHandler with the shared middleware, but use the - // endpoint-specific pullVec with InstrumentHandlerDuration. - pullChain := InstrumentHandlerInFlight(inFlightGauge, - InstrumentHandlerCounter(counter, - InstrumentHandlerDuration(pullVec, - InstrumentHandlerResponseSize(responseSize, pullHandler), - ), - ), - ) - - http.Handle("/metrics", Handler()) - http.Handle("/push", pushChain) - http.Handle("/pull", pullChain) - - if err := http.ListenAndServe(":3000", nil); err != nil { - log.Fatal(err) - } -} |