From 8961609f911516b04f81ac75fc4b0e0b8e455c2e Mon Sep 17 00:00:00 2001 From: Tom Wilkie Date: Thu, 4 Jun 2020 10:30:51 +0100 Subject: [PATCH 1/3] Ensure that nil registers are treat as a no-op, even when wrapping. Signed-off-by: Tom Wilkie --- prometheus/promauto/auto_test.go | 29 +++++++++++++++++++++++++++++ prometheus/wrap.go | 9 +++++++++ 2 files changed, 38 insertions(+) create mode 100644 prometheus/promauto/auto_test.go diff --git a/prometheus/promauto/auto_test.go b/prometheus/promauto/auto_test.go new file mode 100644 index 0000000..5b9c7fe --- /dev/null +++ b/prometheus/promauto/auto_test.go @@ -0,0 +1,29 @@ +// 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 TestWrapNil(t *testing.T) { + // A nil registerer should be treated as a no-op by promauto, even when wrapped. + registerer := prometheus.WrapRegistererWith(prometheus.Labels{"foo": "bar"}, nil) + c := With(registerer).NewCounter(prometheus.CounterOpts{ + Name: "test", + }) + c.Inc() +} diff --git a/prometheus/wrap.go b/prometheus/wrap.go index da6896a..ef6fdec 100644 --- a/prometheus/wrap.go +++ b/prometheus/wrap.go @@ -81,6 +81,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 +92,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 +103,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, From 614377c5501cb1666a3b057dd23c094d6d13ab24 Mon Sep 17 00:00:00 2001 From: Tom Wilkie Date: Thu, 4 Jun 2020 10:57:40 +0100 Subject: [PATCH 2/3] Review feedback: use one line. Signed-off-by: Tom Wilkie --- prometheus/promauto/auto_test.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/prometheus/promauto/auto_test.go b/prometheus/promauto/auto_test.go index 5b9c7fe..e93817b 100644 --- a/prometheus/promauto/auto_test.go +++ b/prometheus/promauto/auto_test.go @@ -22,8 +22,6 @@ import ( func TestWrapNil(t *testing.T) { // A nil registerer should be treated as a no-op by promauto, even when wrapped. registerer := prometheus.WrapRegistererWith(prometheus.Labels{"foo": "bar"}, nil) - c := With(registerer).NewCounter(prometheus.CounterOpts{ - Name: "test", - }) + c := With(registerer).NewCounter(prometheus.CounterOpts{Name: "test"}) c.Inc() } From 9c8ba1f9451a222e7918818ecff91bac5626dd48 Mon Sep 17 00:00:00 2001 From: Tom Wilkie Date: Thu, 4 Jun 2020 11:51:51 +0100 Subject: [PATCH 3/3] Review feedback: add comment and tests for WrapRegistererWith. Signed-off-by: Tom Wilkie --- prometheus/promauto/auto_test.go | 8 +++----- prometheus/wrap.go | 4 +++- prometheus/wrap_test.go | 9 +++++++++ 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/prometheus/promauto/auto_test.go b/prometheus/promauto/auto_test.go index e93817b..44805cb 100644 --- a/prometheus/promauto/auto_test.go +++ b/prometheus/promauto/auto_test.go @@ -19,9 +19,7 @@ import ( "github.com/prometheus/client_golang/prometheus" ) -func TestWrapNil(t *testing.T) { - // A nil registerer should be treated as a no-op by promauto, even when wrapped. - registerer := prometheus.WrapRegistererWith(prometheus.Labels{"foo": "bar"}, nil) - c := With(registerer).NewCounter(prometheus.CounterOpts{Name: "test"}) - c.Inc() +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 ef6fdec..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 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) + } +}