diff --git a/prometheus/promauto/auto_test.go b/prometheus/promauto/auto_test.go new file mode 100644 index 0000000..44805cb --- /dev/null +++ b/prometheus/promauto/auto_test.go @@ -0,0 +1,25 @@ +// Copyright 2020 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package promauto + +import ( + "testing" + + "github.com/prometheus/client_golang/prometheus" +) + +func TestNil(t *testing.T) { + // A nil registerer should be treated as a no-op by promauto. + With(nil).NewCounter(prometheus.CounterOpts{Name: "test"}).Inc() +} diff --git a/prometheus/wrap.go b/prometheus/wrap.go index da6896a..438aa5e 100644 --- a/prometheus/wrap.go +++ b/prometheus/wrap.go @@ -28,7 +28,8 @@ import ( // registered with the wrapped Registerer in a modified way. The modified // Collector adds the provided Labels to all Metrics it collects (as // ConstLabels). The Metrics collected by the unmodified Collector must not -// duplicate any of those labels. +// duplicate any of those labels. Wrapping a nil value is valid, resulting +// in a no-op Registerer. // // WrapRegistererWith provides a way to add fixed labels to a subset of // Collectors. It should not be used to add fixed labels to all metrics exposed. @@ -51,6 +52,7 @@ func WrapRegistererWith(labels Labels, reg Registerer) Registerer { // Registerer. Collectors registered with the returned Registerer will be // registered with the wrapped Registerer in a modified way. The modified // Collector adds the provided prefix to the name of all Metrics it collects. +// Wrapping a nil value is valid, resulting in a no-op Registerer. // // WrapRegistererWithPrefix is useful to have one place to prefix all metrics of // a sub-system. To make this work, register metrics of the sub-system with the @@ -81,6 +83,9 @@ type wrappingRegisterer struct { } func (r *wrappingRegisterer) Register(c Collector) error { + if r.wrappedRegisterer == nil { + return nil + } return r.wrappedRegisterer.Register(&wrappingCollector{ wrappedCollector: c, prefix: r.prefix, @@ -89,6 +94,9 @@ func (r *wrappingRegisterer) Register(c Collector) error { } func (r *wrappingRegisterer) MustRegister(cs ...Collector) { + if r.wrappedRegisterer == nil { + return + } for _, c := range cs { if err := r.Register(c); err != nil { panic(err) @@ -97,6 +105,9 @@ func (r *wrappingRegisterer) MustRegister(cs ...Collector) { } func (r *wrappingRegisterer) Unregister(c Collector) bool { + if r.wrappedRegisterer == nil { + return false + } return r.wrappedRegisterer.Unregister(&wrappingCollector{ wrappedCollector: c, prefix: r.prefix, diff --git a/prometheus/wrap_test.go b/prometheus/wrap_test.go index 256875a..003544e 100644 --- a/prometheus/wrap_test.go +++ b/prometheus/wrap_test.go @@ -321,3 +321,12 @@ func TestWrap(t *testing.T) { } } + +func TestNil(t *testing.T) { + // A wrapped nil registerer should be treated as a no-op, and not panic. + c := NewCounter(CounterOpts{Name: "test"}) + err := WrapRegistererWith(Labels{"foo": "bar"}, nil).Register(c) + if err != nil { + t.Fatal("registering failed:", err) + } +}