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.
|
// The returned gauge is safe to use from concurrent goroutines.
|
||||||
func NewGauge(name string, f func() float64) *Gauge {
|
func NewGauge(name string, f func() float64) *Gauge {
|
||||||
|
if f == nil {
|
||||||
|
panic(fmt.Errorf("BUG: f cannot be nil"))
|
||||||
|
}
|
||||||
g := &Gauge{
|
g := &Gauge{
|
||||||
f: f,
|
f: f,
|
||||||
}
|
}
|
||||||
@ -47,3 +50,51 @@ func (g *Gauge) marshalTo(prefix string, w io.Writer) {
|
|||||||
fmt.Fprintf(w, "%s %g\n", prefix, v)
|
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.
|
// Obtain gauge value.
|
||||||
fmt.Println(g.Get())
|
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"
|
"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) {
|
func TestGaugeSerial(t *testing.T) {
|
||||||
name := "GaugeSerial"
|
name := "GaugeSerial"
|
||||||
n := 1.23
|
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("NewGauge(%q)", name), func() { NewGauge(name, func() float64 { return 0 }) })
|
||||||
expectPanic(t, fmt.Sprintf("NewSummary(%q)", name), func() { NewSummary(name) })
|
expectPanic(t, fmt.Sprintf("NewSummary(%q)", name), func() { NewSummary(name) })
|
||||||
expectPanic(t, fmt.Sprintf("GetOrCreateCounter(%q)", name), func() { GetOrCreateCounter(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) })
|
expectPanic(t, fmt.Sprintf("GetOrCreateSummary(%q)", name), func() { GetOrCreateSummary(name) })
|
||||||
}
|
}
|
||||||
f("")
|
f("")
|
||||||
@ -52,6 +53,12 @@ func TestGetOrCreateNotCounter(t *testing.T) {
|
|||||||
expectPanic(t, name, func() { GetOrCreateCounter(name) })
|
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) {
|
func TestGetOrCreateNotSummary(t *testing.T) {
|
||||||
name := "GetOrCreateNotSummary"
|
name := "GetOrCreateNotSummary"
|
||||||
NewCounter(name)
|
NewCounter(name)
|
||||||
|
Loading…
Reference in New Issue
Block a user