initial import
This commit is contained in:
55
core/metric/counter.go
Normal file
55
core/metric/counter.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package metric
|
||||
|
||||
import (
|
||||
"zero/core/proc"
|
||||
|
||||
prom "github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
type (
|
||||
CounterVecOpts VectorOpts
|
||||
|
||||
CounterVec interface {
|
||||
Inc(lables ...string)
|
||||
Add(v float64, labels ...string)
|
||||
close() bool
|
||||
}
|
||||
|
||||
promCounterVec struct {
|
||||
counter *prom.CounterVec
|
||||
}
|
||||
)
|
||||
|
||||
func NewCounterVec(cfg *CounterVecOpts) CounterVec {
|
||||
if cfg == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
vec := prom.NewCounterVec(prom.CounterOpts{
|
||||
Namespace: cfg.Namespace,
|
||||
Subsystem: cfg.Subsystem,
|
||||
Name: cfg.Name,
|
||||
Help: cfg.Help,
|
||||
}, cfg.Labels)
|
||||
prom.MustRegister(vec)
|
||||
cv := &promCounterVec{
|
||||
counter: vec,
|
||||
}
|
||||
proc.AddShutdownListener(func() {
|
||||
cv.close()
|
||||
})
|
||||
|
||||
return cv
|
||||
}
|
||||
|
||||
func (cv *promCounterVec) Inc(labels ...string) {
|
||||
cv.counter.WithLabelValues(labels...).Inc()
|
||||
}
|
||||
|
||||
func (cv *promCounterVec) Add(v float64, lables ...string) {
|
||||
cv.counter.WithLabelValues(lables...).Add(v)
|
||||
}
|
||||
|
||||
func (cv *promCounterVec) close() bool {
|
||||
return prom.Unregister(cv.counter)
|
||||
}
|
||||
53
core/metric/counter_test.go
Normal file
53
core/metric/counter_test.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package metric
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNewCounterVec(t *testing.T) {
|
||||
counterVec := NewCounterVec(&CounterVecOpts{
|
||||
Namespace: "http_server",
|
||||
Subsystem: "requests",
|
||||
Name: "total",
|
||||
Help: "rpc client requests error count.",
|
||||
})
|
||||
defer counterVec.close()
|
||||
counterVecNil := NewCounterVec(nil)
|
||||
assert.NotNil(t, counterVec)
|
||||
assert.Nil(t, counterVecNil)
|
||||
}
|
||||
|
||||
func TestCounterIncr(t *testing.T) {
|
||||
counterVec := NewCounterVec(&CounterVecOpts{
|
||||
Namespace: "http_client",
|
||||
Subsystem: "call",
|
||||
Name: "code_total",
|
||||
Help: "http client requests error count.",
|
||||
Labels: []string{"path", "code"},
|
||||
})
|
||||
defer counterVec.close()
|
||||
cv, _ := counterVec.(*promCounterVec)
|
||||
cv.Inc("/Users", "500")
|
||||
cv.Inc("/Users", "500")
|
||||
r := testutil.ToFloat64(cv.counter)
|
||||
assert.Equal(t, float64(2), r)
|
||||
}
|
||||
|
||||
func TestCounterAdd(t *testing.T) {
|
||||
counterVec := NewCounterVec(&CounterVecOpts{
|
||||
Namespace: "rpc_server",
|
||||
Subsystem: "requests",
|
||||
Name: "err_total",
|
||||
Help: "rpc client requests error count.",
|
||||
Labels: []string{"method", "code"},
|
||||
})
|
||||
defer counterVec.close()
|
||||
cv, _ := counterVec.(*promCounterVec)
|
||||
cv.Add(11, "/Users", "500")
|
||||
cv.Add(22, "/Users", "500")
|
||||
r := testutil.ToFloat64(cv.counter)
|
||||
assert.Equal(t, float64(33), r)
|
||||
}
|
||||
61
core/metric/gauge.go
Normal file
61
core/metric/gauge.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package metric
|
||||
|
||||
import (
|
||||
"zero/core/proc"
|
||||
|
||||
prom "github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
type (
|
||||
GaugeVecOpts VectorOpts
|
||||
|
||||
GuageVec interface {
|
||||
Set(v float64, labels ...string)
|
||||
Inc(labels ...string)
|
||||
Add(v float64, labels ...string)
|
||||
close() bool
|
||||
}
|
||||
|
||||
promGuageVec struct {
|
||||
gauge *prom.GaugeVec
|
||||
}
|
||||
)
|
||||
|
||||
func NewGaugeVec(cfg *GaugeVecOpts) GuageVec {
|
||||
if cfg == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
vec := prom.NewGaugeVec(
|
||||
prom.GaugeOpts{
|
||||
Namespace: cfg.Namespace,
|
||||
Subsystem: cfg.Subsystem,
|
||||
Name: cfg.Name,
|
||||
Help: cfg.Help,
|
||||
}, cfg.Labels)
|
||||
prom.MustRegister(vec)
|
||||
gv := &promGuageVec{
|
||||
gauge: vec,
|
||||
}
|
||||
proc.AddShutdownListener(func() {
|
||||
gv.close()
|
||||
})
|
||||
|
||||
return gv
|
||||
}
|
||||
|
||||
func (gv *promGuageVec) Inc(labels ...string) {
|
||||
gv.gauge.WithLabelValues(labels...).Inc()
|
||||
}
|
||||
|
||||
func (gv *promGuageVec) Add(v float64, lables ...string) {
|
||||
gv.gauge.WithLabelValues(lables...).Add(v)
|
||||
}
|
||||
|
||||
func (gv *promGuageVec) Set(v float64, lables ...string) {
|
||||
gv.gauge.WithLabelValues(lables...).Set(v)
|
||||
}
|
||||
|
||||
func (gv *promGuageVec) close() bool {
|
||||
return prom.Unregister(gv.gauge)
|
||||
}
|
||||
68
core/metric/gauge_test.go
Normal file
68
core/metric/gauge_test.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package metric
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNewGaugeVec(t *testing.T) {
|
||||
gaugeVec := NewGaugeVec(&GaugeVecOpts{
|
||||
Namespace: "rpc_server",
|
||||
Subsystem: "requests",
|
||||
Name: "duration",
|
||||
Help: "rpc server requests duration(ms).",
|
||||
})
|
||||
defer gaugeVec.close()
|
||||
gaugeVecNil := NewGaugeVec(nil)
|
||||
assert.NotNil(t, gaugeVec)
|
||||
assert.Nil(t, gaugeVecNil)
|
||||
}
|
||||
|
||||
func TestGaugeInc(t *testing.T) {
|
||||
gaugeVec := NewGaugeVec(&GaugeVecOpts{
|
||||
Namespace: "rpc_client2",
|
||||
Subsystem: "requests",
|
||||
Name: "duration_ms",
|
||||
Help: "rpc server requests duration(ms).",
|
||||
Labels: []string{"path"},
|
||||
})
|
||||
defer gaugeVec.close()
|
||||
gv, _ := gaugeVec.(*promGuageVec)
|
||||
gv.Inc("/users")
|
||||
gv.Inc("/users")
|
||||
r := testutil.ToFloat64(gv.gauge)
|
||||
assert.Equal(t, float64(2), r)
|
||||
}
|
||||
|
||||
func TestGaugeAdd(t *testing.T) {
|
||||
gaugeVec := NewGaugeVec(&GaugeVecOpts{
|
||||
Namespace: "rpc_client",
|
||||
Subsystem: "request",
|
||||
Name: "duration_ms",
|
||||
Help: "rpc server requests duration(ms).",
|
||||
Labels: []string{"path"},
|
||||
})
|
||||
defer gaugeVec.close()
|
||||
gv, _ := gaugeVec.(*promGuageVec)
|
||||
gv.Add(-10, "/classroom")
|
||||
gv.Add(30, "/classroom")
|
||||
r := testutil.ToFloat64(gv.gauge)
|
||||
assert.Equal(t, float64(20), r)
|
||||
}
|
||||
|
||||
func TestGaugeSet(t *testing.T) {
|
||||
gaugeVec := NewGaugeVec(&GaugeVecOpts{
|
||||
Namespace: "http_client",
|
||||
Subsystem: "request",
|
||||
Name: "duration_ms",
|
||||
Help: "rpc server requests duration(ms).",
|
||||
Labels: []string{"path"},
|
||||
})
|
||||
gaugeVec.close()
|
||||
gv, _ := gaugeVec.(*promGuageVec)
|
||||
gv.Set(666, "/users")
|
||||
r := testutil.ToFloat64(gv.gauge)
|
||||
assert.Equal(t, float64(666), r)
|
||||
}
|
||||
58
core/metric/histogram.go
Normal file
58
core/metric/histogram.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package metric
|
||||
|
||||
import (
|
||||
"zero/core/proc"
|
||||
|
||||
prom "github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
type (
|
||||
HistogramVecOpts struct {
|
||||
Namespace string
|
||||
Subsystem string
|
||||
Name string
|
||||
Help string
|
||||
Labels []string
|
||||
Buckets []float64
|
||||
}
|
||||
|
||||
HistogramVec interface {
|
||||
Observe(v int64, lables ...string)
|
||||
close() bool
|
||||
}
|
||||
|
||||
promHistogramVec struct {
|
||||
histogram *prom.HistogramVec
|
||||
}
|
||||
)
|
||||
|
||||
func NewHistogramVec(cfg *HistogramVecOpts) HistogramVec {
|
||||
if cfg == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
vec := prom.NewHistogramVec(prom.HistogramOpts{
|
||||
Namespace: cfg.Namespace,
|
||||
Subsystem: cfg.Subsystem,
|
||||
Name: cfg.Name,
|
||||
Help: cfg.Help,
|
||||
Buckets: cfg.Buckets,
|
||||
}, cfg.Labels)
|
||||
prom.MustRegister(vec)
|
||||
hv := &promHistogramVec{
|
||||
histogram: vec,
|
||||
}
|
||||
proc.AddShutdownListener(func() {
|
||||
hv.close()
|
||||
})
|
||||
|
||||
return hv
|
||||
}
|
||||
|
||||
func (hv *promHistogramVec) Observe(v int64, labels ...string) {
|
||||
hv.histogram.WithLabelValues(labels...).Observe(float64(v))
|
||||
}
|
||||
|
||||
func (hv *promHistogramVec) close() bool {
|
||||
return prom.Unregister(hv.histogram)
|
||||
}
|
||||
49
core/metric/histogram_test.go
Normal file
49
core/metric/histogram_test.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package metric
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNewHistogramVec(t *testing.T) {
|
||||
histogramVec := NewHistogramVec(&HistogramVecOpts{
|
||||
Name: "duration_ms",
|
||||
Help: "rpc server requests duration(ms).",
|
||||
Buckets: []float64{1, 2, 3},
|
||||
})
|
||||
defer histogramVec.close()
|
||||
histogramVecNil := NewHistogramVec(nil)
|
||||
assert.NotNil(t, histogramVec)
|
||||
assert.Nil(t, histogramVecNil)
|
||||
}
|
||||
|
||||
func TestHistogramObserve(t *testing.T) {
|
||||
histogramVec := NewHistogramVec(&HistogramVecOpts{
|
||||
Name: "counts",
|
||||
Help: "rpc server requests duration(ms).",
|
||||
Buckets: []float64{1, 2, 3},
|
||||
Labels: []string{"method"},
|
||||
})
|
||||
defer histogramVec.close()
|
||||
hv, _ := histogramVec.(*promHistogramVec)
|
||||
hv.Observe(2, "/Users")
|
||||
|
||||
metadata := `
|
||||
# HELP counts rpc server requests duration(ms).
|
||||
# TYPE counts histogram
|
||||
`
|
||||
val := `
|
||||
counts_bucket{method="/Users",le="1"} 0
|
||||
counts_bucket{method="/Users",le="2"} 1
|
||||
counts_bucket{method="/Users",le="3"} 1
|
||||
counts_bucket{method="/Users",le="+Inf"} 1
|
||||
counts_sum{method="/Users"} 2
|
||||
counts_count{method="/Users"} 1
|
||||
`
|
||||
|
||||
err := testutil.CollectAndCompare(hv.histogram, strings.NewReader(metadata+val))
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
10
core/metric/metric.go
Normal file
10
core/metric/metric.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package metric
|
||||
|
||||
// VectorOpts general configuration
|
||||
type VectorOpts struct {
|
||||
Namespace string
|
||||
Subsystem string
|
||||
Name string
|
||||
Help string
|
||||
Labels []string
|
||||
}
|
||||
Reference in New Issue
Block a user