Added GetOrCreateGauge to be consistent with Counter and Summary
This commit is contained in:
parent
d8d17da673
commit
6cd90960e1
51
gauge.go
51
gauge.go
@ -19,6 +19,9 @@ import (
|
||||
//
|
||||
// The returned gauge is safe to use from concurrent goroutines.
|
||||
func NewGauge(name string, f func() float64) *Gauge {
|
||||
if f == nil {
|
||||
panic(fmt.Errorf("BUG: f cannot be nil"))
|
||||
}
|
||||
g := &Gauge{
|
||||
f: f,
|
||||
}
|
||||
@ -47,3 +50,51 @@ func (g *Gauge) marshalTo(prefix string, w io.Writer) {
|
||||
fmt.Fprintf(w, "%s %g\n", prefix, v)
|
||||
}
|
||||
}
|
||||
|
||||
// GetOrCreateGauge returns registered gauge with the given name
|
||||
// or creates new gauge if the registry doesn't contain gauge with
|
||||
// the given name.
|
||||
//
|
||||
// name must be valid Prometheus-compatible metric with possible lables.
|
||||
// For instance,
|
||||
//
|
||||
// * foo
|
||||
// * foo{bar="baz"}
|
||||
// * foo{bar="baz",aaa="b"}
|
||||
//
|
||||
// The returned gauge is safe to use from concurrent goroutines.
|
||||
//
|
||||
// Performance tip: prefer NewGauge instead of GetOrCreateGauge.
|
||||
func GetOrCreateGauge(name string, f func() float64) *Gauge {
|
||||
metricsMapLock.Lock()
|
||||
nm := metricsMap[name]
|
||||
metricsMapLock.Unlock()
|
||||
if nm == nil {
|
||||
// Slow path - create and register missing gauge.
|
||||
if f == nil {
|
||||
panic(fmt.Errorf("BUG: f cannot be nil"))
|
||||
}
|
||||
if err := validateMetric(name); err != nil {
|
||||
panic(fmt.Errorf("BUG: invalid metric name %q: %s", name, err))
|
||||
}
|
||||
nmNew := &namedMetric{
|
||||
name: name,
|
||||
metric: &Gauge{
|
||||
f: f,
|
||||
},
|
||||
}
|
||||
metricsMapLock.Lock()
|
||||
nm = metricsMap[name]
|
||||
if nm == nil {
|
||||
nm = nmNew
|
||||
metricsMap[name] = nm
|
||||
metricsList = append(metricsList, nm)
|
||||
}
|
||||
metricsMapLock.Unlock()
|
||||
}
|
||||
g, ok := nm.metric.(*Gauge)
|
||||
if !ok {
|
||||
panic(fmt.Errorf("BUG: metric %q isn't a Gauge. It is %T", name, nm.metric))
|
||||
}
|
||||
return g
|
||||
}
|
||||
|
@ -16,3 +16,26 @@ func ExampleGauge() {
|
||||
// Obtain gauge value.
|
||||
fmt.Println(g.Get())
|
||||
}
|
||||
|
||||
func ExampleGauge_vec() {
|
||||
for i := 0; i < 3; i++ {
|
||||
// Dynamically construct metric name and pass it to GetOrCreateGauge.
|
||||
name := fmt.Sprintf(`metric{label1=%q, label2="%d"}`, "value1", i)
|
||||
iLocal := i
|
||||
metrics.GetOrCreateGauge(name, func() float64 {
|
||||
return float64(iLocal + 1)
|
||||
})
|
||||
}
|
||||
|
||||
// Read counter values.
|
||||
for i := 0; i < 3; i++ {
|
||||
name := fmt.Sprintf(`metric{label1=%q, label2="%d"}`, "value1", i)
|
||||
n := metrics.GetOrCreateGauge(name, func() float64 { return 0 }).Get()
|
||||
fmt.Println(n)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// 2
|
||||
// 3
|
||||
}
|
||||
|
@ -6,6 +6,15 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGaugeError(t *testing.T) {
|
||||
expectPanic(t, "NewGauge_nil_callback", func() {
|
||||
NewGauge("NewGauge_nil_callback", nil)
|
||||
})
|
||||
expectPanic(t, "GetOrCreateGauge_nil_callback", func() {
|
||||
GetOrCreateGauge("GetOrCreateGauge_nil_callback", nil)
|
||||
})
|
||||
}
|
||||
|
||||
func TestGaugeSerial(t *testing.T) {
|
||||
name := "GaugeSerial"
|
||||
n := 1.23
|
||||
|
@ -14,6 +14,7 @@ func TestInvalidName(t *testing.T) {
|
||||
expectPanic(t, fmt.Sprintf("NewGauge(%q)", name), func() { NewGauge(name, func() float64 { return 0 }) })
|
||||
expectPanic(t, fmt.Sprintf("NewSummary(%q)", name), func() { NewSummary(name) })
|
||||
expectPanic(t, fmt.Sprintf("GetOrCreateCounter(%q)", name), func() { GetOrCreateCounter(name) })
|
||||
expectPanic(t, fmt.Sprintf("GetOrCreateGauge(%q)", name), func() { GetOrCreateGauge(name, func() float64 { return 0 }) })
|
||||
expectPanic(t, fmt.Sprintf("GetOrCreateSummary(%q)", name), func() { GetOrCreateSummary(name) })
|
||||
}
|
||||
f("")
|
||||
@ -52,6 +53,12 @@ func TestGetOrCreateNotCounter(t *testing.T) {
|
||||
expectPanic(t, name, func() { GetOrCreateCounter(name) })
|
||||
}
|
||||
|
||||
func TestGetOrCreateNotGauge(t *testing.T) {
|
||||
name := "GetOrCreateNotGauge"
|
||||
NewCounter(name)
|
||||
expectPanic(t, name, func() { GetOrCreateGauge(name, func() float64 { return 0 }) })
|
||||
}
|
||||
|
||||
func TestGetOrCreateNotSummary(t *testing.T) {
|
||||
name := "GetOrCreateNotSummary"
|
||||
NewCounter(name)
|
||||
|
Loading…
Reference in New Issue
Block a user