diff --git a/prometheus/examples_test.go b/prometheus/examples_test.go index 14e853d..4be1998 100644 --- a/prometheus/examples_test.go +++ b/prometheus/examples_test.go @@ -161,7 +161,7 @@ func ExampleInstrumentHandler() { // exported to Prometheus, partitioned by HTTP status code and method // and by the handler name (here "fileserver"). http.Handle("/doc", prometheus.InstrumentHandler( - "fileserver", http.FileServer(http.Dir("/usr/share/doc")), + "fileserver", prometheus.DefaultRegistry, http.FileServer(http.Dir("/usr/share/doc")), )) // The Prometheus handler still has to be registered to handle the // "/metrics" endpoint. The handler returned by prometheus.Handler() is @@ -169,7 +169,7 @@ func ExampleInstrumentHandler() { // example, we want the handler name to be "metrics", so we instrument // the uninstrumented Prometheus handler ourselves. http.Handle("/metrics", prometheus.InstrumentHandler( - "metrics", prometheus.UninstrumentedHandler(), + "metrics", prometheus.DefaultRegistry, prometheus.UninstrumentedHandler(), )) } diff --git a/prometheus/http.go b/prometheus/http.go index 46ae4c2..ac3fb1f 100644 --- a/prometheus/http.go +++ b/prometheus/http.go @@ -46,16 +46,16 @@ func nowSeries(t ...time.Time) nower { }) } -// InstrumentHandler wraps the given HTTP handler for instrumentation. It -// registers four metric vector collectors (if not already done) and reports -// http metrics to the (newly or already) registered collectors: +// InstrumentHandler wraps the given HTTP handler with instrumentation. +// It registers four metric vector collectors in the provided Registry. // http_requests_total (CounterVec), http_request_duration_microseconds // (SummaryVec), http_request_size_bytes (SummaryVec), http_response_size_bytes // (SummaryVec). Each has three labels: handler, method, code. The value of the // handler label is set by the handlerName parameter of this function. -func InstrumentHandler(name string, hnd http.Handler) http.Handler { +func InstrumentHandler(name string, r Registry, hnd http.Handler) http.Handler { return InstrumentHandlerWithOpts( SummaryOpts{Subsystem: "http", ConstLabels: Labels{"handler": name}}, + r, hnd, ) } @@ -85,7 +85,7 @@ func InstrumentHandler(name string, hnd http.Handler) http.Handler { // cannot use SummaryOpts. Instead, a CounterOpts struct is created internally, // and all its fields are set to the equally named fields in the provided // SummaryOpts. -func InstrumentHandlerWithOpts(opts SummaryOpts, hnd http.Handler) http.Handler { +func InstrumentHandlerWithOpts(opts SummaryOpts, r Registry, hnd http.Handler) http.Handler { reqCnt := NewCounterVec( CounterOpts{ Namespace: opts.Namespace, @@ -109,10 +109,10 @@ func InstrumentHandlerWithOpts(opts SummaryOpts, hnd http.Handler) http.Handler opts.Help = "The HTTP response sizes in bytes." resSz := NewSummaryVec(opts, instLabels) - regReqCnt := MustRegisterOrGet(reqCnt).(*CounterVec) - regReqDur := MustRegisterOrGet(reqDur).(*SummaryVec) - regReqSz := MustRegisterOrGet(reqSz).(*SummaryVec) - regResSz := MustRegisterOrGet(resSz).(*SummaryVec) + regReqCnt := r.MustRegisterOrGet(reqCnt).(*CounterVec) + regReqDur := r.MustRegisterOrGet(reqDur).(*SummaryVec) + regReqSz := r.MustRegisterOrGet(reqSz).(*SummaryVec) + regResSz := r.MustRegisterOrGet(resSz).(*SummaryVec) return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { now := time.Now() diff --git a/prometheus/http_test.go b/prometheus/http_test.go index da3b75d..075821a 100644 --- a/prometheus/http_test.go +++ b/prometheus/http_test.go @@ -39,14 +39,12 @@ func TestInstrumentHandler(t *testing.T) { now = nowSeries(instant, end) respBody := respBody("Howdy there!") - hndlr := InstrumentHandler("test-handler", respBody) - opts := SummaryOpts{ Subsystem: "http", ConstLabels: Labels{"handler": "test-handler"}, } - reqCnt := MustRegisterOrGet(NewCounterVec( + reqCnt := NewCounterVec( CounterOpts{ Namespace: opts.Namespace, Subsystem: opts.Subsystem, @@ -55,30 +53,21 @@ func TestInstrumentHandler(t *testing.T) { ConstLabels: opts.ConstLabels, }, instLabels, - )).(*CounterVec) + ) opts.Name = "request_duration_microseconds" opts.Help = "The HTTP request latencies in microseconds." - reqDur := MustRegisterOrGet(NewSummaryVec(opts, instLabels)).(*SummaryVec) + reqDur := NewSummaryVec(opts, instLabels) - opts.Name = "request_size_bytes" - opts.Help = "The HTTP request sizes in bytes." - reqSz := MustRegisterOrGet(NewSummaryVec(opts, instLabels)).(*SummaryVec) - - opts.Name = "response_size_bytes" - opts.Help = "The HTTP response sizes in bytes." - resSz := MustRegisterOrGet(NewSummaryVec(opts, instLabels)).(*SummaryVec) - - reqCnt.Reset() - reqDur.Reset() - reqSz.Reset() - resSz.Reset() - - resp := httptest.NewRecorder() - req := &http.Request{ - Method: "GET", + reg, err := NewRegistry(reqCnt, reqDur) + if err != nil { + t.Fatalf("got err: %v", err) } + resp := httptest.NewRecorder() + req := &http.Request{Method: "GET"} + + hndlr := InstrumentHandler("test-handler", reg, respBody) hndlr.ServeHTTP(resp, req) if resp.Code != http.StatusTeapot { diff --git a/prometheus/registry.go b/prometheus/registry.go index 103f03c..093b1be 100644 --- a/prometheus/registry.go +++ b/prometheus/registry.go @@ -125,6 +125,10 @@ type Registry interface { // makes more sense. Register(Collector) (Collector, error) + // MustRegister works like Register but panics where Register would have + // returned an error. + MustRegister(Collector) Collector + // RegisterOrGet works like Register but does not return an error if a Collector // is registered that equals a previously registered Collector. (Two Collectors // are considered equal if their Describe method yields the same set of @@ -140,6 +144,10 @@ type Registry interface { // makes more sense. RegisterOrGet(Collector) (Collector, error) + // MustRegisterOrGet works like Register but panics where RegisterOrGet would + // have returned an error. + MustRegisterOrGet(Collector) Collector + // Unregister unregisters the Collector that equals the Collector passed in as // an argument. (Two Collectors are considered equal if their Describe method // yields the same set of descriptors.) The function returns whether a Collector @@ -268,11 +276,7 @@ func Register(m Collector) (Collector, error) { // MustRegister works like Register but panics where Register would have // returned an error. func MustRegister(m Collector) Collector { - m, err := Register(m) - if err != nil { - panic(err) - } - return m + return DefaultRegistry.MustRegister(m) } // RegisterOrGet works like Register but does not return an error if a Collector @@ -378,7 +382,7 @@ type registry struct { } func (r *registry) Handler() http.Handler { - return InstrumentHandler("prometheus", r.UninstrumentedHandler()) + return InstrumentHandler("prometheus", r, r.UninstrumentedHandler()) } func (r *registry) UninstrumentedHandler() http.Handler { @@ -462,6 +466,14 @@ func (r *registry) Register(c Collector) (Collector, error) { return c, nil } +func (r *registry) MustRegister(m Collector) Collector { + m, err := r.Register(m) + if err != nil { + panic(err) + } + return m +} + func (r *registry) RegisterOrGet(m Collector) (Collector, error) { existing, err := r.Register(m) if err != nil && err != errAlreadyReg { @@ -470,6 +482,14 @@ func (r *registry) RegisterOrGet(m Collector) (Collector, error) { return existing, nil } +func (r *registry) MustRegisterOrGet(m Collector) Collector { + m, err := r.RegisterOrGet(m) + if err != nil { + panic(err) + } + return m +} + func (r *registry) Unregister(c Collector) bool { descChan := make(chan *Desc, capDescChan) go func() {