Improve CollectAndCount

Now that we have also added CollectAndLint and GatherAndLint, I
thought we should bring CollectAndCount in line. So:

- Add GatherAndCount.
- Add filtering by metric name.
- Add tests.

Minor wart: CollectAndCount should now return `(int, error)`, but that
would be a breaking change as the current version just returns
`int`. I decided to let the new version panic when it should return an
error. An error is anyway very unlikely, so the biggest annoyance here
is really just the inconsistency.

Signed-off-by: beorn7 <beorn@grafana.com>
This commit is contained in:
beorn7 2020-05-14 00:17:45 +02:00
parent ce2dae2878
commit 0577ef6c57
2 changed files with 62 additions and 23 deletions

View File

@ -112,31 +112,43 @@ func ToFloat64(c prometheus.Collector) float64 {
panic(fmt.Errorf("collected a non-gauge/counter/untyped metric: %s", pb)) panic(fmt.Errorf("collected a non-gauge/counter/untyped metric: %s", pb))
} }
// CollectAndCount collects all Metrics from the provided Collector and returns their number. // CollectAndCount registers the provided Collector with a newly created
// // pedantic Registry. It then calls GatherAndCount with that Registry and with
// This can be used to assert the number of metrics collected by a given collector after certain operations. // the provided metricNames. In the unlikely case that the registration or the
// // gathering fails, this function panics. (This is inconsistent with the other
// This function is only for testing purposes, and even for testing, other approaches // CollectAnd… functions in this package and has historical reasons. Changing
// are often more appropriate (see this package's documentation). // the function signature would be a breaking change and will therefore only
func CollectAndCount(c prometheus.Collector) int { // happen with the next major version bump.)
var ( func CollectAndCount(c prometheus.Collector, metricNames ...string) int {
mCount int reg := prometheus.NewPedanticRegistry()
mChan = make(chan prometheus.Metric) if err := reg.Register(c); err != nil {
done = make(chan struct{}) panic(fmt.Errorf("registering collector failed: %s", err))
) }
result, err := GatherAndCount(reg, metricNames...)
if err != nil {
panic(err)
}
return result
}
go func() { // GatherAndCount gathers all metrics from the provided Gatherer and counts
for range mChan { // them. It returns the number of metric children in all gathered metric
mCount++ // families together. If any metricNames are provided, only metrics with those
} // names are counted.
close(done) func GatherAndCount(g prometheus.Gatherer, metricNames ...string) (int, error) {
}() got, err := g.Gather()
if err != nil {
return 0, fmt.Errorf("gathering metrics failed: %s", err)
}
if metricNames != nil {
got = filterMetrics(got, metricNames)
}
c.Collect(mChan) result := 0
close(mChan) for _, mf := range got {
<-done result += len(mf.GetMetric())
}
return mCount return result, nil
} }
// CollectAndCompare registers the provided Collector with a newly created // CollectAndCompare registers the provided Collector with a newly created

View File

@ -306,3 +306,30 @@ some_total{label1="value1"} 1
t.Errorf("Expected\n%#+v\nGot:\n%#+v", expectedError, err.Error()) t.Errorf("Expected\n%#+v\nGot:\n%#+v", expectedError, err.Error())
} }
} }
func TestCollectAndCount(t *testing.T) {
c := prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "some_total",
Help: "A value that represents a counter.",
},
[]string{"foo"},
)
if got, want := CollectAndCount(c), 0; got != want {
t.Errorf("unexpected metric count, got %d, want %d", got, want)
}
c.WithLabelValues("bar")
if got, want := CollectAndCount(c), 1; got != want {
t.Errorf("unexpected metric count, got %d, want %d", got, want)
}
c.WithLabelValues("baz")
if got, want := CollectAndCount(c), 2; got != want {
t.Errorf("unexpected metric count, got %d, want %d", got, want)
}
if got, want := CollectAndCount(c, "some_total"), 2; got != want {
t.Errorf("unexpected metric count, got %d, want %d", got, want)
}
if got, want := CollectAndCount(c, "some_other_total"), 0; got != want {
t.Errorf("unexpected metric count, got %d, want %d", got, want)
}
}