123 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			123 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Go
		
	
	
	
| package middleware
 | |
| 
 | |
| import (
 | |
| 	"net/http"
 | |
| 
 | |
| 	"github.com/justinas/alice"
 | |
| 	"github.com/prometheus/client_golang/prometheus"
 | |
| 	"github.com/prometheus/client_golang/prometheus/promhttp"
 | |
| )
 | |
| 
 | |
| // DefaultMetricsHandler is the default http.Handler for serving metrics from
 | |
| // the default prometheus.Registry
 | |
| var DefaultMetricsHandler = NewMetricsHandlerWithDefaultRegistry()
 | |
| 
 | |
| // NewMetricsHandlerWithDefaultRegistry creates a new http.Handler for serving
 | |
| // metrics from the default prometheus.Registry.
 | |
| func NewMetricsHandlerWithDefaultRegistry() http.Handler {
 | |
| 	return NewMetricsHandler(prometheus.DefaultRegisterer, prometheus.DefaultGatherer)
 | |
| }
 | |
| 
 | |
| // NewMetricsHandler creates a new http.Handler for serving metrics from the
 | |
| // provided prometheus.Registerer and prometheus.Gatherer
 | |
| func NewMetricsHandler(registerer prometheus.Registerer, gatherer prometheus.Gatherer) http.Handler {
 | |
| 	return promhttp.InstrumentMetricHandler(
 | |
| 		registerer, promhttp.HandlerFor(gatherer, promhttp.HandlerOpts{}),
 | |
| 	)
 | |
| }
 | |
| 
 | |
| // NewRequestMetricsWithDefaultRegistry returns a middleware that will record
 | |
| // metrics for HTTP requests to the default prometheus.Registry
 | |
| func NewRequestMetricsWithDefaultRegistry() alice.Constructor {
 | |
| 	return NewRequestMetrics(prometheus.DefaultRegisterer)
 | |
| }
 | |
| 
 | |
| // NewRequestMetrics returns a middleware that will record metrics for HTTP
 | |
| // requests to the provided prometheus.Registerer
 | |
| func NewRequestMetrics(registerer prometheus.Registerer) alice.Constructor {
 | |
| 	return func(next http.Handler) http.Handler {
 | |
| 		// Counter for all requests
 | |
| 		// This is bucketed based on the response code we set
 | |
| 		counterHandler := func(next http.Handler) http.Handler {
 | |
| 			return promhttp.InstrumentHandlerCounter(registerRequestsCounter(registerer), next)
 | |
| 		}
 | |
| 
 | |
| 		// Gauge to all requests currently being handled
 | |
| 		inFlightHandler := func(next http.Handler) http.Handler {
 | |
| 			return promhttp.InstrumentHandlerInFlight(registerInflightRequestsGauge(registerer), next)
 | |
| 		}
 | |
| 
 | |
| 		// The latency of all requests bucketed by HTTP method
 | |
| 		durationHandler := func(next http.Handler) http.Handler {
 | |
| 			return promhttp.InstrumentHandlerDuration(registerRequestsLatencyHistogram(registerer), next)
 | |
| 		}
 | |
| 
 | |
| 		return alice.New(counterHandler, inFlightHandler, durationHandler).Then(next)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // registerRequestsCounter registers the 'oauth2_proxy_requests_total' metric
 | |
| // This keeps a tally of all received requests bucket by their HTTP response
 | |
| // status code
 | |
| func registerRequestsCounter(registerer prometheus.Registerer) *prometheus.CounterVec {
 | |
| 	counter := prometheus.NewCounterVec(
 | |
| 		prometheus.CounterOpts{
 | |
| 			Name: "oauth2_proxy_requests_total",
 | |
| 			Help: "Total number of requests by HTTP status code.",
 | |
| 		},
 | |
| 		[]string{"code"},
 | |
| 	)
 | |
| 
 | |
| 	if err := registerer.Register(counter); err != nil {
 | |
| 		if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
 | |
| 			counter = are.ExistingCollector.(*prometheus.CounterVec)
 | |
| 		} else {
 | |
| 			panic(err)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return counter
 | |
| }
 | |
| 
 | |
| // registerInflightRequestsGauge registers 'oauth2_proxy_requests_in_flight'
 | |
| // This only keeps the count of currently in progress HTTP requests
 | |
| func registerInflightRequestsGauge(registerer prometheus.Registerer) prometheus.Gauge {
 | |
| 	gauge := prometheus.NewGauge(prometheus.GaugeOpts{
 | |
| 		Name: "oauth2_proxy_requests_in_flight",
 | |
| 		Help: "Current number of requests being served.",
 | |
| 	})
 | |
| 
 | |
| 	if err := registerer.Register(gauge); err != nil {
 | |
| 		if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
 | |
| 			gauge = are.ExistingCollector.(prometheus.Gauge)
 | |
| 		} else {
 | |
| 			panic(err)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return gauge
 | |
| }
 | |
| 
 | |
| // registerRequestsLatencyHistogram registers 'oauth2_proxy_response_duration_seconds'
 | |
| // This keeps tally of the requests bucketed by the time taken to process the request
 | |
| func registerRequestsLatencyHistogram(registerer prometheus.Registerer) *prometheus.HistogramVec {
 | |
| 	histogram := prometheus.NewHistogramVec(
 | |
| 		prometheus.HistogramOpts{
 | |
| 			Name:    "oauth2_proxy_response_duration_seconds",
 | |
| 			Help:    "A histogram of request latencies.",
 | |
| 			Buckets: prometheus.DefBuckets,
 | |
| 		},
 | |
| 		[]string{"method"},
 | |
| 	)
 | |
| 
 | |
| 	if err := registerer.Register(histogram); err != nil {
 | |
| 		if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
 | |
| 			histogram = are.ExistingCollector.(*prometheus.HistogramVec)
 | |
| 		} else {
 | |
| 			panic(err)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return histogram
 | |
| }
 |