X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/16f704326f44fd1e5e5e60b936c9b5895d6a6ff8..f04693da1811e670d4cbb981debeecf14d79137c:/sdk/go/httpserver/request_limiter.go diff --git a/sdk/go/httpserver/request_limiter.go b/sdk/go/httpserver/request_limiter.go index e7192d5b4f..23e6e016d3 100644 --- a/sdk/go/httpserver/request_limiter.go +++ b/sdk/go/httpserver/request_limiter.go @@ -6,6 +6,9 @@ package httpserver import ( "net/http" + "sync/atomic" + + "github.com/prometheus/client_golang/prometheus" ) // RequestCounter is an http.Handler that tracks the number of @@ -24,19 +27,45 @@ type RequestCounter interface { type limiterHandler struct { requests chan struct{} handler http.Handler + count int64 // only used if cap(requests)==0 } // NewRequestLimiter returns a RequestCounter that delegates up to // maxRequests at a time to the given handler, and responds 503 to all // incoming requests beyond that limit. -func NewRequestLimiter(maxRequests int, handler http.Handler) RequestCounter { - return &limiterHandler{ +// +// "concurrent_requests" and "max_concurrent_requests" metrics are +// registered with the given reg, if reg is not nil. +func NewRequestLimiter(maxRequests int, handler http.Handler, reg *prometheus.Registry) RequestCounter { + h := &limiterHandler{ requests: make(chan struct{}, maxRequests), handler: handler, } + if reg != nil { + reg.MustRegister(prometheus.NewGaugeFunc( + prometheus.GaugeOpts{ + Namespace: "arvados", + Name: "concurrent_requests", + Help: "Number of requests in progress", + }, + func() float64 { return float64(h.Current()) }, + )) + reg.MustRegister(prometheus.NewGaugeFunc( + prometheus.GaugeOpts{ + Namespace: "arvados", + Name: "max_concurrent_requests", + Help: "Maximum number of concurrent requests", + }, + func() float64 { return float64(h.Max()) }, + )) + } + return h } func (h *limiterHandler) Current() int { + if cap(h.requests) == 0 { + return int(atomic.LoadInt64(&h.count)) + } return len(h.requests) } @@ -45,6 +74,11 @@ func (h *limiterHandler) Max() int { } func (h *limiterHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) { + if cap(h.requests) == 0 { + atomic.AddInt64(&h.count, 1) + h.handler.ServeHTTP(resp, req) + atomic.AddInt64(&h.count, -1) + } select { case h.requests <- struct{}{}: default: