metrics: add label type in metrics package
This commit is contained in:
parent
d87d697d92
commit
d77ebb8511
@ -95,6 +95,20 @@ func (exp *exp) getFloat(name string) *expvar.Float {
|
||||
return v
|
||||
}
|
||||
|
||||
func (exp *exp) getMap(name string) *expvar.Map {
|
||||
var v *expvar.Map
|
||||
exp.expvarLock.Lock()
|
||||
p := expvar.Get(name)
|
||||
if p != nil {
|
||||
v = p.(*expvar.Map)
|
||||
} else {
|
||||
v = new(expvar.Map)
|
||||
expvar.Publish(name, v)
|
||||
}
|
||||
exp.expvarLock.Unlock()
|
||||
return v
|
||||
}
|
||||
|
||||
func (exp *exp) publishCounter(name string, metric metrics.Counter) {
|
||||
v := exp.getInt(name)
|
||||
v.Set(metric.Count())
|
||||
@ -162,6 +176,60 @@ func (exp *exp) publishResettingTimer(name string, metric metrics.ResettingTimer
|
||||
exp.getInt(name + ".99-percentile").Set(ps[3])
|
||||
}
|
||||
|
||||
func (exp *exp) publishLabel(name string, metric metrics.Label) {
|
||||
labels := metric.Value()
|
||||
for k, v := range labels {
|
||||
exp.getMap(name).Set(k, exp.interfaceToExpVal(v))
|
||||
}
|
||||
}
|
||||
|
||||
func (exp *exp) interfaceToExpVal(v interface{}) expvar.Var {
|
||||
switch i := v.(type) {
|
||||
case string:
|
||||
newV := new(expvar.String)
|
||||
newV.Set(i)
|
||||
return newV
|
||||
case int64:
|
||||
newV := new(expvar.Int)
|
||||
newV.Set(i)
|
||||
return newV
|
||||
case int32:
|
||||
newV := new(expvar.Int)
|
||||
newV.Set(int64(i))
|
||||
return newV
|
||||
case int16:
|
||||
newV := new(expvar.Int)
|
||||
newV.Set(int64(i))
|
||||
return newV
|
||||
case int8:
|
||||
newV := new(expvar.Int)
|
||||
newV.Set(int64(i))
|
||||
return newV
|
||||
case int:
|
||||
newV := new(expvar.Int)
|
||||
newV.Set(int64(i))
|
||||
return newV
|
||||
case float32:
|
||||
newV := new(expvar.Float)
|
||||
newV.Set(float64(i))
|
||||
return newV
|
||||
case float64:
|
||||
newV := new(expvar.Float)
|
||||
newV.Set(i)
|
||||
return newV
|
||||
case map[string]interface{}:
|
||||
newV := new(expvar.Map)
|
||||
for k, v := range i {
|
||||
newV.Set(k, exp.interfaceToExpVal(v))
|
||||
}
|
||||
return newV
|
||||
default:
|
||||
newV := new(expvar.String)
|
||||
newV.Set(fmt.Sprint(v))
|
||||
return newV
|
||||
}
|
||||
}
|
||||
|
||||
func (exp *exp) syncToExpvar() {
|
||||
exp.registry.Each(func(name string, i interface{}) {
|
||||
switch i := i.(type) {
|
||||
@ -179,6 +247,8 @@ func (exp *exp) syncToExpvar() {
|
||||
exp.publishTimer(name, i)
|
||||
case metrics.ResettingTimer:
|
||||
exp.publishResettingTimer(name, i)
|
||||
case metrics.Label:
|
||||
exp.publishLabel(name, i)
|
||||
default:
|
||||
panic(fmt.Sprintf("unsupported type for '%s': %T", name, i))
|
||||
}
|
||||
|
48
metrics/label.go
Normal file
48
metrics/label.go
Normal file
@ -0,0 +1,48 @@
|
||||
package metrics
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
// Label hold an map[string]interface{} value that can be set arbitrarily.
|
||||
type Label interface {
|
||||
Value() map[string]interface{}
|
||||
String() string
|
||||
Mark(map[string]interface{})
|
||||
}
|
||||
|
||||
// NewRegisteredLabel constructs and registers a new StandardLabel.
|
||||
func NewRegisteredLabel(name string, r Registry) Label {
|
||||
c := NewStandardLabel()
|
||||
if nil == r {
|
||||
r = DefaultRegistry
|
||||
}
|
||||
r.Register(name, c)
|
||||
return c
|
||||
}
|
||||
|
||||
// NewStandardLabel constructs a new StandardLabel.
|
||||
func NewStandardLabel() *StandardLabel {
|
||||
return &StandardLabel{}
|
||||
}
|
||||
|
||||
// StandardLabel is the standard implementation of a Label.
|
||||
type StandardLabel struct {
|
||||
value map[string]interface{}
|
||||
jsonStr string
|
||||
}
|
||||
|
||||
// Value returns label values.
|
||||
func (l *StandardLabel) Value() map[string]interface{} {
|
||||
return l.value
|
||||
}
|
||||
|
||||
// Mark records the label.
|
||||
func (l *StandardLabel) Mark(value map[string]interface{}) {
|
||||
buf, _ := json.Marshal(value)
|
||||
l.jsonStr = string(buf)
|
||||
l.value = value
|
||||
}
|
||||
|
||||
// String returns label by JSON format.
|
||||
func (l *StandardLabel) String() string {
|
||||
return l.jsonStr
|
||||
}
|
@ -31,6 +31,7 @@ var (
|
||||
typeSummaryTpl = "# TYPE %s summary\n"
|
||||
keyValueTpl = "%s %v\n\n"
|
||||
keyQuantileTagValueTpl = "%s {quantile=\"%s\"} %v\n"
|
||||
keyLabelValueTpl = "%s%s %v\n\n"
|
||||
)
|
||||
|
||||
// collector is a collection of byte buffers that aggregate Prometheus reports
|
||||
@ -98,6 +99,15 @@ func (c *collector) addResettingTimer(name string, m metrics.ResettingTimer) {
|
||||
c.buff.WriteRune('\n')
|
||||
}
|
||||
|
||||
func (c *collector) addLabel(name string, m metrics.Label) {
|
||||
c.writeLabel(mutateKey(name), m.String())
|
||||
}
|
||||
|
||||
func (c *collector) writeLabel(name string, value interface{}) {
|
||||
c.buff.WriteString(fmt.Sprintf(typeGaugeTpl, name))
|
||||
c.buff.WriteString(fmt.Sprintf(keyLabelValueTpl, name, value, 1))
|
||||
}
|
||||
|
||||
func (c *collector) writeGaugeCounter(name string, value interface{}) {
|
||||
name = mutateKey(name)
|
||||
c.buff.WriteString(fmt.Sprintf(typeGaugeTpl, name))
|
||||
|
@ -57,6 +57,8 @@ func Handler(reg metrics.Registry) http.Handler {
|
||||
c.addTimer(name, m.Snapshot())
|
||||
case metrics.ResettingTimer:
|
||||
c.addResettingTimer(name, m.Snapshot())
|
||||
case metrics.Label:
|
||||
c.addLabel(name, m)
|
||||
default:
|
||||
log.Warn("Unknown Prometheus metric type", "type", fmt.Sprintf("%T", i))
|
||||
}
|
||||
|
@ -196,7 +196,7 @@ func (r *StandardRegistry) register(name string, i interface{}) error {
|
||||
return DuplicateMetric(name)
|
||||
}
|
||||
switch i.(type) {
|
||||
case Counter, Gauge, GaugeFloat64, Healthcheck, Histogram, Meter, Timer, ResettingTimer:
|
||||
case Counter, Gauge, GaugeFloat64, Healthcheck, Histogram, Meter, Timer, ResettingTimer, Label:
|
||||
r.metrics[name] = i
|
||||
}
|
||||
return nil
|
||||
|
Loading…
Reference in New Issue
Block a user