diff --git a/app/vmalert/README.md b/app/vmalert/README.md index 544576d97..71e0f15df 100644 --- a/app/vmalert/README.md +++ b/app/vmalert/README.md @@ -813,16 +813,17 @@ external_labels: series: # values support several special equations: -# 'a+bxc' becomes 'a a+b a+(2*b) a+(3*b) … a+(c*b)' +# 'a+bxc' becomes 'a a+b a+(2*b) a+(3*b) … a+(c*b)' # Read this as series starts at a, then c further samples incrementing by b. -# 'a-bxc' becomes 'a a-b a-(2*b) a-(3*b) … a-(c*b)' +# 'a-bxc' becomes 'a a-b a-(2*b) a-(3*b) … a-(c*b)' # Read this as series starts at a, then c further samples decrementing by b (or incrementing by negative b). # '_' represents a missing sample from scrape +# 'stale' indicates a stale sample # Examples: # 1. '-2+4x3' becomes '-2 2 6 10' - series starts at -2, then 3 further samples incrementing by 4. # 2. ' 1-2x4' becomes '1 -1 -3 -5 -7' - series starts at 1, then 4 further samples decrementing by 2. # 3. ' 1x4' becomes '1 1 1 1 1' - shorthand for '1+0x4', series starts at 1, then 4 further samples incrementing by 0. -# 4. ' 1 _x3' becomes '1 _ _ _ ' - the missing sample cannot increment, so 3 missing samples are produced by the '_x3' expression. +# 4. ' 1 _x3 stale' becomes '1 _ _ _ stale' - the missing sample cannot increment, so 3 missing samples are produced by the '_x3' expression. values: ``` diff --git a/app/vmalert/unittest/input.go b/app/vmalert/unittest/input.go index 6ba19bab3..58dd3edab 100644 --- a/app/vmalert/unittest/input.go +++ b/app/vmalert/unittest/input.go @@ -12,6 +12,7 @@ import ( testutil "github.com/VictoriaMetrics/VictoriaMetrics/app/victoria-metrics/test" "github.com/VictoriaMetrics/VictoriaMetrics/app/vmstorage" + "github.com/VictoriaMetrics/VictoriaMetrics/lib/decimal" "github.com/VictoriaMetrics/VictoriaMetrics/lib/logger" "github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils" "github.com/VictoriaMetrics/metricsql" @@ -85,9 +86,13 @@ func WriteInputSeries(input []Series, interval *promutils.Duration, startStamp t func parseInputValue(input string, origin bool) ([]sequenceValue, error) { var res []sequenceValue items := strings.Split(input, " ") - reg2 := regexp.MustCompile(`\D?\d*\D?`) + reg := regexp.MustCompile(`\D?\d*\D?`) for _, item := range items { - vals := reg2.FindAllString(item, -1) + if item == "stale" { + res = append(res, sequenceValue{Value: decimal.StaleNaN}) + continue + } + vals := reg.FindAllString(item, -1) switch len(vals) { case 1: if vals[0] == "_" { diff --git a/app/vmalert/unittest/input_test.go b/app/vmalert/unittest/input_test.go index cf8bb7942..5f74de98b 100644 --- a/app/vmalert/unittest/input_test.go +++ b/app/vmalert/unittest/input_test.go @@ -1,8 +1,9 @@ package unittest import ( - "reflect" "testing" + + "github.com/VictoriaMetrics/VictoriaMetrics/lib/decimal" ) func TestParseInputValue(t *testing.T) { @@ -21,6 +22,12 @@ func TestParseInputValue(t *testing.T) { nil, true, }, + // stale doesn't support operations + { + "stalex3", + nil, + true, + }, { "-4", []sequenceValue{{Value: -4}}, @@ -31,6 +38,11 @@ func TestParseInputValue(t *testing.T) { []sequenceValue{{Omitted: true}}, false, }, + { + "stale", + []sequenceValue{{Value: decimal.StaleNaN}}, + false, + }, { "-4x1", []sequenceValue{{Value: -4}, {Value: -4}}, @@ -52,8 +64,8 @@ func TestParseInputValue(t *testing.T) { false, }, { - "1+1x1 _ -4 3+20x1", - []sequenceValue{{Value: 1}, {Value: 2}, {Omitted: true}, {Value: -4}, {Value: 3}, {Value: 23}}, + "1+1x1 _ -4 stale 3+20x1", + []sequenceValue{{Value: 1}, {Value: 2}, {Omitted: true}, {Value: -4}, {Value: decimal.StaleNaN}, {Value: 3}, {Value: 23}}, false, }, } @@ -63,8 +75,19 @@ func TestParseInputValue(t *testing.T) { if err != nil != tc.failed { t.Fatalf("failed to parse %s, expect %t, got %t", tc.input, tc.failed, err != nil) } - if !reflect.DeepEqual(tc.exp, output) { + if len(tc.exp) != len(output) { t.Fatalf("expect %v, got %v", tc.exp, output) } + for i := 0; i < len(tc.exp); i++ { + if tc.exp[i].Omitted != output[i].Omitted { + t.Fatalf("expect %v, got %v", tc.exp, output) + } + if tc.exp[i].Value != output[i].Value { + if decimal.IsStaleNaN(tc.exp[i].Value) && decimal.IsStaleNaN(output[i].Value) { + continue + } + t.Fatalf("expect %v, got %v", tc.exp, output) + } + } } } diff --git a/app/vmalert/unittest/testdata/test1.yaml b/app/vmalert/unittest/testdata/test1.yaml index 96f3a30ab..d60e8587f 100644 --- a/app/vmalert/unittest/testdata/test1.yaml +++ b/app/vmalert/unittest/testdata/test1.yaml @@ -9,7 +9,7 @@ tests: name: "basic test" input_series: - series: "test" - values: "_x5 1x5" + values: "_x5 1x5 _ stale" alert_rule_test: - eval_time: 1m @@ -26,6 +26,16 @@ tests: alertname: SameAlertNameWithDifferentGroup exp_alerts: [] + metricsql_expr_test: + - expr: test + eval_time: 11m + exp_samples: + - labels: '{__name__="test"}' + value: 1 + - expr: test + eval_time: 12m + exp_samples: [] + - interval: 1m name: "basic test2" input_series: diff --git a/docs/vmalert.md b/docs/vmalert.md index 085f3c3cb..84d212b6d 100644 --- a/docs/vmalert.md +++ b/docs/vmalert.md @@ -824,16 +824,17 @@ external_labels: series: # values support several special equations: -# 'a+bxc' becomes 'a a+b a+(2*b) a+(3*b) … a+(c*b)' +# 'a+bxc' becomes 'a a+b a+(2*b) a+(3*b) … a+(c*b)' # Read this as series starts at a, then c further samples incrementing by b. -# 'a-bxc' becomes 'a a-b a-(2*b) a-(3*b) … a-(c*b)' +# 'a-bxc' becomes 'a a-b a-(2*b) a-(3*b) … a-(c*b)' # Read this as series starts at a, then c further samples decrementing by b (or incrementing by negative b). # '_' represents a missing sample from scrape +# 'stale' indicates a stale sample # Examples: # 1. '-2+4x3' becomes '-2 2 6 10' - series starts at -2, then 3 further samples incrementing by 4. # 2. ' 1-2x4' becomes '1 -1 -3 -5 -7' - series starts at 1, then 4 further samples decrementing by 2. # 3. ' 1x4' becomes '1 1 1 1 1' - shorthand for '1+0x4', series starts at 1, then 4 further samples incrementing by 0. -# 4. ' 1 _x3' becomes '1 _ _ _ ' - the missing sample cannot increment, so 3 missing samples are produced by the '_x3' expression. +# 4. ' 1 _x3 stale' becomes '1 _ _ _ stale' - the missing sample cannot increment, so 3 missing samples are produced by the '_x3' expression. values: ```