diff --git a/pkg/api/alerting/v2alpha1/types.go b/pkg/api/alerting/v2alpha1/types.go index e723487d2..fbd37ff88 100644 --- a/pkg/api/alerting/v2alpha1/types.go +++ b/pkg/api/alerting/v2alpha1/types.go @@ -35,6 +35,8 @@ import ( const ( RuleLevelCluster RuleLevel = "cluster" RuleLevelNamespace RuleLevel = "namespace" + + AnnotationKeyRuleUpdateTime = "rule_update_time" ) var ( @@ -217,10 +219,22 @@ func AlertingRuleIdCompare(leftId, rightId string) bool { } func (q *AlertingRuleQueryParams) Sort(rules []*GettableAlertingRule) { - idCompare := func(left, right *GettableAlertingRule) bool { + baseCompare := func(left, right *GettableAlertingRule) bool { + var leftUpdateTime, rightUpdateTime string + if len(left.Annotations) > 0 { + leftUpdateTime = left.Annotations[AnnotationKeyRuleUpdateTime] + } + if len(right.Annotations) > 0 { + rightUpdateTime = right.Annotations[AnnotationKeyRuleUpdateTime] + } + + if leftUpdateTime != rightUpdateTime { + return leftUpdateTime > rightUpdateTime + } + return AlertingRuleIdCompare(left.Id, right.Id) } - var compare = idCompare + var compare = baseCompare if q != nil { reverse := q.SortType == "desc" switch q.SortField { @@ -232,7 +246,7 @@ func (q *AlertingRuleQueryParams) Sort(rules []*GettableAlertingRule) { } return c < 0 } - return idCompare(left, right) + return baseCompare(left, right) } case "lastEvaluation": compare = func(left, right *GettableAlertingRule) bool { @@ -250,7 +264,7 @@ func (q *AlertingRuleQueryParams) Sort(rules []*GettableAlertingRule) { return left.LastEvaluation.Before(*right.LastEvaluation) } } - return idCompare(left, right) + return baseCompare(left, right) } case "evaluationTime": compare = func(left, right *GettableAlertingRule) bool { @@ -260,7 +274,7 @@ func (q *AlertingRuleQueryParams) Sort(rules []*GettableAlertingRule) { } return left.EvaluationDurationSeconds < right.EvaluationDurationSeconds } - return idCompare(left, right) + return baseCompare(left, right) } } } diff --git a/pkg/models/alerting/alerting.go b/pkg/models/alerting/alerting.go index 90568c713..3a4b14d4a 100644 --- a/pkg/models/alerting/alerting.go +++ b/pkg/models/alerting/alerting.go @@ -4,6 +4,7 @@ import ( "context" "sort" "strings" + "time" "github.com/pkg/errors" promresourcesv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" @@ -470,6 +471,8 @@ func (o *operator) CreateCustomAlertingRule(ctx context.Context, namespace strin return v2alpha1.ErrAlertingRuleAlreadyExists } + setRuleUpdateTime(rule, time.Now()) + return ruler.AddAlertingRule(ctx, ruleNamespace, extraRuleResourceSelector, customRuleGroupDefault, parseToPrometheusRule(rule), ruleResourceLabels) } @@ -521,6 +524,8 @@ func (o *operator) UpdateCustomAlertingRule(ctx context.Context, namespace, name return v2alpha1.ErrAlertingRuleNotFound } + setRuleUpdateTime(rule, time.Now()) + return ruler.UpdateAlertingRule(ctx, ruleNamespace, extraRuleResourceSelector, resourceRule.Group, parseToPrometheusRule(rule), ruleResourceLabels) } @@ -633,3 +638,13 @@ func pageAlerts(alertingRules []*v2alpha1.GettableAlertingRule, Items: queryParams.Sub(alerts), } } + +func setRuleUpdateTime(rule *v2alpha1.PostableAlertingRule, t time.Time) { + if rule.Annotations == nil { + rule.Annotations = make(map[string]string) + } + if t.IsZero() { + t = time.Now() + } + rule.Annotations[v2alpha1.AnnotationKeyRuleUpdateTime] = t.UTC().Format(time.RFC3339) +}