From 4edc6dbeae834162a64ddce2f575f4d61244f913 Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Thu, 19 Sep 2024 23:21:31 +0530 Subject: [PATCH] feat: add last option to alert condition match type (#5929) --- frontend/public/locales/en-GB/alerts.json | 1 + frontend/public/locales/en-GB/rules.json | 1 + frontend/public/locales/en/alerts.json | 1 + frontend/public/locales/en/rules.json | 1 + .../container/FormAlertRules/RuleOptions.tsx | 1 + pkg/query-service/rules/alerting.go | 1 + pkg/query-service/rules/base_rule.go | 21 ++++ .../rules/threshold_rule_test.go | 105 ++++++++++++++++++ 8 files changed, 132 insertions(+) diff --git a/frontend/public/locales/en-GB/alerts.json b/frontend/public/locales/en-GB/alerts.json index a43d04ab59..86f21c8c78 100644 --- a/frontend/public/locales/en-GB/alerts.json +++ b/frontend/public/locales/en-GB/alerts.json @@ -53,6 +53,7 @@ "option_atleastonce": "at least once", "option_onaverage": "on average", "option_intotal": "in total", + "option_last": "last", "option_above": "above", "option_below": "below", "option_equal": "is equal to", diff --git a/frontend/public/locales/en-GB/rules.json b/frontend/public/locales/en-GB/rules.json index 9d55a0ba0f..9ac3641c7a 100644 --- a/frontend/public/locales/en-GB/rules.json +++ b/frontend/public/locales/en-GB/rules.json @@ -40,6 +40,7 @@ "option_atleastonce": "at least once", "option_onaverage": "on average", "option_intotal": "in total", + "option_last": "last", "option_above": "above", "option_below": "below", "option_equal": "is equal to", diff --git a/frontend/public/locales/en/alerts.json b/frontend/public/locales/en/alerts.json index e7ed6232ad..02d20a2977 100644 --- a/frontend/public/locales/en/alerts.json +++ b/frontend/public/locales/en/alerts.json @@ -53,6 +53,7 @@ "option_atleastonce": "at least once", "option_onaverage": "on average", "option_intotal": "in total", + "option_last": "last", "option_above": "above", "option_below": "below", "option_equal": "is equal to", diff --git a/frontend/public/locales/en/rules.json b/frontend/public/locales/en/rules.json index 9d55a0ba0f..9ac3641c7a 100644 --- a/frontend/public/locales/en/rules.json +++ b/frontend/public/locales/en/rules.json @@ -40,6 +40,7 @@ "option_atleastonce": "at least once", "option_onaverage": "on average", "option_intotal": "in total", + "option_last": "last", "option_above": "above", "option_below": "below", "option_equal": "is equal to", diff --git a/frontend/src/container/FormAlertRules/RuleOptions.tsx b/frontend/src/container/FormAlertRules/RuleOptions.tsx index 2ef6bba4c0..da265f34cc 100644 --- a/frontend/src/container/FormAlertRules/RuleOptions.tsx +++ b/frontend/src/container/FormAlertRules/RuleOptions.tsx @@ -103,6 +103,7 @@ function RuleOptions({ {t('option_allthetimes')} {t('option_onaverage')} {t('option_intotal')} + {t('option_last')} ); diff --git a/pkg/query-service/rules/alerting.go b/pkg/query-service/rules/alerting.go index cb5205f99e..77c9fbe219 100644 --- a/pkg/query-service/rules/alerting.go +++ b/pkg/query-service/rules/alerting.go @@ -112,6 +112,7 @@ const ( AllTheTimes MatchType = "2" OnAverage MatchType = "3" InTotal MatchType = "4" + Last MatchType = "5" ) type RuleCondition struct { diff --git a/pkg/query-service/rules/base_rule.go b/pkg/query-service/rules/base_rule.go index a108938b1d..b82aab91b5 100644 --- a/pkg/query-service/rules/base_rule.go +++ b/pkg/query-service/rules/base_rule.go @@ -483,6 +483,27 @@ func (r *BaseRule) shouldAlert(series v3.Series) (Sample, bool) { shouldAlert = true } } + case Last: + // If the last sample matches the condition, the rule is firing. + shouldAlert = false + alertSmpl = Sample{Point: Point{V: series.Points[len(series.Points)-1].Value}, Metric: lblsNormalized, MetricOrig: lbls} + if r.compareOp() == ValueIsAbove { + if series.Points[len(series.Points)-1].Value > r.targetVal() { + shouldAlert = true + } + } else if r.compareOp() == ValueIsBelow { + if series.Points[len(series.Points)-1].Value < r.targetVal() { + shouldAlert = true + } + } else if r.compareOp() == ValueIsEq { + if series.Points[len(series.Points)-1].Value == r.targetVal() { + shouldAlert = true + } + } else if r.compareOp() == ValueIsNotEq { + if series.Points[len(series.Points)-1].Value != r.targetVal() { + shouldAlert = true + } + } } return alertSmpl, shouldAlert } diff --git a/pkg/query-service/rules/threshold_rule_test.go b/pkg/query-service/rules/threshold_rule_test.go index 65d020d25f..8f9554db52 100644 --- a/pkg/query-service/rules/threshold_rule_test.go +++ b/pkg/query-service/rules/threshold_rule_test.go @@ -677,6 +677,111 @@ func TestThresholdRuleShouldAlert(t *testing.T) { matchType: "4", // InTotal target: 20.0, }, + // Test cases for Last + // greater than last + { + values: v3.Series{ + Points: []v3.Point{ + {Value: 10.0}, + {Value: 10.0}, + }, + }, + expectAlert: true, + compareOp: "1", // Greater Than + matchType: "5", // Last + target: 5.0, + expectedAlertSample: v3.Point{Value: 10.0}, + }, + { + values: v3.Series{ + Points: []v3.Point{ + {Value: 10.0}, + {Value: 10.0}, + }, + }, + expectAlert: false, + compareOp: "1", // Greater Than + matchType: "5", // Last + target: 20.0, + }, + // less than last + { + values: v3.Series{ + Points: []v3.Point{ + {Value: 10.0}, + {Value: 10.0}, + }, + }, + expectAlert: true, + compareOp: "2", // Less Than + matchType: "5", // Last + target: 15.0, + expectedAlertSample: v3.Point{Value: 10.0}, + }, + { + values: v3.Series{ + Points: []v3.Point{ + {Value: 10.0}, + {Value: 10.0}, + }, + }, + expectAlert: false, + compareOp: "2", // Less Than + matchType: "5", // Last + target: 5.0, + }, + // equals last + { + values: v3.Series{ + Points: []v3.Point{ + {Value: 10.0}, + {Value: 10.0}, + }, + }, + expectAlert: true, + compareOp: "3", // Equals + matchType: "5", // Last + target: 10.0, + expectedAlertSample: v3.Point{Value: 10.0}, + }, + { + values: v3.Series{ + Points: []v3.Point{ + {Value: 10.0}, + {Value: 10.0}, + }, + }, + expectAlert: false, + compareOp: "3", // Equals + matchType: "5", // Last + target: 5.0, + }, + // not equals last + { + values: v3.Series{ + Points: []v3.Point{ + {Value: 10.0}, + {Value: 10.0}, + }, + }, + expectAlert: true, + compareOp: "4", // Not Equals + matchType: "5", // Last + target: 5.0, + expectedAlertSample: v3.Point{Value: 10.0}, + }, + { + values: v3.Series{ + Points: []v3.Point{ + {Value: 10.0}, + {Value: 10.0}, + }, + }, + expectAlert: false, + compareOp: "4", // Not Equals + matchType: "5", // Last + target: 10.0, + }, } fm := featureManager.StartManager()