137 lines
3.3 KiB
Go
137 lines
3.3 KiB
Go
package metric
|
|
|
|
import (
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/mitchellh/mapstructure"
|
|
"github.com/pkg/errors"
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
"github.com/prometheus/common/model"
|
|
)
|
|
|
|
const (
|
|
GaugeSet = "set"
|
|
GaugeInc = "inc"
|
|
GaugeDec = "dec"
|
|
GaugeAdd = "add"
|
|
GaugeSub = "sub"
|
|
|
|
ErrGaugeActionRequired = "gauge action must be defined as `set`, `inc`, `dec`, `add`, or `sub`"
|
|
ErrGaugeInvalidAction = "action %s is not valid, action must be `set`, `inc`, `dec`, `add`, or `sub`"
|
|
)
|
|
|
|
type GaugeConfig struct {
|
|
Value *string `mapstructure:"value"`
|
|
Action string `mapstructure:"action"`
|
|
}
|
|
|
|
func validateGaugeConfig(config *GaugeConfig) error {
|
|
if config.Action == "" {
|
|
return errors.New(ErrGaugeActionRequired)
|
|
}
|
|
config.Action = strings.ToLower(config.Action)
|
|
if config.Action != GaugeSet &&
|
|
config.Action != GaugeInc &&
|
|
config.Action != GaugeDec &&
|
|
config.Action != GaugeAdd &&
|
|
config.Action != GaugeSub {
|
|
return errors.Errorf(ErrGaugeInvalidAction, config.Action)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func parseGaugeConfig(config interface{}) (*GaugeConfig, error) {
|
|
cfg := &GaugeConfig{}
|
|
err := mapstructure.Decode(config, cfg)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return cfg, nil
|
|
}
|
|
|
|
// Gauges is a vector of gauges for a each log stream.
|
|
type Gauges struct {
|
|
*metricVec
|
|
Cfg *GaugeConfig
|
|
}
|
|
|
|
// NewGauges creates a new gauge vec.
|
|
func NewGauges(name, help string, config interface{}, maxIdleSec int64) (*Gauges, error) {
|
|
cfg, err := parseGaugeConfig(config)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = validateGaugeConfig(cfg)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &Gauges{
|
|
metricVec: newMetricVec(func(labels map[string]string) prometheus.Metric {
|
|
return &expiringGauge{prometheus.NewGauge(prometheus.GaugeOpts{
|
|
Help: help,
|
|
Name: name,
|
|
ConstLabels: labels,
|
|
}),
|
|
0,
|
|
}
|
|
}, maxIdleSec),
|
|
Cfg: cfg,
|
|
}, nil
|
|
}
|
|
|
|
// With returns the gauge associated with a stream labelset.
|
|
func (g *Gauges) With(labels model.LabelSet) prometheus.Gauge {
|
|
return g.metricVec.With(labels).(prometheus.Gauge)
|
|
}
|
|
|
|
type expiringGauge struct {
|
|
prometheus.Gauge
|
|
lastModSec int64
|
|
}
|
|
|
|
// Set sets the Gauge to an arbitrary value.
|
|
func (g *expiringGauge) Set(val float64) {
|
|
g.Gauge.Set(val)
|
|
g.lastModSec = time.Now().Unix()
|
|
}
|
|
|
|
// Inc increments the Gauge by 1. Use Add to increment it by arbitrary
|
|
// values.
|
|
func (g *expiringGauge) Inc() {
|
|
g.Gauge.Inc()
|
|
g.lastModSec = time.Now().Unix()
|
|
}
|
|
|
|
// Dec decrements the Gauge by 1. Use Sub to decrement it by arbitrary
|
|
// values.
|
|
func (g *expiringGauge) Dec() {
|
|
g.Gauge.Dec()
|
|
g.lastModSec = time.Now().Unix()
|
|
}
|
|
|
|
// Add adds the given value to the Gauge. (The value can be negative,
|
|
// resulting in a decrease of the Gauge.)
|
|
func (g *expiringGauge) Add(val float64) {
|
|
g.Gauge.Add(val)
|
|
g.lastModSec = time.Now().Unix()
|
|
}
|
|
|
|
// Sub subtracts the given value from the Gauge. (The value can be
|
|
// negative, resulting in an increase of the Gauge.)
|
|
func (g *expiringGauge) Sub(val float64) {
|
|
g.Gauge.Sub(val)
|
|
g.lastModSec = time.Now().Unix()
|
|
}
|
|
|
|
// SetToCurrentTime sets the Gauge to the current Unix time in seconds.
|
|
func (g *expiringGauge) SetToCurrentTime() {
|
|
g.Gauge.SetToCurrentTime()
|
|
g.lastModSec = time.Now().Unix()
|
|
}
|
|
|
|
// HasExpired implements Expirable
|
|
func (g *expiringGauge) HasExpired(currentTimeSec int64, maxAgeSec int64) bool {
|
|
return currentTimeSec-g.lastModSec >= maxAgeSec
|
|
}
|