github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/clients/pkg/logentry/metric/gauges.go (about)

     1  package metric
     2  
     3  import (
     4  	"strings"
     5  	"time"
     6  
     7  	"github.com/mitchellh/mapstructure"
     8  	"github.com/pkg/errors"
     9  	"github.com/prometheus/client_golang/prometheus"
    10  	"github.com/prometheus/common/model"
    11  )
    12  
    13  const (
    14  	GaugeSet = "set"
    15  	GaugeInc = "inc"
    16  	GaugeDec = "dec"
    17  	GaugeAdd = "add"
    18  	GaugeSub = "sub"
    19  
    20  	ErrGaugeActionRequired = "gauge action must be defined as `set`, `inc`, `dec`, `add`, or `sub`"
    21  	ErrGaugeInvalidAction  = "action %s is not valid, action must be `set`, `inc`, `dec`, `add`, or `sub`"
    22  )
    23  
    24  type GaugeConfig struct {
    25  	Value  *string `mapstructure:"value"`
    26  	Action string  `mapstructure:"action"`
    27  }
    28  
    29  func validateGaugeConfig(config *GaugeConfig) error {
    30  	if config.Action == "" {
    31  		return errors.New(ErrGaugeActionRequired)
    32  	}
    33  	config.Action = strings.ToLower(config.Action)
    34  	if config.Action != GaugeSet &&
    35  		config.Action != GaugeInc &&
    36  		config.Action != GaugeDec &&
    37  		config.Action != GaugeAdd &&
    38  		config.Action != GaugeSub {
    39  		return errors.Errorf(ErrGaugeInvalidAction, config.Action)
    40  	}
    41  	return nil
    42  }
    43  
    44  func parseGaugeConfig(config interface{}) (*GaugeConfig, error) {
    45  	cfg := &GaugeConfig{}
    46  	err := mapstructure.Decode(config, cfg)
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  	return cfg, nil
    51  }
    52  
    53  // Gauges is a vector of gauges for a each log stream.
    54  type Gauges struct {
    55  	*metricVec
    56  	Cfg *GaugeConfig
    57  }
    58  
    59  // NewGauges creates a new gauge vec.
    60  func NewGauges(name, help string, config interface{}, maxIdleSec int64) (*Gauges, error) {
    61  	cfg, err := parseGaugeConfig(config)
    62  	if err != nil {
    63  		return nil, err
    64  	}
    65  	err = validateGaugeConfig(cfg)
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  	return &Gauges{
    70  		metricVec: newMetricVec(func(labels map[string]string) prometheus.Metric {
    71  			return &expiringGauge{prometheus.NewGauge(prometheus.GaugeOpts{
    72  				Help:        help,
    73  				Name:        name,
    74  				ConstLabels: labels,
    75  			}),
    76  				0,
    77  			}
    78  		}, maxIdleSec),
    79  		Cfg: cfg,
    80  	}, nil
    81  }
    82  
    83  // With returns the gauge associated with a stream labelset.
    84  func (g *Gauges) With(labels model.LabelSet) prometheus.Gauge {
    85  	return g.metricVec.With(labels).(prometheus.Gauge)
    86  }
    87  
    88  type expiringGauge struct {
    89  	prometheus.Gauge
    90  	lastModSec int64
    91  }
    92  
    93  // Set sets the Gauge to an arbitrary value.
    94  func (g *expiringGauge) Set(val float64) {
    95  	g.Gauge.Set(val)
    96  	g.lastModSec = time.Now().Unix()
    97  }
    98  
    99  // Inc increments the Gauge by 1. Use Add to increment it by arbitrary
   100  // values.
   101  func (g *expiringGauge) Inc() {
   102  	g.Gauge.Inc()
   103  	g.lastModSec = time.Now().Unix()
   104  }
   105  
   106  // Dec decrements the Gauge by 1. Use Sub to decrement it by arbitrary
   107  // values.
   108  func (g *expiringGauge) Dec() {
   109  	g.Gauge.Dec()
   110  	g.lastModSec = time.Now().Unix()
   111  }
   112  
   113  // Add adds the given value to the Gauge. (The value can be negative,
   114  // resulting in a decrease of the Gauge.)
   115  func (g *expiringGauge) Add(val float64) {
   116  	g.Gauge.Add(val)
   117  	g.lastModSec = time.Now().Unix()
   118  }
   119  
   120  // Sub subtracts the given value from the Gauge. (The value can be
   121  // negative, resulting in an increase of the Gauge.)
   122  func (g *expiringGauge) Sub(val float64) {
   123  	g.Gauge.Sub(val)
   124  	g.lastModSec = time.Now().Unix()
   125  }
   126  
   127  // SetToCurrentTime sets the Gauge to the current Unix time in seconds.
   128  func (g *expiringGauge) SetToCurrentTime() {
   129  	g.Gauge.SetToCurrentTime()
   130  	g.lastModSec = time.Now().Unix()
   131  }
   132  
   133  // HasExpired implements Expirable
   134  func (g *expiringGauge) HasExpired(currentTimeSec int64, maxAgeSec int64) bool {
   135  	return currentTimeSec-g.lastModSec >= maxAgeSec
   136  }