普罗米修斯 CollectAndCount 总是 returns 1

prometheus CollectAndCount always returns 1

我想检测一个程序并通过测试检查检测是否正确完成。我发现了 testutil,它有一个名为 CollectAndCount 的函数。我希望函数 returns 与我在 HTTP 指标端点上看到的计数相同。当我在下面的示例中将计数器增加 2 倍时,CollectAndCount returns 1 而不是预期的 2。在这种情况下使用 ToFloat64 函数是可行的。因为我也想获得直方图的计数,所以 ToFloat64 不可用。

package main

import (
    "testing"

    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/testutil"
)

func TestMetricT(t *testing.T) {
    var Duration = prometheus.NewHistogram(prometheus.HistogramOpts{
        Name:    "duration",
        Help:    "Help",
        Buckets: prometheus.DefBuckets,
    })

    var Errors = prometheus.NewCounter(prometheus.CounterOpts{
        Name: "errors",
        Help: "Help",
    })

    prometheus.MustRegister(Duration, Errors)

    timer := prometheus.NewTimer(Duration)
    timer.ObserveDuration()
    Errors.Inc()

    timer = prometheus.NewTimer(Duration)
    timer.ObserveDuration()

    Errors.Inc()

    errors := testutil.CollectAndCount(Errors)
    if errors != 2 {
        t.Error("no 2 increments but", errors, "ToFloat64 counts", testutil.ToFloat64(Errors))
    }

    observations := testutil.CollectAndCount(Duration)
    if observations != 2 {
        t.Error("not 2 observations but", observations)
    }

}

输出为:

--- FAIL: TestMetricT (0.00s)
    so_test.go:35: no 2 increments but 1 ToFloat64 counts 2
    so_test.go:40: not 2 observations but 1
FAIL
FAIL

我使用与您的示例略有不同的指标来说明正在发生的事情,并且我还决定使用 testify 来获得更紧凑的示例。有什么问题欢迎随时提问


TL;DR: CollectAndCount returns 收集的指标数量,ToFloat64 返回单个指标的实际值.

package main

import (
    "testing"

    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/testutil"
    "github.com/stretchr/testify/assert"
)

func TestMetricT(t *testing.T) {
    assert := assert.New(t)

    var A = prometheus.NewCounter(prometheus.CounterOpts{
        Name: "A",
        Help: "Help",
    })

    var B = prometheus.NewCounter(prometheus.CounterOpts{
        Name: "B",
        Help: "Help",
    })

    // CounterVec is a Collector that bundles a set of Counters
    var C = prometheus.NewCounterVec(prometheus.CounterOpts{
        Name: "C",
        Help: "Help",
    }, []string{"subname"},
    )

    prometheus.MustRegister(A, B, C)

    // After the registration, simple metrics like A and B can
    // be collected with the CollectAndCount function.
    // The CollectAndCount function seems to count the number of
    // metrics which were collected, not their value.
    assert.Equal(1, testutil.CollectAndCount(A))
    assert.Equal(1, testutil.CollectAndCount(B))
    // Different to the "simple" metrics like the counters A and B,
    // C is a CounterVec, a collection of counters that share
    // the same description.
    // After its registration, this collection contains 0 metrics,
    // until one is added to the collection.
    assert.Equal(0, testutil.CollectAndCount(C))

    // ToFloat64 returns the actual value of the metric. After the
    // registration, the value of the counters A and B is 0.
    assert.Equal(float64(0), testutil.ToFloat64(A))
    assert.Equal(float64(0), testutil.ToFloat64(B))

    A.Inc()
    B.Inc()

    // After we incremented A and B, CollectAndCount still
    // collects exactly one metric series for A, and one for B.
    assert.Equal(1, testutil.CollectAndCount(A))
    assert.Equal(1, testutil.CollectAndCount(B))
    // But the actual values of the counters were incremented by 1.
    assert.Equal(float64(1), testutil.ToFloat64(A))
    assert.Equal(float64(1), testutil.ToFloat64(B))

    A.Inc()
    B.Inc()

    assert.Equal(1, testutil.CollectAndCount(A))
    assert.Equal(1, testutil.CollectAndCount(B))
    // Now we incremented the counters again, and ToFloat64
    // returns 2, since we've incremented each counter 2 times.
    assert.Equal(float64(2), testutil.ToFloat64(A))
    assert.Equal(float64(2), testutil.ToFloat64(B))

    A.Inc()

    assert.Equal(1, testutil.CollectAndCount(A))
    assert.Equal(1, testutil.CollectAndCount(B))
    // Only incremented A
    assert.Equal(float64(3), testutil.ToFloat64(A))
    assert.Equal(float64(2), testutil.ToFloat64(B))

    // To increment C, we have to use a label. This
    // adds a metric with the label "firstLabel" to the
    // collection C.
    C.WithLabelValues("firstLabel").Inc()
    // Now, CollectAndCount will collect the one metric which
    // is contained in the collection C.
    assert.Equal(1, testutil.CollectAndCount(C))
    // The ToFloat64 value of the metrics is as expected.
    // We have to again use a label here, since we cannot get a
    // single float value from a collection.
    assert.Equal(float64(1), testutil.ToFloat64(C.WithLabelValues("firstLabel")))

    // Let's increase the "firstLabel" metric again and add another one.
    C.WithLabelValues("firstLabel").Inc()
    C.WithLabelValues("secondLabel").Inc()

    // CollectAndCount now collects 2 metrics from the collection C.
    assert.Equal(2, testutil.CollectAndCount(C))
    assert.Equal(float64(2), testutil.ToFloat64(C.WithLabelValues("firstLabel")))
    assert.Equal(float64(1), testutil.ToFloat64(C.WithLabelValues("secondLabel")))

    C.WithLabelValues("firstLabel").Inc()
    C.WithLabelValues("secondLabel").Inc()
    C.WithLabelValues("thirdLabel").Inc()

    assert.Equal(3, testutil.CollectAndCount(C))
    assert.Equal(float64(3), testutil.ToFloat64(C.WithLabelValues("firstLabel")))
    assert.Equal(float64(2), testutil.ToFloat64(C.WithLabelValues("secondLabel")))
    assert.Equal(float64(1), testutil.ToFloat64(C.WithLabelValues("thirdLabel")))
}