Instrumentation: Add histogram for request duration (#28364)

Signed-off-by: bergquist <carl.bergquist@gmail.com>
This commit is contained in:
Carl Bergquist 2020-10-20 09:44:38 +02:00 committed by GitHub
parent b036112444
commit edbaa9d681
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 48 additions and 23 deletions

View File

@ -7,12 +7,14 @@ import (
"time" "time"
"github.com/grafana/grafana/pkg/infra/metrics" "github.com/grafana/grafana/pkg/infra/metrics"
"github.com/grafana/grafana/pkg/setting"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"gopkg.in/macaron.v1" "gopkg.in/macaron.v1"
) )
var ( var (
httpRequestsInFlight prometheus.Gauge httpRequestsInFlight prometheus.Gauge
httpRequestDurationHistogram *prometheus.HistogramVec
) )
func init() { func init() {
@ -23,11 +25,22 @@ func init() {
}, },
) )
prometheus.MustRegister(httpRequestsInFlight) httpRequestDurationHistogram = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Namespace: "grafana",
Name: "http_request_duration_seconds",
Help: "Histogram of latencies for HTTP requests.",
Buckets: []float64{.1, .2, .4, 1, 3, 8, 20, 60, 120},
},
[]string{"handler"},
)
prometheus.MustRegister(httpRequestsInFlight, httpRequestDurationHistogram)
} }
// RequestMetrics is a middleware handler that instruments the request // RequestMetrics is a middleware handler that instruments the request
func RequestMetrics(handler string) macaron.Handler { func RequestMetrics(cfg *setting.Cfg) func(handler string) macaron.Handler {
return func(handler string) macaron.Handler {
return func(res http.ResponseWriter, req *http.Request, c *macaron.Context) { return func(res http.ResponseWriter, req *http.Request, c *macaron.Context) {
rw := res.(macaron.ResponseWriter) rw := res.(macaron.ResponseWriter)
now := time.Now() now := time.Now()
@ -40,8 +53,15 @@ func RequestMetrics(handler string) macaron.Handler {
code := sanitizeCode(status) code := sanitizeCode(status)
method := sanitizeMethod(req.Method) method := sanitizeMethod(req.Method)
metrics.MHttpRequestTotal.WithLabelValues(handler, code, method).Inc() metrics.MHttpRequestTotal.WithLabelValues(handler, code, method).Inc()
duration := time.Since(now).Nanoseconds() / int64(time.Millisecond) duration := time.Since(now).Nanoseconds() / int64(time.Millisecond)
// enable histogram and disable summaries for http requests.
if cfg.IsHTTPRequestHistogramEnabled() {
httpRequestDurationHistogram.WithLabelValues(handler).Observe(float64(duration))
} else {
metrics.MHttpRequestSummary.WithLabelValues(handler, code, method).Observe(float64(duration)) metrics.MHttpRequestSummary.WithLabelValues(handler, code, method).Observe(float64(duration))
}
switch { switch {
case strings.HasPrefix(req.RequestURI, "/api/datasources/proxy"): case strings.HasPrefix(req.RequestURI, "/api/datasources/proxy"):
@ -52,6 +72,7 @@ func RequestMetrics(handler string) macaron.Handler {
countPageRequests(status) countPageRequests(status)
} }
} }
}
} }
func countApiRequests(status int) { func countApiRequests(status int) {

View File

@ -273,7 +273,7 @@ func (s *Server) buildServiceGraph(services []*registry.Descriptor) error {
objs := []interface{}{ objs := []interface{}{
bus.GetBus(), bus.GetBus(),
s.cfg, s.cfg,
routing.NewRouteRegister(middleware.RequestMetrics, middleware.RequestTracing), routing.NewRouteRegister(middleware.RequestMetrics(s.cfg), middleware.RequestTracing),
localcache.New(5*time.Minute, 10*time.Minute), localcache.New(5*time.Minute, 10*time.Minute),
s, s,
} }

View File

@ -344,6 +344,10 @@ func (c Cfg) IsDatabaseMetricsEnabled() bool {
return c.FeatureToggles["database_metrics"] return c.FeatureToggles["database_metrics"]
} }
func (c Cfg) IsHTTPRequestHistogramEnabled() bool {
return c.FeatureToggles["http_request_histogram"]
}
type CommandLineArgs struct { type CommandLineArgs struct {
Config string Config string
HomePath string HomePath string