From 4ff9f0e34a2780395838f38b592af748ce6a2971 Mon Sep 17 00:00:00 2001 From: Daniel Norman <1992255+2color@users.noreply.github.com> Date: Wed, 27 Mar 2024 19:15:55 +0100 Subject: [PATCH] feat: add histograms for req duration and size (#108) --- metrics.go | 47 +++++++++++++---------------------------------- 1 file changed, 13 insertions(+), 34 deletions(-) diff --git a/metrics.go b/metrics.go index 05f05aa..bc34eac 100644 --- a/metrics.go +++ b/metrics.go @@ -19,38 +19,17 @@ func registerVersionMetric(version string) { m.Set(1) } -// httpMetricsObjectives Objectives map defines the quantile objectives for a -// summary metric in Prometheus. Each key-value pair in the map represents a -// quantile level and the desired maximum error allowed for that quantile. -// -// Adjusting the objectives control the trade-off between -// accuracy and resource usage for the summary metric. -// -// Example: 0.95: 0.005 means that the 95th percentile (P95) should have a -// maximum error of 0.005, which represents a 0.5% error margin. -var httpMetricsObjectives = map[float64]float64{ - 0.5: 0.05, - 0.75: 0.025, - 0.9: 0.01, - 0.95: 0.005, - 0.99: 0.001, -} - // withHTTPMetrics collects metrics around HTTP request/response count, duration, and size // per specific handler. Allows us to track them separately for /ipns and /ipfs. func withHTTPMetrics(handler http.Handler, handlerName string) http.Handler { - // HTTP metric template names match Kubo: - // https://github.com/ipfs/kubo/blob/e550d9e4761ea394357c413c02ade142c0dea88c/core/corehttp/metrics.go#L79-L152 - // This allows Kubo users to migrate to rainbow and compare global totals. - opts := prometheus.SummaryOpts{ + opts := prometheus.HistogramOpts{ Namespace: "ipfs", Subsystem: "http", - Objectives: httpMetricsObjectives, + Buckets: []float64{0.05, 0.1, 0.2, 0.5, 1, 2, 5, 10, 30, 60}, ConstLabels: prometheus.Labels{"handler": handlerName}, } - // Dynamic labels 'method or 'code' are auto-filled - // by https://pkg.go.dev/github.com/prometheus/client_golang/prometheus/promhttp#InstrumentHandlerResponseSize + labels := []string{"method", "code"} reqWip := prometheus.NewGauge( @@ -77,25 +56,25 @@ func withHTTPMetrics(handler http.Handler, handlerName string) http.Handler { prometheus.MustRegister(reqCnt) opts.Name = "request_duration_seconds" - opts.Help = "The HTTP request latencies in seconds." - reqDur := prometheus.NewSummaryVec(opts, labels) - prometheus.MustRegister(reqDur) + opts.Help = "The HTTP request latencies in seconds. " + reqDurHist := prometheus.NewHistogramVec(opts, labels) + prometheus.MustRegister(reqDurHist) opts.Name = "request_size_bytes" opts.Help = "The HTTP request sizes in bytes." - reqSz := prometheus.NewSummaryVec(opts, labels) - prometheus.MustRegister(reqSz) + reqSzHist := prometheus.NewHistogramVec(opts, labels) + prometheus.MustRegister(reqSzHist) opts.Name = "response_size_bytes" opts.Help = "The HTTP response sizes in bytes." - resSz := prometheus.NewSummaryVec(opts, labels) - prometheus.MustRegister(resSz) + resSzHist := prometheus.NewHistogramVec(opts, labels) + prometheus.MustRegister(resSzHist) handler = promhttp.InstrumentHandlerInFlight(reqWip, handler) handler = promhttp.InstrumentHandlerCounter(reqCnt, handler) - handler = promhttp.InstrumentHandlerDuration(reqDur, handler) - handler = promhttp.InstrumentHandlerRequestSize(reqSz, handler) - handler = promhttp.InstrumentHandlerResponseSize(resSz, handler) + handler = promhttp.InstrumentHandlerDuration(reqDurHist, handler) + handler = promhttp.InstrumentHandlerRequestSize(reqSzHist, handler) + handler = promhttp.InstrumentHandlerResponseSize(resSzHist, handler) return handler }