mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-12-26 20:30:10 +01:00
4e922eb93b
* vmalert: use group's ID in UI to avoid collisions Identical group names are allowed. So we should used IDs for various groupings and aggregations in UI. Signed-off-by: hagen1778 <roman@victoriametrics.com> * vmalert: prevent disabling state updates tracking The minimum number of update states to track is now set to 1. Signed-off-by: hagen1778 <roman@victoriametrics.com> * vmalert: properly update `debug` and `update_entries_limit` params on hot-reload Signed-off-by: hagen1778 <roman@victoriametrics.com> * vmalert: display `debug` field for rule in UI Signed-off-by: hagen1778 <roman@victoriametrics.com> * vmalert: exclude `updates` field from json marhsaling This field isn't correctly marshaled right now. And implementing the correct marshaling for it doesn't seem right, since json representation is mostly used by systems like Grafana. And Grafana doesn't expect this field to be present. Signed-off-by: hagen1778 <roman@victoriametrics.com> * fix test for disabled state Signed-off-by: hagen1778 <roman@victoriametrics.com> * fix test for disabled state Signed-off-by: hagen1778 <roman@victoriametrics.com> --------- Signed-off-by: hagen1778 <roman@victoriametrics.com>
113 lines
2.5 KiB
Go
113 lines
2.5 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal"
|
|
)
|
|
|
|
// Rule represents alerting or recording rule
|
|
// that has unique ID, can be Executed and
|
|
// updated with other Rule.
|
|
type Rule interface {
|
|
// ID returns unique ID that may be used for
|
|
// identifying this Rule among others.
|
|
ID() uint64
|
|
// Exec executes the rule with given context at the given timestamp and limit.
|
|
// returns an err if number of resulting time series exceeds the limit.
|
|
Exec(ctx context.Context, ts time.Time, limit int) ([]prompbmarshal.TimeSeries, error)
|
|
// ExecRange executes the rule on the given time range.
|
|
ExecRange(ctx context.Context, start, end time.Time) ([]prompbmarshal.TimeSeries, error)
|
|
// UpdateWith performs modification of current Rule
|
|
// with fields of the given Rule.
|
|
UpdateWith(Rule) error
|
|
// ToAPI converts Rule into APIRule
|
|
ToAPI() APIRule
|
|
// Close performs the shutdown procedures for rule
|
|
// such as metrics unregister
|
|
Close()
|
|
}
|
|
|
|
var errDuplicate = errors.New("result contains metrics with the same labelset after applying rule labels")
|
|
|
|
type ruleState struct {
|
|
sync.RWMutex
|
|
entries []ruleStateEntry
|
|
cur int
|
|
}
|
|
|
|
type ruleStateEntry struct {
|
|
// stores last moment of time rule.Exec was called
|
|
time time.Time
|
|
// stores the timesteamp with which rule.Exec was called
|
|
at time.Time
|
|
// stores the duration of the last rule.Exec call
|
|
duration time.Duration
|
|
// stores last error that happened in Exec func
|
|
// resets on every successful Exec
|
|
// may be used as Health ruleState
|
|
err error
|
|
// stores the number of samples returned during
|
|
// the last evaluation
|
|
samples int
|
|
// stores the curl command reflecting the HTTP request used during rule.Exec
|
|
curl string
|
|
}
|
|
|
|
func newRuleState(size int) *ruleState {
|
|
if size < 1 {
|
|
size = 1
|
|
}
|
|
return &ruleState{
|
|
entries: make([]ruleStateEntry, size),
|
|
}
|
|
}
|
|
|
|
func (s *ruleState) getLast() ruleStateEntry {
|
|
s.RLock()
|
|
defer s.RUnlock()
|
|
return s.entries[s.cur]
|
|
}
|
|
|
|
func (s *ruleState) size() int {
|
|
s.RLock()
|
|
defer s.RUnlock()
|
|
return len(s.entries)
|
|
}
|
|
|
|
func (s *ruleState) getAll() []ruleStateEntry {
|
|
entries := make([]ruleStateEntry, 0)
|
|
|
|
s.RLock()
|
|
defer s.RUnlock()
|
|
|
|
cur := s.cur
|
|
for {
|
|
e := s.entries[cur]
|
|
if !e.time.IsZero() || !e.at.IsZero() {
|
|
entries = append(entries, e)
|
|
}
|
|
cur--
|
|
if cur < 0 {
|
|
cur = cap(s.entries) - 1
|
|
}
|
|
if cur == s.cur {
|
|
return entries
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *ruleState) add(e ruleStateEntry) {
|
|
s.Lock()
|
|
defer s.Unlock()
|
|
|
|
s.cur++
|
|
if s.cur > cap(s.entries)-1 {
|
|
s.cur = 0
|
|
}
|
|
s.entries[s.cur] = e
|
|
}
|