2021-05-13 09:05:33 -05:00
package state_test
2021-03-24 17:34:18 -05:00
import (
2021-10-05 06:26:24 -05:00
"context"
2021-11-25 04:46:47 -06:00
"errors"
2021-11-26 11:58:19 -06:00
"fmt"
2022-08-18 08:40:33 -05:00
"math/rand"
2022-02-24 04:58:54 -06:00
"sort"
2021-03-24 17:34:18 -05:00
"testing"
2021-03-30 11:37:56 -05:00
"time"
2022-06-22 11:18:42 -05:00
"github.com/benbjohnson/clock"
2022-11-09 14:08:57 -06:00
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
2021-03-24 17:34:18 -05:00
"github.com/grafana/grafana-plugin-sdk-go/data"
2022-05-22 09:33:49 -05:00
"github.com/prometheus/client_golang/prometheus"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
2021-11-04 14:15:56 -05:00
2021-11-25 04:46:47 -06:00
"github.com/grafana/grafana/pkg/expr"
2022-05-22 09:33:49 -05:00
"github.com/grafana/grafana/pkg/services/annotations"
2022-09-19 02:54:37 -05:00
"github.com/grafana/grafana/pkg/services/annotations/annotationstest"
2022-05-22 09:33:49 -05:00
"github.com/grafana/grafana/pkg/services/dashboards"
2021-03-24 17:34:18 -05:00
"github.com/grafana/grafana/pkg/services/ngalert/eval"
2021-09-14 06:55:01 -05:00
"github.com/grafana/grafana/pkg/services/ngalert/metrics"
2021-03-24 17:34:18 -05:00
"github.com/grafana/grafana/pkg/services/ngalert/models"
2021-09-14 06:55:01 -05:00
"github.com/grafana/grafana/pkg/services/ngalert/state"
2022-10-05 15:32:20 -05:00
"github.com/grafana/grafana/pkg/services/ngalert/state/historian"
2021-09-14 06:55:01 -05:00
"github.com/grafana/grafana/pkg/services/ngalert/tests"
2023-01-27 02:46:21 -06:00
"github.com/grafana/grafana/pkg/util"
2021-03-24 17:34:18 -05:00
)
2021-09-14 06:55:01 -05:00
var testMetrics = metrics . NewNGAlert ( prometheus . NewPedanticRegistry ( ) )
2021-04-30 11:28:06 -05:00
2022-11-09 14:08:57 -06:00
func TestWarmStateCache ( t * testing . T ) {
evaluationTime , err := time . Parse ( "2006-01-02" , "2021-03-25" )
require . NoError ( t , err )
ctx := context . Background ( )
_ , dbstore := tests . SetupTestEnv ( t , 1 )
const mainOrgID int64 = 1
rule := tests . CreateTestAlertRule ( t , ctx , dbstore , 600 , mainOrgID )
expectedEntries := [ ] * state . State {
{
AlertRuleUID : rule . UID ,
OrgID : rule . OrgID ,
CacheID : ` [["test1","testValue1"]] ` ,
Labels : data . Labels { "test1" : "testValue1" } ,
State : eval . Normal ,
Results : [ ] state . Evaluation {
{ EvaluationTime : evaluationTime , EvaluationState : eval . Normal } ,
} ,
StartsAt : evaluationTime . Add ( - 1 * time . Minute ) ,
EndsAt : evaluationTime . Add ( 1 * time . Minute ) ,
LastEvaluationTime : evaluationTime ,
Annotations : map [ string ] string { "testAnnoKey" : "testAnnoValue" } ,
} , {
AlertRuleUID : rule . UID ,
OrgID : rule . OrgID ,
CacheID : ` [["test2","testValue2"]] ` ,
Labels : data . Labels { "test2" : "testValue2" } ,
State : eval . Alerting ,
Results : [ ] state . Evaluation {
{ EvaluationTime : evaluationTime , EvaluationState : eval . Alerting } ,
} ,
StartsAt : evaluationTime . Add ( - 1 * time . Minute ) ,
EndsAt : evaluationTime . Add ( 1 * time . Minute ) ,
LastEvaluationTime : evaluationTime ,
Annotations : map [ string ] string { "testAnnoKey" : "testAnnoValue" } ,
} ,
2023-01-04 08:40:04 -06:00
{
AlertRuleUID : rule . UID ,
OrgID : rule . OrgID ,
CacheID : ` [["test3","testValue3"]] ` ,
Labels : data . Labels { "test3" : "testValue3" } ,
State : eval . NoData ,
Results : [ ] state . Evaluation {
{ EvaluationTime : evaluationTime , EvaluationState : eval . NoData } ,
} ,
StartsAt : evaluationTime . Add ( - 1 * time . Minute ) ,
EndsAt : evaluationTime . Add ( 1 * time . Minute ) ,
LastEvaluationTime : evaluationTime ,
Annotations : map [ string ] string { "testAnnoKey" : "testAnnoValue" } ,
} ,
{
AlertRuleUID : rule . UID ,
OrgID : rule . OrgID ,
CacheID : ` [["test4","testValue4"]] ` ,
Labels : data . Labels { "test4" : "testValue4" } ,
State : eval . Error ,
Results : [ ] state . Evaluation {
{ EvaluationTime : evaluationTime , EvaluationState : eval . Error } ,
} ,
StartsAt : evaluationTime . Add ( - 1 * time . Minute ) ,
EndsAt : evaluationTime . Add ( 1 * time . Minute ) ,
LastEvaluationTime : evaluationTime ,
Annotations : map [ string ] string { "testAnnoKey" : "testAnnoValue" } ,
} ,
{
AlertRuleUID : rule . UID ,
OrgID : rule . OrgID ,
CacheID : ` [["test5","testValue5"]] ` ,
Labels : data . Labels { "test5" : "testValue5" } ,
State : eval . Pending ,
Results : [ ] state . Evaluation {
{ EvaluationTime : evaluationTime , EvaluationState : eval . Pending } ,
} ,
StartsAt : evaluationTime . Add ( - 1 * time . Minute ) ,
EndsAt : evaluationTime . Add ( 1 * time . Minute ) ,
LastEvaluationTime : evaluationTime ,
Annotations : map [ string ] string { "testAnnoKey" : "testAnnoValue" } ,
} ,
2022-11-09 14:08:57 -06:00
}
labels := models . InstanceLabels { "test1" : "testValue1" }
_ , hash , _ := labels . StringAndHash ( )
instance1 := models . AlertInstance {
AlertInstanceKey : models . AlertInstanceKey {
RuleOrgID : rule . OrgID ,
RuleUID : rule . UID ,
LabelsHash : hash ,
} ,
CurrentState : models . InstanceStateNormal ,
LastEvalTime : evaluationTime ,
CurrentStateSince : evaluationTime . Add ( - 1 * time . Minute ) ,
CurrentStateEnd : evaluationTime . Add ( 1 * time . Minute ) ,
Labels : labels ,
}
labels = models . InstanceLabels { "test2" : "testValue2" }
_ , hash , _ = labels . StringAndHash ( )
instance2 := models . AlertInstance {
AlertInstanceKey : models . AlertInstanceKey {
RuleOrgID : rule . OrgID ,
RuleUID : rule . UID ,
LabelsHash : hash ,
} ,
CurrentState : models . InstanceStateFiring ,
LastEvalTime : evaluationTime ,
CurrentStateSince : evaluationTime . Add ( - 1 * time . Minute ) ,
CurrentStateEnd : evaluationTime . Add ( 1 * time . Minute ) ,
Labels : labels ,
}
2023-01-04 08:40:04 -06:00
labels = models . InstanceLabels { "test3" : "testValue3" }
_ , hash , _ = labels . StringAndHash ( )
instance3 := models . AlertInstance {
AlertInstanceKey : models . AlertInstanceKey {
RuleOrgID : rule . OrgID ,
RuleUID : rule . UID ,
LabelsHash : hash ,
} ,
CurrentState : models . InstanceStateNoData ,
LastEvalTime : evaluationTime ,
CurrentStateSince : evaluationTime . Add ( - 1 * time . Minute ) ,
CurrentStateEnd : evaluationTime . Add ( 1 * time . Minute ) ,
Labels : labels ,
}
labels = models . InstanceLabels { "test4" : "testValue4" }
_ , hash , _ = labels . StringAndHash ( )
instance4 := models . AlertInstance {
AlertInstanceKey : models . AlertInstanceKey {
RuleOrgID : rule . OrgID ,
RuleUID : rule . UID ,
LabelsHash : hash ,
} ,
CurrentState : models . InstanceStateError ,
LastEvalTime : evaluationTime ,
CurrentStateSince : evaluationTime . Add ( - 1 * time . Minute ) ,
CurrentStateEnd : evaluationTime . Add ( 1 * time . Minute ) ,
Labels : labels ,
}
labels = models . InstanceLabels { "test5" : "testValue5" }
_ , hash , _ = labels . StringAndHash ( )
instance5 := models . AlertInstance {
AlertInstanceKey : models . AlertInstanceKey {
RuleOrgID : rule . OrgID ,
RuleUID : rule . UID ,
LabelsHash : hash ,
} ,
CurrentState : models . InstanceStatePending ,
LastEvalTime : evaluationTime ,
CurrentStateSince : evaluationTime . Add ( - 1 * time . Minute ) ,
CurrentStateEnd : evaluationTime . Add ( 1 * time . Minute ) ,
Labels : labels ,
}
_ = dbstore . SaveAlertInstances ( ctx , instance1 , instance2 , instance3 , instance4 , instance5 )
2023-01-10 15:26:15 -06:00
cfg := state . ManagerCfg {
Metrics : testMetrics . GetStateMetrics ( ) ,
ExternalURL : nil ,
InstanceStore : dbstore ,
Images : & state . NoopImageService { } ,
Clock : clock . NewMock ( ) ,
Historian : & state . FakeHistorian { } ,
}
st := state . NewManager ( cfg )
2022-11-09 14:08:57 -06:00
st . Warm ( ctx , dbstore )
t . Run ( "instance cache has expected entries" , func ( t * testing . T ) {
for _ , entry := range expectedEntries {
cacheEntry := st . Get ( entry . OrgID , entry . AlertRuleUID , entry . CacheID )
if diff := cmp . Diff ( entry , cacheEntry , cmpopts . IgnoreFields ( state . State { } , "Results" ) ) ; diff != "" {
t . Errorf ( "Result mismatch (-want +got):\n%s" , diff )
t . FailNow ( )
}
}
} )
}
2022-02-24 04:58:54 -06:00
func TestDashboardAnnotations ( t * testing . T ) {
evaluationTime , err := time . Parse ( "2006-01-02" , "2022-01-01" )
require . NoError ( t , err )
ctx := context . Background ( )
_ , dbstore := tests . SetupTestEnv ( t , 1 )
2022-09-19 02:54:37 -05:00
fakeAnnoRepo := annotationstest . NewFakeAnnotationsRepo ( )
2023-03-06 10:40:37 -06:00
metrics := metrics . NewHistorianMetrics ( prometheus . NewRegistry ( ) )
hist := historian . NewAnnotationBackend ( fakeAnnoRepo , & dashboards . FakeDashboardService { } , nil , metrics )
2023-01-10 15:26:15 -06:00
cfg := state . ManagerCfg {
Metrics : testMetrics . GetStateMetrics ( ) ,
ExternalURL : nil ,
InstanceStore : dbstore ,
Images : & state . NoopImageService { } ,
Clock : clock . New ( ) ,
Historian : hist ,
}
st := state . NewManager ( cfg )
2022-02-24 04:58:54 -06:00
const mainOrgID int64 = 1
rule := tests . CreateTestAlertRuleWithLabels ( t , ctx , dbstore , 600 , mainOrgID , map [ string ] string {
"test1" : "testValue1" ,
"test2" : "{{ $labels.instance_label }}" ,
} )
2022-11-04 13:23:08 -05:00
st . Warm ( ctx , dbstore )
2022-11-03 04:35:34 -05:00
bValue := float64 ( 42 )
cValue := float64 ( 1 )
2022-06-21 17:16:53 -05:00
_ = st . ProcessEvalResults ( ctx , evaluationTime , rule , eval . Results { {
2022-02-24 04:58:54 -06:00
Instance : data . Labels { "instance_label" : "testValue2" } ,
State : eval . Alerting ,
EvaluatedAt : evaluationTime ,
2022-11-03 04:35:34 -05:00
Values : map [ string ] eval . NumberValueCapture {
"B" : { Var : "B" , Value : & bValue , Labels : data . Labels { "job" : "prometheus" } } ,
"C" : { Var : "C" , Value : & cValue , Labels : data . Labels { "job" : "prometheus" } } ,
} ,
2022-07-14 14:59:59 -05:00
} } , data . Labels {
"alertname" : rule . Title ,
} )
2022-02-24 04:58:54 -06:00
2022-11-03 04:35:34 -05:00
expected := [ ] string { rule . Title + " {alertname=" + rule . Title + ", instance_label=testValue2, test1=testValue1, test2=testValue2} - B=42.000000, C=1.000000" }
2022-02-24 04:58:54 -06:00
sort . Strings ( expected )
require . Eventuallyf ( t , func ( ) bool {
var actual [ ] string
2022-09-19 02:54:37 -05:00
for _ , next := range fakeAnnoRepo . Items ( ) {
2022-02-24 04:58:54 -06:00
actual = append ( actual , next . Text )
}
sort . Strings ( actual )
if len ( expected ) != len ( actual ) {
return false
}
for i := 0 ; i < len ( expected ) ; i ++ {
if expected [ i ] != actual [ i ] {
return false
}
}
return true
} , time . Second , 100 * time . Millisecond , "unexpected annotations" )
}
2021-03-24 17:34:18 -05:00
func TestProcessEvalResults ( t * testing . T ) {
2021-03-30 11:37:56 -05:00
evaluationTime , err := time . Parse ( "2006-01-02" , "2021-03-25" )
if err != nil {
t . Fatalf ( "error parsing date format: %s" , err . Error ( ) )
}
2021-04-23 13:47:52 -05:00
evaluationDuration := 10 * time . Millisecond
2021-04-21 11:30:03 -05:00
2021-03-24 17:34:18 -05:00
testCases := [ ] struct {
2021-12-01 05:04:54 -06:00
desc string
alertRule * models . AlertRule
evalResults [ ] eval . Results
expectedStates map [ string ] * state . State
expectedAnnotations int
2021-03-24 17:34:18 -05:00
} {
{
2021-04-23 13:47:52 -05:00
desc : "a cache entry is correctly created" ,
alertRule : & models . AlertRule {
OrgID : 1 ,
Title : "test_title" ,
UID : "test_alert_rule_uid" ,
NamespaceUID : "test_namespace_uid" ,
Annotations : map [ string ] string { "annotation" : "test" } ,
Labels : map [ string ] string { "label" : "test" } ,
IntervalSeconds : 10 ,
} ,
evalResults : [ ] eval . Results {
2021-03-30 11:37:56 -05:00
{
2021-04-23 13:47:52 -05:00
eval . Result {
2021-04-23 14:32:25 -05:00
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Normal ,
EvaluatedAt : evaluationTime ,
EvaluationDuration : evaluationDuration ,
2021-04-23 13:47:52 -05:00
} ,
} ,
} ,
2021-04-23 14:32:25 -05:00
expectedStates : map [ string ] * state . State {
2021-04-28 10:42:19 -05:00
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` : {
2021-04-23 13:47:52 -05:00
AlertRuleUID : "test_alert_rule_uid" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` ,
2021-04-23 13:47:52 -05:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid" ,
"alertname" : "test_title" ,
"label" : "test" ,
"instance_label" : "test" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
State : eval . Normal ,
2021-04-23 14:32:25 -05:00
Results : [ ] state . Evaluation {
2021-04-23 13:47:52 -05:00
{
EvaluationTime : evaluationTime ,
EvaluationState : eval . Normal ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-04-23 13:47:52 -05:00
} ,
2021-04-02 10:11:33 -05:00
} ,
LastEvaluationTime : evaluationTime ,
2021-04-23 13:47:52 -05:00
EvaluationDuration : evaluationDuration ,
Annotations : map [ string ] string { "annotation" : "test" } ,
2021-03-30 11:37:56 -05:00
} ,
} ,
2021-03-24 17:34:18 -05:00
} ,
{
2021-04-23 13:47:52 -05:00
desc : "two results create two correct cache entries" ,
alertRule : & models . AlertRule {
OrgID : 1 ,
Title : "test_title" ,
UID : "test_alert_rule_uid" ,
NamespaceUID : "test_namespace_uid" ,
Annotations : map [ string ] string { "annotation" : "test" } ,
Labels : map [ string ] string { "label" : "test" } ,
IntervalSeconds : 10 ,
} ,
evalResults : [ ] eval . Results {
2021-03-30 11:37:56 -05:00
{
2021-04-23 13:47:52 -05:00
eval . Result {
2021-04-23 14:32:25 -05:00
Instance : data . Labels { "instance_label_1" : "test" } ,
State : eval . Normal ,
EvaluatedAt : evaluationTime ,
EvaluationDuration : evaluationDuration ,
2021-04-23 13:47:52 -05:00
} ,
eval . Result {
2021-04-23 14:32:25 -05:00
Instance : data . Labels { "instance_label_2" : "test" } ,
State : eval . Alerting ,
EvaluatedAt : evaluationTime ,
EvaluationDuration : evaluationDuration ,
2021-04-23 13:47:52 -05:00
} ,
} ,
} ,
2021-12-01 05:04:54 -06:00
expectedAnnotations : 1 ,
2021-04-23 14:32:25 -05:00
expectedStates : map [ string ] * state . State {
2021-04-28 10:42:19 -05:00
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid"],["alertname","test_title"],["instance_label_1","test"],["label","test"]] ` : {
2021-04-23 13:47:52 -05:00
AlertRuleUID : "test_alert_rule_uid" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid"],["alertname","test_title"],["instance_label_1","test"],["label","test"]] ` ,
2021-04-23 13:47:52 -05:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid" ,
"alertname" : "test_title" ,
"label" : "test" ,
"instance_label_1" : "test" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
State : eval . Normal ,
2021-04-23 14:32:25 -05:00
Results : [ ] state . Evaluation {
2021-04-23 13:47:52 -05:00
{
EvaluationTime : evaluationTime ,
EvaluationState : eval . Normal ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-04-23 13:47:52 -05:00
} ,
2021-04-02 10:11:33 -05:00
} ,
2021-04-23 13:47:52 -05:00
LastEvaluationTime : evaluationTime ,
EvaluationDuration : evaluationDuration ,
Annotations : map [ string ] string { "annotation" : "test" } ,
} ,
2021-04-28 10:42:19 -05:00
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid"],["alertname","test_title"],["instance_label_2","test"],["label","test"]] ` : {
2021-04-23 13:47:52 -05:00
AlertRuleUID : "test_alert_rule_uid" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid"],["alertname","test_title"],["instance_label_2","test"],["label","test"]] ` ,
2021-04-23 13:47:52 -05:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid" ,
"alertname" : "test_title" ,
"label" : "test" ,
"instance_label_2" : "test" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
State : eval . Alerting ,
2021-04-23 14:32:25 -05:00
Results : [ ] state . Evaluation {
2021-04-23 13:47:52 -05:00
{
EvaluationTime : evaluationTime ,
EvaluationState : eval . Alerting ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-04-23 13:47:52 -05:00
} ,
} ,
StartsAt : evaluationTime ,
2021-09-02 10:22:59 -05:00
EndsAt : evaluationTime . Add ( state . ResendDelay * 3 ) ,
2021-04-23 13:47:52 -05:00
LastEvaluationTime : evaluationTime ,
EvaluationDuration : evaluationDuration ,
Annotations : map [ string ] string { "annotation" : "test" } ,
2021-03-30 11:37:56 -05:00
} ,
} ,
2021-03-24 17:34:18 -05:00
} ,
{
2021-04-23 13:47:52 -05:00
desc : "state is maintained" ,
alertRule : & models . AlertRule {
OrgID : 1 ,
Title : "test_title" ,
UID : "test_alert_rule_uid_1" ,
NamespaceUID : "test_namespace_uid" ,
Annotations : map [ string ] string { "annotation" : "test" } ,
Labels : map [ string ] string { "label" : "test" } ,
IntervalSeconds : 10 ,
} ,
evalResults : [ ] eval . Results {
{
eval . Result {
2021-04-23 14:32:25 -05:00
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Normal ,
EvaluatedAt : evaluationTime ,
EvaluationDuration : evaluationDuration ,
2021-04-23 13:47:52 -05:00
} ,
} ,
2021-03-30 11:37:56 -05:00
{
2021-04-23 13:47:52 -05:00
eval . Result {
2021-04-23 14:32:25 -05:00
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Normal ,
EvaluatedAt : evaluationTime . Add ( 1 * time . Minute ) ,
EvaluationDuration : evaluationDuration ,
2021-04-23 13:47:52 -05:00
} ,
} ,
} ,
2021-04-23 14:32:25 -05:00
expectedStates : map [ string ] * state . State {
2021-04-28 10:42:19 -05:00
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_1"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` : {
2021-04-23 13:47:52 -05:00
AlertRuleUID : "test_alert_rule_uid_1" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_1"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` ,
2021-04-23 13:47:52 -05:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid_1" ,
"alertname" : "test_title" ,
"label" : "test" ,
"instance_label" : "test" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
State : eval . Normal ,
2021-04-23 14:32:25 -05:00
Results : [ ] state . Evaluation {
2021-04-23 13:47:52 -05:00
{
EvaluationTime : evaluationTime ,
EvaluationState : eval . Normal ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-04-23 13:47:52 -05:00
} ,
{
EvaluationTime : evaluationTime . Add ( 1 * time . Minute ) ,
EvaluationState : eval . Normal ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-04-23 13:47:52 -05:00
} ,
2021-04-02 10:11:33 -05:00
} ,
LastEvaluationTime : evaluationTime . Add ( 1 * time . Minute ) ,
2021-04-23 13:47:52 -05:00
EvaluationDuration : evaluationDuration ,
Annotations : map [ string ] string { "annotation" : "test" } ,
2021-03-30 11:37:56 -05:00
} ,
} ,
2021-03-24 17:34:18 -05:00
} ,
{
2021-04-23 13:47:52 -05:00
desc : "normal -> alerting transition when For is unset" ,
alertRule : & models . AlertRule {
OrgID : 1 ,
Title : "test_title" ,
UID : "test_alert_rule_uid_2" ,
NamespaceUID : "test_namespace_uid" ,
Annotations : map [ string ] string { "annotation" : "test" } ,
Labels : map [ string ] string { "label" : "test" } ,
IntervalSeconds : 10 ,
} ,
evalResults : [ ] eval . Results {
2021-03-30 11:37:56 -05:00
{
2021-04-23 13:47:52 -05:00
eval . Result {
2021-04-23 14:32:25 -05:00
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Normal ,
EvaluatedAt : evaluationTime ,
EvaluationDuration : evaluationDuration ,
2021-04-23 13:47:52 -05:00
} ,
} ,
{
eval . Result {
2021-04-23 14:32:25 -05:00
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Alerting ,
EvaluatedAt : evaluationTime . Add ( 1 * time . Minute ) ,
EvaluationDuration : evaluationDuration ,
2021-04-23 13:47:52 -05:00
} ,
} ,
} ,
2021-12-01 05:04:54 -06:00
expectedAnnotations : 1 ,
2021-04-23 14:32:25 -05:00
expectedStates : map [ string ] * state . State {
2021-04-28 10:42:19 -05:00
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` : {
2021-04-23 13:47:52 -05:00
AlertRuleUID : "test_alert_rule_uid_2" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` ,
2021-04-23 13:47:52 -05:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid_2" ,
"alertname" : "test_title" ,
"label" : "test" ,
"instance_label" : "test" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
State : eval . Alerting ,
2021-04-23 14:32:25 -05:00
Results : [ ] state . Evaluation {
2021-04-23 13:47:52 -05:00
{
EvaluationTime : evaluationTime ,
EvaluationState : eval . Normal ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-04-23 13:47:52 -05:00
} ,
{
EvaluationTime : evaluationTime . Add ( 1 * time . Minute ) ,
EvaluationState : eval . Alerting ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-04-23 13:47:52 -05:00
} ,
2021-04-02 10:11:33 -05:00
} ,
2021-04-23 13:47:52 -05:00
StartsAt : evaluationTime . Add ( 1 * time . Minute ) ,
2021-09-02 10:22:59 -05:00
EndsAt : evaluationTime . Add ( 1 * time . Minute ) . Add ( state . ResendDelay * 3 ) ,
2021-04-02 10:11:33 -05:00
LastEvaluationTime : evaluationTime . Add ( 1 * time . Minute ) ,
2021-04-23 13:47:52 -05:00
EvaluationDuration : evaluationDuration ,
2021-05-04 12:08:12 -05:00
Annotations : map [ string ] string { "annotation" : "test" } ,
2021-03-30 11:37:56 -05:00
} ,
} ,
2021-03-24 17:34:18 -05:00
} ,
{
2021-04-23 13:47:52 -05:00
desc : "normal -> alerting when For is set" ,
alertRule : & models . AlertRule {
OrgID : 1 ,
Title : "test_title" ,
UID : "test_alert_rule_uid_2" ,
NamespaceUID : "test_namespace_uid" ,
Annotations : map [ string ] string { "annotation" : "test" } ,
Labels : map [ string ] string { "label" : "test" } ,
IntervalSeconds : 10 ,
For : 1 * time . Minute ,
} ,
evalResults : [ ] eval . Results {
2021-03-30 11:37:56 -05:00
{
2021-04-23 13:47:52 -05:00
eval . Result {
2021-04-23 14:32:25 -05:00
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Normal ,
EvaluatedAt : evaluationTime ,
EvaluationDuration : evaluationDuration ,
2021-04-23 13:47:52 -05:00
} ,
} ,
{
eval . Result {
2021-04-23 14:32:25 -05:00
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Alerting ,
EvaluatedAt : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
2021-04-23 13:47:52 -05:00
} ,
} ,
{
eval . Result {
2021-04-23 14:32:25 -05:00
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Alerting ,
EvaluatedAt : evaluationTime . Add ( 80 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
2021-04-23 13:47:52 -05:00
} ,
} ,
} ,
2021-12-01 05:04:54 -06:00
expectedAnnotations : 2 ,
2021-04-23 14:32:25 -05:00
expectedStates : map [ string ] * state . State {
2021-04-28 10:42:19 -05:00
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` : {
2021-04-23 13:47:52 -05:00
AlertRuleUID : "test_alert_rule_uid_2" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` ,
2021-04-23 13:47:52 -05:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid_2" ,
"alertname" : "test_title" ,
"label" : "test" ,
"instance_label" : "test" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
State : eval . Alerting ,
2021-04-23 14:32:25 -05:00
Results : [ ] state . Evaluation {
2021-04-23 13:47:52 -05:00
{
EvaluationTime : evaluationTime ,
EvaluationState : eval . Normal ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-04-23 13:47:52 -05:00
} ,
{
EvaluationTime : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationState : eval . Alerting ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-04-23 13:47:52 -05:00
} ,
{
EvaluationTime : evaluationTime . Add ( 80 * time . Second ) ,
EvaluationState : eval . Alerting ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-04-23 13:47:52 -05:00
} ,
} ,
StartsAt : evaluationTime . Add ( 80 * time . Second ) ,
2021-09-02 10:22:59 -05:00
EndsAt : evaluationTime . Add ( 80 * time . Second ) . Add ( state . ResendDelay * 3 ) ,
2021-04-23 13:47:52 -05:00
LastEvaluationTime : evaluationTime . Add ( 80 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
2021-05-04 12:08:12 -05:00
Annotations : map [ string ] string { "annotation" : "test" } ,
2021-04-23 13:47:52 -05:00
} ,
} ,
} ,
2021-11-04 14:15:56 -05:00
{
desc : "normal -> alerting -> noData -> alerting when For is set" ,
alertRule : & models . AlertRule {
OrgID : 1 ,
Title : "test_title" ,
UID : "test_alert_rule_uid_2" ,
NamespaceUID : "test_namespace_uid" ,
Annotations : map [ string ] string { "annotation" : "test" } ,
Labels : map [ string ] string { "label" : "test" } ,
IntervalSeconds : 10 ,
For : 20 * time . Second ,
NoDataState : models . NoData ,
} ,
evalResults : [ ] eval . Results {
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Normal ,
EvaluatedAt : evaluationTime ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Alerting ,
EvaluatedAt : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . NoData ,
EvaluatedAt : evaluationTime . Add ( 20 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Alerting ,
EvaluatedAt : evaluationTime . Add ( 30 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Alerting ,
EvaluatedAt : evaluationTime . Add ( 40 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
} ,
2021-12-01 05:04:54 -06:00
expectedAnnotations : 3 ,
2021-11-04 14:15:56 -05:00
expectedStates : map [ string ] * state . State {
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` : {
AlertRuleUID : "test_alert_rule_uid_2" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` ,
2021-11-04 14:15:56 -05:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid_2" ,
"alertname" : "test_title" ,
"label" : "test" ,
"instance_label" : "test" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
State : eval . Pending ,
2021-11-04 14:15:56 -05:00
Results : [ ] state . Evaluation {
{
EvaluationTime : evaluationTime . Add ( 30 * time . Second ) ,
EvaluationState : eval . Alerting ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-11-04 14:15:56 -05:00
} ,
{
EvaluationTime : evaluationTime . Add ( 40 * time . Second ) ,
EvaluationState : eval . Alerting ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-11-04 14:15:56 -05:00
} ,
} ,
StartsAt : evaluationTime . Add ( 30 * time . Second ) ,
EndsAt : evaluationTime . Add ( 30 * time . Second ) . Add ( state . ResendDelay * 3 ) ,
LastEvaluationTime : evaluationTime . Add ( 40 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
Annotations : map [ string ] string { "annotation" : "test" } ,
} ,
} ,
} ,
{
desc : "pending -> alerting -> noData when For is set and NoDataState is NoData" ,
alertRule : & models . AlertRule {
OrgID : 1 ,
Title : "test_title" ,
UID : "test_alert_rule_uid_2" ,
NamespaceUID : "test_namespace_uid" ,
Annotations : map [ string ] string { "annotation" : "test" } ,
Labels : map [ string ] string { "label" : "test" } ,
IntervalSeconds : 10 ,
For : 20 * time . Second ,
NoDataState : models . NoData ,
} ,
evalResults : [ ] eval . Results {
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Alerting ,
EvaluatedAt : evaluationTime ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Alerting ,
EvaluatedAt : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Alerting ,
EvaluatedAt : evaluationTime . Add ( 20 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . NoData ,
EvaluatedAt : evaluationTime . Add ( 30 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
} ,
2022-03-01 11:06:42 -06:00
expectedAnnotations : 3 ,
2021-11-04 14:15:56 -05:00
expectedStates : map [ string ] * state . State {
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` : {
AlertRuleUID : "test_alert_rule_uid_2" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` ,
2021-11-04 14:15:56 -05:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid_2" ,
"alertname" : "test_title" ,
"label" : "test" ,
"instance_label" : "test" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
State : eval . NoData ,
2021-11-04 14:15:56 -05:00
Results : [ ] state . Evaluation {
{
EvaluationTime : evaluationTime . Add ( 20 * time . Second ) ,
EvaluationState : eval . Alerting ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-11-04 14:15:56 -05:00
} ,
{
EvaluationTime : evaluationTime . Add ( 30 * time . Second ) ,
EvaluationState : eval . NoData ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-11-04 14:15:56 -05:00
} ,
} ,
2022-03-01 11:06:42 -06:00
StartsAt : evaluationTime . Add ( 20 * time . Second ) ,
2021-11-04 14:15:56 -05:00
EndsAt : evaluationTime . Add ( 30 * time . Second ) . Add ( state . ResendDelay * 3 ) ,
LastEvaluationTime : evaluationTime . Add ( 30 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
Annotations : map [ string ] string { "annotation" : "test" } ,
} ,
} ,
} ,
2021-04-23 13:47:52 -05:00
{
2021-05-26 13:37:42 -05:00
desc : "normal -> pending when For is set but not exceeded and first result is normal" ,
2021-04-23 13:47:52 -05:00
alertRule : & models . AlertRule {
OrgID : 1 ,
Title : "test_title" ,
UID : "test_alert_rule_uid_2" ,
NamespaceUID : "test_namespace_uid" ,
Annotations : map [ string ] string { "annotation" : "test" } ,
Labels : map [ string ] string { "label" : "test" } ,
IntervalSeconds : 10 ,
For : 1 * time . Minute ,
} ,
evalResults : [ ] eval . Results {
{
eval . Result {
2021-04-23 14:32:25 -05:00
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Normal ,
EvaluatedAt : evaluationTime ,
EvaluationDuration : evaluationDuration ,
2021-04-23 13:47:52 -05:00
} ,
} ,
{
eval . Result {
2021-04-23 14:32:25 -05:00
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Alerting ,
EvaluatedAt : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
2021-04-23 13:47:52 -05:00
} ,
} ,
} ,
2021-12-01 05:04:54 -06:00
expectedAnnotations : 1 ,
2021-04-23 14:32:25 -05:00
expectedStates : map [ string ] * state . State {
2021-04-28 10:42:19 -05:00
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` : {
2021-04-23 13:47:52 -05:00
AlertRuleUID : "test_alert_rule_uid_2" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` ,
2021-04-23 13:47:52 -05:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid_2" ,
"alertname" : "test_title" ,
"label" : "test" ,
"instance_label" : "test" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
State : eval . Pending ,
2021-04-23 14:32:25 -05:00
Results : [ ] state . Evaluation {
2021-04-23 13:47:52 -05:00
{
EvaluationTime : evaluationTime ,
EvaluationState : eval . Normal ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-04-23 13:47:52 -05:00
} ,
{
EvaluationTime : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationState : eval . Alerting ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-04-23 13:47:52 -05:00
} ,
} ,
StartsAt : evaluationTime . Add ( 10 * time . Second ) ,
2021-09-02 10:22:59 -05:00
EndsAt : evaluationTime . Add ( 10 * time . Second ) . Add ( state . ResendDelay * 3 ) ,
2021-04-23 13:47:52 -05:00
LastEvaluationTime : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
Annotations : map [ string ] string { "annotation" : "test" } ,
} ,
} ,
} ,
2021-05-26 13:37:42 -05:00
{
desc : "normal -> pending when For is set but not exceeded and first result is alerting" ,
alertRule : & models . AlertRule {
OrgID : 1 ,
Title : "test_title" ,
UID : "test_alert_rule_uid_2" ,
NamespaceUID : "test_namespace_uid" ,
Annotations : map [ string ] string { "annotation" : "test" } ,
Labels : map [ string ] string { "label" : "test" } ,
IntervalSeconds : 10 ,
For : 1 * time . Minute ,
} ,
evalResults : [ ] eval . Results {
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Alerting ,
EvaluatedAt : evaluationTime ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Alerting ,
EvaluatedAt : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
} ,
2021-12-01 05:04:54 -06:00
expectedAnnotations : 1 ,
2021-05-26 13:37:42 -05:00
expectedStates : map [ string ] * state . State {
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` : {
AlertRuleUID : "test_alert_rule_uid_2" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` ,
2021-05-26 13:37:42 -05:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid_2" ,
"alertname" : "test_title" ,
"label" : "test" ,
"instance_label" : "test" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
State : eval . Pending ,
2021-05-26 13:37:42 -05:00
Results : [ ] state . Evaluation {
{
EvaluationTime : evaluationTime ,
EvaluationState : eval . Alerting ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-05-26 13:37:42 -05:00
} ,
{
EvaluationTime : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationState : eval . Alerting ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-05-26 13:37:42 -05:00
} ,
} ,
StartsAt : evaluationTime ,
2021-09-02 10:22:59 -05:00
EndsAt : evaluationTime . Add ( state . ResendDelay * 3 ) ,
2021-05-26 13:37:42 -05:00
LastEvaluationTime : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
Annotations : map [ string ] string { "annotation" : "test" } ,
} ,
} ,
} ,
2021-04-23 13:47:52 -05:00
{
desc : "normal -> alerting when result is NoData and NoDataState is alerting" ,
alertRule : & models . AlertRule {
OrgID : 1 ,
Title : "test_title" ,
UID : "test_alert_rule_uid_2" ,
NamespaceUID : "test_namespace_uid" ,
Annotations : map [ string ] string { "annotation" : "test" } ,
Labels : map [ string ] string { "label" : "test" } ,
IntervalSeconds : 10 ,
NoDataState : models . Alerting ,
} ,
evalResults : [ ] eval . Results {
{
eval . Result {
2021-04-23 14:32:25 -05:00
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Normal ,
EvaluatedAt : evaluationTime ,
EvaluationDuration : evaluationDuration ,
2021-04-23 13:47:52 -05:00
} ,
} ,
{
eval . Result {
2021-04-23 14:32:25 -05:00
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . NoData ,
EvaluatedAt : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
2021-04-23 13:47:52 -05:00
} ,
} ,
} ,
2021-12-01 05:04:54 -06:00
expectedAnnotations : 1 ,
2021-04-23 14:32:25 -05:00
expectedStates : map [ string ] * state . State {
2021-04-28 10:42:19 -05:00
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` : {
2021-04-23 13:47:52 -05:00
AlertRuleUID : "test_alert_rule_uid_2" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` ,
2021-04-23 13:47:52 -05:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid_2" ,
"alertname" : "test_title" ,
"label" : "test" ,
"instance_label" : "test" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
2022-05-23 03:49:49 -05:00
State : eval . Alerting ,
StateReason : eval . NoData . String ( ) ,
2021-04-23 14:32:25 -05:00
Results : [ ] state . Evaluation {
2021-04-23 13:47:52 -05:00
{
EvaluationTime : evaluationTime ,
EvaluationState : eval . Normal ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-04-23 13:47:52 -05:00
} ,
{
EvaluationTime : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationState : eval . NoData ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-04-23 13:47:52 -05:00
} ,
} ,
StartsAt : evaluationTime . Add ( 10 * time . Second ) ,
2021-09-02 10:22:59 -05:00
EndsAt : evaluationTime . Add ( 10 * time . Second ) . Add ( state . ResendDelay * 3 ) ,
2021-04-23 13:47:52 -05:00
LastEvaluationTime : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
2021-05-04 12:08:12 -05:00
Annotations : map [ string ] string { "annotation" : "test" } ,
2021-04-23 13:47:52 -05:00
} ,
} ,
} ,
{
desc : "normal -> nodata when result is NoData and NoDataState is nodata" ,
alertRule : & models . AlertRule {
OrgID : 1 ,
Title : "test_title" ,
UID : "test_alert_rule_uid_2" ,
NamespaceUID : "test_namespace_uid" ,
Annotations : map [ string ] string { "annotation" : "test" } ,
Labels : map [ string ] string { "label" : "test" } ,
IntervalSeconds : 10 ,
NoDataState : models . NoData ,
} ,
evalResults : [ ] eval . Results {
{
eval . Result {
2021-04-23 14:32:25 -05:00
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Normal ,
EvaluatedAt : evaluationTime ,
EvaluationDuration : evaluationDuration ,
2021-04-23 13:47:52 -05:00
} ,
} ,
{
eval . Result {
2021-04-23 14:32:25 -05:00
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . NoData ,
EvaluatedAt : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
2021-04-23 13:47:52 -05:00
} ,
} ,
} ,
2021-12-01 05:04:54 -06:00
expectedAnnotations : 1 ,
2021-04-23 14:32:25 -05:00
expectedStates : map [ string ] * state . State {
2021-04-28 10:42:19 -05:00
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` : {
2021-04-23 13:47:52 -05:00
AlertRuleUID : "test_alert_rule_uid_2" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` ,
2021-04-23 13:47:52 -05:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid_2" ,
"alertname" : "test_title" ,
"label" : "test" ,
"instance_label" : "test" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
State : eval . NoData ,
2021-04-23 14:32:25 -05:00
Results : [ ] state . Evaluation {
2021-04-23 13:47:52 -05:00
{
EvaluationTime : evaluationTime ,
EvaluationState : eval . Normal ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-04-23 13:47:52 -05:00
} ,
{
EvaluationTime : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationState : eval . NoData ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-04-23 13:47:52 -05:00
} ,
} ,
StartsAt : evaluationTime . Add ( 10 * time . Second ) ,
2021-09-02 10:22:59 -05:00
EndsAt : evaluationTime . Add ( 10 * time . Second ) . Add ( state . ResendDelay * 3 ) ,
2021-04-23 13:47:52 -05:00
LastEvaluationTime : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
2021-05-04 12:08:12 -05:00
Annotations : map [ string ] string { "annotation" : "test" } ,
2021-04-23 13:47:52 -05:00
} ,
} ,
} ,
2021-11-04 14:15:56 -05:00
{
desc : "normal -> nodata no labels when result is NoData and NoDataState is nodata" ,
alertRule : & models . AlertRule {
OrgID : 1 ,
Title : "test_title" ,
UID : "test_alert_rule_uid_2" ,
NamespaceUID : "test_namespace_uid" ,
Annotations : map [ string ] string { "annotation" : "test" } ,
Labels : map [ string ] string { "label" : "test" } ,
IntervalSeconds : 10 ,
NoDataState : models . NoData ,
} ,
evalResults : [ ] eval . Results {
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Normal ,
EvaluatedAt : evaluationTime ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { } ,
State : eval . NoData ,
EvaluatedAt : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
} ,
2021-12-01 05:04:54 -06:00
expectedAnnotations : 1 ,
2021-11-04 14:15:56 -05:00
expectedStates : map [ string ] * state . State {
2022-06-21 17:16:53 -05:00
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` : {
AlertRuleUID : "test_alert_rule_uid_2" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` ,
2022-06-21 17:16:53 -05:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid_2" ,
"alertname" : "test_title" ,
"label" : "test" ,
"instance_label" : "test" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
State : eval . Normal ,
2022-06-21 17:16:53 -05:00
Results : [ ] state . Evaluation {
{
EvaluationTime : evaluationTime ,
EvaluationState : eval . Normal ,
Values : make ( map [ string ] * float64 ) ,
} ,
} ,
StartsAt : time . Time { } ,
EndsAt : time . Time { } ,
LastEvaluationTime : evaluationTime ,
EvaluationDuration : evaluationDuration ,
Annotations : map [ string ] string { "annotation" : "test" } ,
} ,
2021-11-04 14:15:56 -05:00
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["label","test"]] ` : {
AlertRuleUID : "test_alert_rule_uid_2" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["label","test"]] ` ,
2021-11-04 14:15:56 -05:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid_2" ,
"alertname" : "test_title" ,
"label" : "test" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
State : eval . NoData ,
2021-11-04 14:15:56 -05:00
Results : [ ] state . Evaluation {
{
EvaluationTime : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationState : eval . NoData ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-11-04 14:15:56 -05:00
} ,
} ,
StartsAt : evaluationTime . Add ( 10 * time . Second ) ,
EndsAt : evaluationTime . Add ( 10 * time . Second ) . Add ( state . ResendDelay * 3 ) ,
LastEvaluationTime : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
Annotations : map [ string ] string { "annotation" : "test" } ,
} ,
} ,
} ,
{
desc : "normal (multi-dimensional) -> nodata no labels when result is NoData and NoDataState is nodata" ,
alertRule : & models . AlertRule {
OrgID : 1 ,
Title : "test_title" ,
UID : "test_alert_rule_uid_2" ,
NamespaceUID : "test_namespace_uid" ,
Annotations : map [ string ] string { "annotation" : "test" } ,
Labels : map [ string ] string { "label" : "test" } ,
IntervalSeconds : 10 ,
NoDataState : models . NoData ,
} ,
evalResults : [ ] eval . Results {
{
eval . Result {
Instance : data . Labels { "instance_label" : "test-1" } ,
State : eval . Normal ,
EvaluatedAt : evaluationTime ,
EvaluationDuration : evaluationDuration ,
} ,
eval . Result {
Instance : data . Labels { "instance_label" : "test-2" } ,
State : eval . Normal ,
EvaluatedAt : evaluationTime ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { } ,
State : eval . NoData ,
EvaluatedAt : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
} ,
2021-12-01 05:04:54 -06:00
expectedAnnotations : 1 ,
2021-11-04 14:15:56 -05:00
expectedStates : map [ string ] * state . State {
2022-06-21 17:16:53 -05:00
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test-1"],["label","test"]] ` : {
AlertRuleUID : "test_alert_rule_uid_2" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test-1"],["label","test"]] ` ,
2022-06-21 17:16:53 -05:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid_2" ,
"alertname" : "test_title" ,
"label" : "test" ,
"instance_label" : "test-1" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
State : eval . Normal ,
2022-06-21 17:16:53 -05:00
Results : [ ] state . Evaluation {
{
EvaluationTime : evaluationTime ,
EvaluationState : eval . Normal ,
Values : make ( map [ string ] * float64 ) ,
} ,
} ,
StartsAt : time . Time { } ,
EndsAt : time . Time { } ,
LastEvaluationTime : evaluationTime ,
EvaluationDuration : evaluationDuration ,
Annotations : map [ string ] string { "annotation" : "test" } ,
} ,
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test-2"],["label","test"]] ` : {
AlertRuleUID : "test_alert_rule_uid_2" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test-2"],["label","test"]] ` ,
2022-06-21 17:16:53 -05:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid_2" ,
"alertname" : "test_title" ,
"label" : "test" ,
"instance_label" : "test-2" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
State : eval . Normal ,
2022-06-21 17:16:53 -05:00
Results : [ ] state . Evaluation {
{
EvaluationTime : evaluationTime ,
EvaluationState : eval . Normal ,
Values : make ( map [ string ] * float64 ) ,
} ,
} ,
StartsAt : time . Time { } ,
EndsAt : time . Time { } ,
LastEvaluationTime : evaluationTime ,
EvaluationDuration : evaluationDuration ,
Annotations : map [ string ] string { "annotation" : "test" } ,
} ,
2021-11-04 14:15:56 -05:00
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["label","test"]] ` : {
AlertRuleUID : "test_alert_rule_uid_2" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["label","test"]] ` ,
2021-11-04 14:15:56 -05:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid_2" ,
"alertname" : "test_title" ,
"label" : "test" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
State : eval . NoData ,
2021-11-04 14:15:56 -05:00
Results : [ ] state . Evaluation {
{
EvaluationTime : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationState : eval . NoData ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-11-04 14:15:56 -05:00
} ,
} ,
StartsAt : evaluationTime . Add ( 10 * time . Second ) ,
EndsAt : evaluationTime . Add ( 10 * time . Second ) . Add ( state . ResendDelay * 3 ) ,
LastEvaluationTime : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
Annotations : map [ string ] string { "annotation" : "test" } ,
} ,
} ,
} ,
{
desc : "normal -> nodata no labels -> normal when result is NoData and NoDataState is nodata" ,
alertRule : & models . AlertRule {
OrgID : 1 ,
Title : "test_title" ,
UID : "test_alert_rule_uid_2" ,
NamespaceUID : "test_namespace_uid" ,
Annotations : map [ string ] string { "annotation" : "test" } ,
Labels : map [ string ] string { "label" : "test" } ,
IntervalSeconds : 10 ,
NoDataState : models . NoData ,
} ,
evalResults : [ ] eval . Results {
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Normal ,
EvaluatedAt : evaluationTime ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { } ,
State : eval . NoData ,
EvaluatedAt : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Normal ,
EvaluatedAt : evaluationTime . Add ( 20 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
} ,
2021-12-01 05:04:54 -06:00
expectedAnnotations : 1 ,
2021-11-04 14:15:56 -05:00
expectedStates : map [ string ] * state . State {
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` : {
AlertRuleUID : "test_alert_rule_uid_2" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` ,
2021-11-04 14:15:56 -05:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid_2" ,
"alertname" : "test_title" ,
"label" : "test" ,
"instance_label" : "test" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
State : eval . Normal ,
2021-11-04 14:15:56 -05:00
Results : [ ] state . Evaluation {
2022-06-21 17:16:53 -05:00
{
EvaluationTime : evaluationTime ,
EvaluationState : eval . Normal ,
Values : make ( map [ string ] * float64 ) ,
} ,
2021-11-04 14:15:56 -05:00
{
EvaluationTime : evaluationTime . Add ( 20 * time . Second ) ,
EvaluationState : eval . Normal ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-11-04 14:15:56 -05:00
} ,
} ,
StartsAt : time . Time { } ,
EndsAt : time . Time { } ,
LastEvaluationTime : evaluationTime . Add ( 20 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
Annotations : map [ string ] string { "annotation" : "test" } ,
} ,
2022-06-21 17:16:53 -05:00
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["label","test"]] ` : {
AlertRuleUID : "test_alert_rule_uid_2" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["label","test"]] ` ,
2022-06-21 17:16:53 -05:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid_2" ,
"alertname" : "test_title" ,
"label" : "test" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
State : eval . NoData ,
2022-06-21 17:16:53 -05:00
Results : [ ] state . Evaluation {
{
EvaluationTime : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationState : eval . NoData ,
Values : make ( map [ string ] * float64 ) ,
} ,
} ,
StartsAt : evaluationTime . Add ( 10 * time . Second ) ,
EndsAt : evaluationTime . Add ( 10 * time . Second ) . Add ( state . ResendDelay * 3 ) ,
LastEvaluationTime : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
Annotations : map [ string ] string { "annotation" : "test" } ,
} ,
2021-11-04 14:15:56 -05:00
} ,
} ,
2021-04-23 13:47:52 -05:00
{
desc : "normal -> normal when result is NoData and NoDataState is ok" ,
alertRule : & models . AlertRule {
OrgID : 1 ,
Title : "test_title" ,
UID : "test_alert_rule_uid_2" ,
NamespaceUID : "test_namespace_uid" ,
Annotations : map [ string ] string { "annotation" : "test" } ,
Labels : map [ string ] string { "label" : "test" } ,
IntervalSeconds : 10 ,
NoDataState : models . OK ,
} ,
evalResults : [ ] eval . Results {
{
eval . Result {
2021-04-23 14:32:25 -05:00
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Normal ,
EvaluatedAt : evaluationTime ,
EvaluationDuration : evaluationDuration ,
2021-04-23 13:47:52 -05:00
} ,
} ,
{
eval . Result {
2021-04-23 14:32:25 -05:00
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . NoData ,
EvaluatedAt : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
2021-04-02 10:11:33 -05:00
} ,
2021-04-23 13:47:52 -05:00
} ,
} ,
2022-05-23 03:49:49 -05:00
expectedAnnotations : 1 ,
2021-04-23 14:32:25 -05:00
expectedStates : map [ string ] * state . State {
2021-04-28 10:42:19 -05:00
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` : {
2021-04-23 13:47:52 -05:00
AlertRuleUID : "test_alert_rule_uid_2" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` ,
2021-04-23 13:47:52 -05:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid_2" ,
"alertname" : "test_title" ,
"label" : "test" ,
"instance_label" : "test" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
2022-05-23 03:49:49 -05:00
State : eval . Normal ,
StateReason : eval . NoData . String ( ) ,
2021-04-23 14:32:25 -05:00
Results : [ ] state . Evaluation {
2021-04-23 13:47:52 -05:00
{
EvaluationTime : evaluationTime ,
EvaluationState : eval . Normal ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-04-23 13:47:52 -05:00
} ,
{
EvaluationTime : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationState : eval . NoData ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-04-23 13:47:52 -05:00
} ,
} ,
StartsAt : evaluationTime . Add ( 10 * time . Second ) ,
2021-09-02 10:22:59 -05:00
EndsAt : evaluationTime . Add ( 10 * time . Second ) . Add ( state . ResendDelay * 3 ) ,
2021-04-23 13:47:52 -05:00
LastEvaluationTime : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
2021-05-04 12:08:12 -05:00
Annotations : map [ string ] string { "annotation" : "test" } ,
2021-04-23 13:47:52 -05:00
} ,
} ,
} ,
{
desc : "EndsAt set correctly. normal -> alerting when result is NoData and NoDataState is alerting and For is set and For is breached" ,
alertRule : & models . AlertRule {
OrgID : 1 ,
Title : "test_title" ,
UID : "test_alert_rule_uid_2" ,
NamespaceUID : "test_namespace_uid" ,
Annotations : map [ string ] string { "annotation" : "test" } ,
Labels : map [ string ] string { "label" : "test" } ,
IntervalSeconds : 10 ,
For : 1 * time . Minute ,
NoDataState : models . Alerting ,
} ,
evalResults : [ ] eval . Results {
{
eval . Result {
2021-04-23 14:32:25 -05:00
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Normal ,
EvaluatedAt : evaluationTime ,
EvaluationDuration : evaluationDuration ,
2021-04-23 13:47:52 -05:00
} ,
} ,
{
eval . Result {
2021-04-23 14:32:25 -05:00
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . NoData ,
EvaluatedAt : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
2021-04-23 13:47:52 -05:00
} ,
} ,
} ,
2021-12-01 05:04:54 -06:00
expectedAnnotations : 1 ,
2021-04-23 14:32:25 -05:00
expectedStates : map [ string ] * state . State {
2021-04-28 10:42:19 -05:00
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` : {
2021-04-23 13:47:52 -05:00
AlertRuleUID : "test_alert_rule_uid_2" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` ,
2021-04-23 13:47:52 -05:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid_2" ,
"alertname" : "test_title" ,
"label" : "test" ,
"instance_label" : "test" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
2022-05-23 03:49:49 -05:00
State : eval . Alerting ,
StateReason : eval . NoData . String ( ) ,
2021-04-23 14:32:25 -05:00
Results : [ ] state . Evaluation {
2021-04-23 13:47:52 -05:00
{
EvaluationTime : evaluationTime ,
EvaluationState : eval . Normal ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-04-23 13:47:52 -05:00
} ,
{
EvaluationTime : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationState : eval . NoData ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-04-23 13:47:52 -05:00
} ,
} ,
StartsAt : evaluationTime . Add ( 10 * time . Second ) ,
2021-09-02 10:22:59 -05:00
EndsAt : evaluationTime . Add ( 10 * time . Second ) . Add ( state . ResendDelay * 3 ) ,
2021-04-23 13:47:52 -05:00
LastEvaluationTime : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
2021-05-04 12:08:12 -05:00
Annotations : map [ string ] string { "annotation" : "test" } ,
2021-04-23 13:47:52 -05:00
} ,
} ,
} ,
{
2022-03-31 03:57:58 -05:00
desc : "normal -> pending when For is set but not exceeded, result is Error and ExecErrState is Alerting" ,
2021-04-23 13:47:52 -05:00
alertRule : & models . AlertRule {
OrgID : 1 ,
Title : "test_title" ,
UID : "test_alert_rule_uid_2" ,
NamespaceUID : "test_namespace_uid" ,
Annotations : map [ string ] string { "annotation" : "test" } ,
Labels : map [ string ] string { "label" : "test" } ,
IntervalSeconds : 10 ,
For : 1 * time . Minute ,
2021-05-18 12:55:43 -05:00
ExecErrState : models . AlertingErrState ,
2021-04-23 13:47:52 -05:00
} ,
evalResults : [ ] eval . Results {
{
eval . Result {
2021-04-23 14:32:25 -05:00
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Normal ,
EvaluatedAt : evaluationTime ,
EvaluationDuration : evaluationDuration ,
2021-04-23 13:47:52 -05:00
} ,
} ,
{
eval . Result {
2021-04-23 14:32:25 -05:00
Instance : data . Labels { "instance_label" : "test" } ,
2021-05-18 12:55:43 -05:00
State : eval . Error ,
2022-11-03 04:35:34 -05:00
Error : errors . New ( "test error" ) ,
2021-04-23 14:32:25 -05:00
EvaluatedAt : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
2021-04-23 13:47:52 -05:00
} ,
} ,
} ,
2021-12-01 05:04:54 -06:00
expectedAnnotations : 1 ,
2021-04-23 14:32:25 -05:00
expectedStates : map [ string ] * state . State {
2021-04-28 10:42:19 -05:00
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` : {
2021-04-23 13:47:52 -05:00
AlertRuleUID : "test_alert_rule_uid_2" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` ,
2021-04-23 13:47:52 -05:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid_2" ,
"alertname" : "test_title" ,
"label" : "test" ,
"instance_label" : "test" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
2022-05-23 03:49:49 -05:00
State : eval . Pending ,
StateReason : eval . Error . String ( ) ,
2022-11-03 04:35:34 -05:00
Error : errors . New ( "test error" ) ,
2021-04-23 14:32:25 -05:00
Results : [ ] state . Evaluation {
2021-04-23 13:47:52 -05:00
{
EvaluationTime : evaluationTime ,
EvaluationState : eval . Normal ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-04-23 13:47:52 -05:00
} ,
{
EvaluationTime : evaluationTime . Add ( 10 * time . Second ) ,
2021-05-18 12:55:43 -05:00
EvaluationState : eval . Error ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-04-23 13:47:52 -05:00
} ,
} ,
StartsAt : evaluationTime . Add ( 10 * time . Second ) ,
2021-09-02 10:22:59 -05:00
EndsAt : evaluationTime . Add ( 10 * time . Second ) . Add ( state . ResendDelay * 3 ) ,
2021-04-23 13:47:52 -05:00
LastEvaluationTime : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
2021-05-04 12:08:12 -05:00
Annotations : map [ string ] string { "annotation" : "test" } ,
2021-03-30 11:37:56 -05:00
} ,
} ,
2021-03-24 17:34:18 -05:00
} ,
2022-03-31 03:57:58 -05:00
{
desc : "normal -> alerting when For is exceeded, result is Error and ExecErrState is Alerting" ,
alertRule : & models . AlertRule {
OrgID : 1 ,
Title : "test_title" ,
UID : "test_alert_rule_uid_2" ,
NamespaceUID : "test_namespace_uid" ,
Annotations : map [ string ] string { "annotation" : "test" } ,
Labels : map [ string ] string { "label" : "test" } ,
IntervalSeconds : 10 ,
For : 30 * time . Second ,
ExecErrState : models . AlertingErrState ,
} ,
evalResults : [ ] eval . Results {
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Normal ,
EvaluatedAt : evaluationTime ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Error ,
EvaluatedAt : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Error ,
EvaluatedAt : evaluationTime . Add ( 20 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Error ,
EvaluatedAt : evaluationTime . Add ( 30 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Error ,
EvaluatedAt : evaluationTime . Add ( 40 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
} ,
expectedAnnotations : 2 ,
expectedStates : map [ string ] * state . State {
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` : {
AlertRuleUID : "test_alert_rule_uid_2" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` ,
2022-03-31 03:57:58 -05:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid_2" ,
"alertname" : "test_title" ,
"label" : "test" ,
"instance_label" : "test" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
2022-05-23 03:49:49 -05:00
State : eval . Alerting ,
StateReason : eval . Error . String ( ) ,
2022-03-31 03:57:58 -05:00
Results : [ ] state . Evaluation {
{
EvaluationTime : evaluationTime . Add ( 20 * time . Second ) ,
EvaluationState : eval . Error ,
Values : make ( map [ string ] * float64 ) ,
} ,
{
EvaluationTime : evaluationTime . Add ( 30 * time . Second ) ,
EvaluationState : eval . Error ,
Values : make ( map [ string ] * float64 ) ,
} ,
{
EvaluationTime : evaluationTime . Add ( 40 * time . Second ) ,
EvaluationState : eval . Error ,
Values : make ( map [ string ] * float64 ) ,
} ,
} ,
StartsAt : evaluationTime . Add ( 40 * time . Second ) ,
EndsAt : evaluationTime . Add ( 40 * time . Second ) . Add ( state . ResendDelay * 3 ) ,
LastEvaluationTime : evaluationTime . Add ( 40 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
Annotations : map [ string ] string { "annotation" : "test" } ,
} ,
} ,
} ,
2021-11-25 04:46:47 -06:00
{
desc : "normal -> error when result is Error and ExecErrState is Error" ,
alertRule : & models . AlertRule {
OrgID : 1 ,
Title : "test_title" ,
UID : "test_alert_rule_uid_2" ,
NamespaceUID : "test_namespace_uid" ,
Data : [ ] models . AlertQuery { {
RefID : "A" ,
DatasourceUID : "datasource_uid_1" ,
} } ,
Annotations : map [ string ] string { "annotation" : "test" } ,
Labels : map [ string ] string { "label" : "test" } ,
IntervalSeconds : 10 ,
For : 1 * time . Minute ,
ExecErrState : models . ErrorErrState ,
} ,
evalResults : [ ] eval . Results {
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Normal ,
EvaluatedAt : evaluationTime ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
Error : expr . QueryError {
RefID : "A" ,
Err : errors . New ( "this is an error" ) ,
} ,
State : eval . Error ,
EvaluatedAt : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
} ,
2021-12-01 05:04:54 -06:00
expectedAnnotations : 1 ,
2021-11-25 04:46:47 -06:00
expectedStates : map [ string ] * state . State {
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` : {
AlertRuleUID : "test_alert_rule_uid_2" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` ,
2021-11-25 04:46:47 -06:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid_2" ,
"alertname" : "test_title" ,
"label" : "test" ,
"instance_label" : "test" ,
"datasource_uid" : "datasource_uid_1" ,
2021-12-03 03:55:16 -06:00
"ref_id" : "A" ,
2021-11-25 04:46:47 -06:00
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
State : eval . Error ,
2021-11-25 04:46:47 -06:00
Error : expr . QueryError {
RefID : "A" ,
Err : errors . New ( "this is an error" ) ,
} ,
Results : [ ] state . Evaluation {
{
EvaluationTime : evaluationTime ,
EvaluationState : eval . Normal ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-11-25 04:46:47 -06:00
} ,
{
EvaluationTime : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationState : eval . Error ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-11-25 04:46:47 -06:00
} ,
} ,
StartsAt : evaluationTime . Add ( 10 * time . Second ) ,
EndsAt : evaluationTime . Add ( 10 * time . Second ) . Add ( state . ResendDelay * 3 ) ,
LastEvaluationTime : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
Annotations : map [ string ] string { "annotation" : "test" , "Error" : "failed to execute query A: this is an error" } ,
} ,
} ,
} ,
2022-04-13 13:45:29 -05:00
{
desc : "normal -> normal when result is Error and ExecErrState is OK" ,
alertRule : & models . AlertRule {
OrgID : 1 ,
Title : "test_title" ,
UID : "test_alert_rule_uid_2" ,
NamespaceUID : "test_namespace_uid" ,
Data : [ ] models . AlertQuery { {
RefID : "A" ,
DatasourceUID : "datasource_uid_1" ,
} } ,
Annotations : map [ string ] string { "annotation" : "test" } ,
Labels : map [ string ] string { "label" : "test" } ,
IntervalSeconds : 10 ,
For : 1 * time . Minute ,
ExecErrState : models . OkErrState ,
} ,
evalResults : [ ] eval . Results {
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Normal ,
EvaluatedAt : evaluationTime ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
Error : expr . QueryError {
RefID : "A" ,
Err : errors . New ( "this is an error" ) ,
} ,
State : eval . Error ,
EvaluatedAt : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
} ,
2022-05-23 03:49:49 -05:00
expectedAnnotations : 1 ,
2022-04-13 13:45:29 -05:00
expectedStates : map [ string ] * state . State {
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` : {
AlertRuleUID : "test_alert_rule_uid_2" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` ,
2022-04-13 13:45:29 -05:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid_2" ,
"alertname" : "test_title" ,
"label" : "test" ,
"instance_label" : "test" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
2022-05-23 03:49:49 -05:00
State : eval . Normal ,
StateReason : eval . Error . String ( ) ,
Error : nil ,
2022-04-13 13:45:29 -05:00
Results : [ ] state . Evaluation {
{
EvaluationTime : evaluationTime ,
EvaluationState : eval . Normal ,
Values : make ( map [ string ] * float64 ) ,
} ,
{
EvaluationTime : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationState : eval . Error ,
Values : make ( map [ string ] * float64 ) ,
} ,
} ,
LastEvaluationTime : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
Annotations : map [ string ] string { "annotation" : "test" } ,
} ,
} ,
} ,
{
desc : "alerting -> normal when result is Error and ExecErrState is OK" ,
alertRule : & models . AlertRule {
OrgID : 1 ,
Title : "test_title" ,
UID : "test_alert_rule_uid_2" ,
NamespaceUID : "test_namespace_uid" ,
Data : [ ] models . AlertQuery { {
RefID : "A" ,
DatasourceUID : "datasource_uid_1" ,
} } ,
Annotations : map [ string ] string { "annotation" : "test" } ,
Labels : map [ string ] string { "label" : "test" } ,
IntervalSeconds : 10 ,
For : 1 * time . Minute ,
ExecErrState : models . OkErrState ,
} ,
evalResults : [ ] eval . Results {
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Alerting ,
EvaluatedAt : evaluationTime ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
Error : expr . QueryError {
RefID : "A" ,
Err : errors . New ( "this is an error" ) ,
} ,
State : eval . Error ,
EvaluatedAt : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
} ,
expectedAnnotations : 2 ,
expectedStates : map [ string ] * state . State {
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` : {
AlertRuleUID : "test_alert_rule_uid_2" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` ,
2022-04-13 13:45:29 -05:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid_2" ,
"alertname" : "test_title" ,
"label" : "test" ,
"instance_label" : "test" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
2022-05-23 03:49:49 -05:00
State : eval . Normal ,
StateReason : eval . Error . String ( ) ,
Error : nil ,
2022-04-13 13:45:29 -05:00
Results : [ ] state . Evaluation {
{
EvaluationTime : evaluationTime ,
EvaluationState : eval . Alerting ,
Values : make ( map [ string ] * float64 ) ,
} ,
{
EvaluationTime : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationState : eval . Error ,
Values : make ( map [ string ] * float64 ) ,
} ,
} ,
StartsAt : evaluationTime . Add ( 10 * time . Second ) ,
EndsAt : evaluationTime . Add ( 10 * time . Second ) ,
LastEvaluationTime : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
Annotations : map [ string ] string { "annotation" : "test" } ,
} ,
} ,
} ,
2022-07-14 04:53:39 -05:00
{
desc : "normal -> alerting -> error when result is Error and ExecErrorState is Error" ,
alertRule : & models . AlertRule {
OrgID : 1 ,
Title : "test_title" ,
UID : "test_alert_rule_uid_2" ,
NamespaceUID : "test_namespace_uid" ,
Annotations : map [ string ] string { "annotation" : "test" } ,
Labels : map [ string ] string { "label" : "test" } ,
IntervalSeconds : 10 ,
For : 20 * time . Second ,
ExecErrState : models . ErrorErrState ,
} ,
evalResults : [ ] eval . Results {
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Alerting ,
EvaluatedAt : evaluationTime ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Alerting ,
EvaluatedAt : evaluationTime . Add ( 10 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Alerting ,
EvaluatedAt : evaluationTime . Add ( 20 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Error ,
EvaluatedAt : evaluationTime . Add ( 30 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Error ,
EvaluatedAt : evaluationTime . Add ( 40 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Error ,
EvaluatedAt : evaluationTime . Add ( 50 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
} ,
expectedAnnotations : 3 ,
expectedStates : map [ string ] * state . State {
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` : {
AlertRuleUID : "test_alert_rule_uid_2" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` ,
2022-07-14 04:53:39 -05:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid_2" ,
"alertname" : "test_title" ,
"label" : "test" ,
"instance_label" : "test" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
State : eval . Error ,
2022-07-14 04:53:39 -05:00
Results : [ ] state . Evaluation {
{
EvaluationTime : evaluationTime . Add ( 40 * time . Second ) ,
EvaluationState : eval . Error ,
Values : make ( map [ string ] * float64 ) ,
} ,
{
EvaluationTime : evaluationTime . Add ( 50 * time . Second ) ,
EvaluationState : eval . Error ,
Values : make ( map [ string ] * float64 ) ,
} ,
} ,
2022-12-06 12:44:06 -06:00
StartsAt : evaluationTime . Add ( 30 * time . Second ) ,
2022-07-14 04:53:39 -05:00
EndsAt : evaluationTime . Add ( 50 * time . Second ) . Add ( state . ResendDelay * 3 ) ,
LastEvaluationTime : evaluationTime . Add ( 50 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
Annotations : map [ string ] string { "annotation" : "test" } ,
} ,
} ,
} ,
2021-11-26 11:58:19 -06:00
{
desc : "normal -> alerting -> error -> alerting - it should clear the error" ,
alertRule : & models . AlertRule {
OrgID : 1 ,
Title : "test_title" ,
UID : "test_alert_rule_uid_2" ,
NamespaceUID : "test_namespace_uid" ,
Annotations : map [ string ] string { "annotation" : "test" } ,
Labels : map [ string ] string { "label" : "test" } ,
IntervalSeconds : 10 ,
For : 30 * time . Second ,
} ,
evalResults : [ ] eval . Results {
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Normal ,
EvaluatedAt : evaluationTime ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Alerting ,
EvaluatedAt : evaluationTime . Add ( 30 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Error ,
Error : fmt . Errorf ( "Failed to query data" ) ,
EvaluatedAt : evaluationTime . Add ( 40 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Alerting ,
EvaluatedAt : evaluationTime . Add ( 70 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
} ,
2022-05-23 03:49:49 -05:00
expectedAnnotations : 3 ,
2021-11-26 11:58:19 -06:00
expectedStates : map [ string ] * state . State {
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` : {
AlertRuleUID : "test_alert_rule_uid_2" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` ,
2021-11-26 11:58:19 -06:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid_2" ,
"alertname" : "test_title" ,
"label" : "test" ,
"instance_label" : "test" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
2022-12-07 04:45:56 -06:00
State : eval . Pending ,
2021-11-26 11:58:19 -06:00
Results : [ ] state . Evaluation {
{
EvaluationTime : evaluationTime . Add ( 30 * time . Second ) ,
EvaluationState : eval . Alerting ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-11-26 11:58:19 -06:00
} ,
{
EvaluationTime : evaluationTime . Add ( 40 * time . Second ) ,
EvaluationState : eval . Error ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-11-26 11:58:19 -06:00
} ,
{
EvaluationTime : evaluationTime . Add ( 70 * time . Second ) ,
EvaluationState : eval . Alerting ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-11-26 11:58:19 -06:00
} ,
} ,
StartsAt : evaluationTime . Add ( 70 * time . Second ) ,
EndsAt : evaluationTime . Add ( 70 * time . Second ) . Add ( state . ResendDelay * 3 ) ,
LastEvaluationTime : evaluationTime . Add ( 70 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
Annotations : map [ string ] string { "annotation" : "test" } ,
} ,
} ,
} ,
{
desc : "normal -> alerting -> error -> no data - it should clear the error" ,
alertRule : & models . AlertRule {
OrgID : 1 ,
Title : "test_title" ,
UID : "test_alert_rule_uid_2" ,
NamespaceUID : "test_namespace_uid" ,
Annotations : map [ string ] string { "annotation" : "test" } ,
Labels : map [ string ] string { "label" : "test" } ,
IntervalSeconds : 10 ,
For : 30 * time . Second ,
NoDataState : models . NoData ,
} ,
evalResults : [ ] eval . Results {
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Normal ,
EvaluatedAt : evaluationTime ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Alerting ,
EvaluatedAt : evaluationTime . Add ( 30 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . Error ,
Error : fmt . Errorf ( "Failed to query data" ) ,
EvaluatedAt : evaluationTime . Add ( 40 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
{
eval . Result {
Instance : data . Labels { "instance_label" : "test" } ,
State : eval . NoData ,
EvaluatedAt : evaluationTime . Add ( 50 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
} ,
2022-05-23 03:49:49 -05:00
expectedAnnotations : 3 ,
2021-11-26 11:58:19 -06:00
expectedStates : map [ string ] * state . State {
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` : {
AlertRuleUID : "test_alert_rule_uid_2" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid_2"],["alertname","test_title"],["instance_label","test"],["label","test"]] ` ,
2021-11-26 11:58:19 -06:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid_2" ,
"alertname" : "test_title" ,
"label" : "test" ,
"instance_label" : "test" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
State : eval . NoData ,
2021-11-26 11:58:19 -06:00
Results : [ ] state . Evaluation {
{
EvaluationTime : evaluationTime . Add ( 30 * time . Second ) ,
EvaluationState : eval . Alerting ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-11-26 11:58:19 -06:00
} ,
{
EvaluationTime : evaluationTime . Add ( 40 * time . Second ) ,
EvaluationState : eval . Error ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-11-26 11:58:19 -06:00
} ,
{
EvaluationTime : evaluationTime . Add ( 50 * time . Second ) ,
EvaluationState : eval . NoData ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-11-26 11:58:19 -06:00
} ,
} ,
StartsAt : evaluationTime . Add ( 30 * time . Second ) ,
EndsAt : evaluationTime . Add ( 50 * time . Second ) . Add ( state . ResendDelay * 3 ) ,
LastEvaluationTime : evaluationTime . Add ( 50 * time . Second ) ,
EvaluationDuration : evaluationDuration ,
Annotations : map [ string ] string { "annotation" : "test" } ,
} ,
} ,
} ,
2021-06-03 12:24:36 -05:00
{
desc : "template is correctly expanded" ,
alertRule : & models . AlertRule {
OrgID : 1 ,
Title : "test_title" ,
UID : "test_alert_rule_uid" ,
NamespaceUID : "test_namespace_uid" ,
Annotations : map [ string ] string { "summary" : "{{$labels.pod}} is down in {{$labels.cluster}} cluster -> {{$labels.namespace}} namespace" } ,
Labels : map [ string ] string { "label" : "test" , "job" : "{{$labels.namespace}}/{{$labels.pod}}" } ,
IntervalSeconds : 10 ,
} ,
evalResults : [ ] eval . Results {
{
eval . Result {
Instance : data . Labels { "cluster" : "us-central-1" , "namespace" : "prod" , "pod" : "grafana" } ,
State : eval . Normal ,
EvaluatedAt : evaluationTime ,
EvaluationDuration : evaluationDuration ,
} ,
} ,
} ,
expectedStates : map [ string ] * state . State {
` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid"],["alertname","test_title"],["cluster","us-central-1"],["job","prod/grafana"],["label","test"],["namespace","prod"],["pod","grafana"]] ` : {
AlertRuleUID : "test_alert_rule_uid" ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","test_namespace_uid"],["__alert_rule_uid__","test_alert_rule_uid"],["alertname","test_title"],["cluster","us-central-1"],["job","prod/grafana"],["label","test"],["namespace","prod"],["pod","grafana"]] ` ,
2021-06-03 12:24:36 -05:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "test_namespace_uid" ,
"__alert_rule_uid__" : "test_alert_rule_uid" ,
"alertname" : "test_title" ,
"cluster" : "us-central-1" ,
"namespace" : "prod" ,
"pod" : "grafana" ,
"label" : "test" ,
"job" : "prod/grafana" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
State : eval . Normal ,
2021-06-03 12:24:36 -05:00
Results : [ ] state . Evaluation {
{
EvaluationTime : evaluationTime ,
EvaluationState : eval . Normal ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2021-06-03 12:24:36 -05:00
} ,
} ,
LastEvaluationTime : evaluationTime ,
EvaluationDuration : evaluationDuration ,
Annotations : map [ string ] string { "summary" : "grafana is down in us-central-1 cluster -> prod namespace" } ,
} ,
} ,
} ,
2021-03-24 17:34:18 -05:00
}
for _ , tc := range testCases {
2022-09-19 02:54:37 -05:00
fakeAnnoRepo := annotationstest . NewFakeAnnotationsRepo ( )
2023-03-06 10:40:37 -06:00
metrics := metrics . NewHistorianMetrics ( prometheus . NewRegistry ( ) )
hist := historian . NewAnnotationBackend ( fakeAnnoRepo , & dashboards . FakeDashboardService { } , nil , metrics )
2023-01-10 15:26:15 -06:00
cfg := state . ManagerCfg {
Metrics : testMetrics . GetStateMetrics ( ) ,
ExternalURL : nil ,
InstanceStore : & state . FakeInstanceStore { } ,
Images : & state . NotAvailableImageService { } ,
Clock : clock . New ( ) ,
Historian : hist ,
}
st := state . NewManager ( cfg )
2021-04-23 13:47:52 -05:00
t . Run ( tc . desc , func ( t * testing . T ) {
for _ , res := range tc . evalResults {
2022-07-14 14:59:59 -05:00
_ = st . ProcessEvalResults ( context . Background ( ) , evaluationTime , tc . alertRule , res , data . Labels {
"alertname" : tc . alertRule . Title ,
"__alert_rule_namespace_uid__" : tc . alertRule . NamespaceUID ,
"__alert_rule_uid__" : tc . alertRule . UID ,
} )
2021-04-23 13:47:52 -05:00
}
2021-11-04 14:15:56 -05:00
states := st . GetStatesForRuleUID ( tc . alertRule . OrgID , tc . alertRule . UID )
assert . Len ( t , states , len ( tc . expectedStates ) )
2021-05-04 11:57:50 -05:00
for _ , s := range tc . expectedStates {
2022-10-11 03:30:33 -05:00
cachedState := st . Get ( s . OrgID , s . AlertRuleUID , s . CacheID )
2021-04-23 14:32:25 -05:00
assert . Equal ( t , s , cachedState )
2021-04-02 10:11:33 -05:00
}
2021-12-01 05:04:54 -06:00
require . Eventuallyf ( t , func ( ) bool {
return tc . expectedAnnotations == fakeAnnoRepo . Len ( )
2022-09-19 02:54:37 -05:00
} , time . Second , 100 * time . Millisecond , "%d annotations are present, expected %d. We have %+v" , fakeAnnoRepo . Len ( ) , tc . expectedAnnotations , printAllAnnotations ( fakeAnnoRepo . Items ( ) ) )
2021-03-24 17:34:18 -05:00
} )
}
2022-08-18 08:40:33 -05:00
t . Run ( "should save state to database" , func ( t * testing . T ) {
2022-09-26 13:55:05 -05:00
instanceStore := & state . FakeInstanceStore { }
2022-08-18 08:40:33 -05:00
clk := clock . New ( )
2023-01-10 15:26:15 -06:00
cfg := state . ManagerCfg {
Metrics : testMetrics . GetStateMetrics ( ) ,
ExternalURL : nil ,
InstanceStore : instanceStore ,
Images : & state . NotAvailableImageService { } ,
Clock : clk ,
Historian : & state . FakeHistorian { } ,
}
st := state . NewManager ( cfg )
2022-08-18 08:40:33 -05:00
rule := models . AlertRuleGen ( ) ( )
var results = eval . GenerateResults ( rand . Intn ( 4 ) + 1 , eval . ResultGen ( eval . WithEvaluatedAt ( clk . Now ( ) ) ) )
states := st . ProcessEvalResults ( context . Background ( ) , clk . Now ( ) , rule , results , make ( data . Labels ) )
require . NotEmpty ( t , states )
2022-10-06 01:22:58 -05:00
savedStates := make ( map [ string ] models . AlertInstance )
2022-08-18 08:40:33 -05:00
for _ , op := range instanceStore . RecordedOps {
switch q := op . ( type ) {
2022-10-06 01:22:58 -05:00
case models . AlertInstance :
2022-08-18 08:40:33 -05:00
cacheId , err := q . Labels . StringKey ( )
require . NoError ( t , err )
savedStates [ cacheId ] = q
}
}
require . Len ( t , savedStates , len ( states ) )
for _ , s := range states {
2022-10-11 03:30:33 -05:00
require . Contains ( t , savedStates , s . CacheID )
2022-08-18 08:40:33 -05:00
}
} )
2021-03-24 17:34:18 -05:00
}
2021-07-26 11:12:04 -05:00
2022-09-19 02:54:37 -05:00
func printAllAnnotations ( annos map [ int64 ] annotations . Item ) string {
2022-05-23 03:49:49 -05:00
str := "["
for _ , anno := range annos {
2022-09-19 02:54:37 -05:00
str += fmt . Sprintf ( "%+v, " , anno )
2022-05-23 03:49:49 -05:00
}
str += "]"
return str
}
2021-07-26 11:12:04 -05:00
func TestStaleResultsHandler ( t * testing . T ) {
2022-06-21 17:16:53 -05:00
evaluationTime := time . Now ( )
2022-11-22 01:09:15 -06:00
interval := time . Minute
2021-07-26 11:12:04 -05:00
2022-02-08 02:52:03 -06:00
ctx := context . Background ( )
2021-08-25 08:11:22 -05:00
_ , dbstore := tests . SetupTestEnv ( t , 1 )
2021-07-26 11:12:04 -05:00
2021-09-29 09:16:40 -05:00
const mainOrgID int64 = 1
2022-06-21 17:16:53 -05:00
rule := tests . CreateTestAlertRule ( t , ctx , dbstore , int64 ( interval . Seconds ( ) ) , mainOrgID )
lastEval := evaluationTime . Add ( - 2 * interval )
2022-09-09 10:44:06 -05:00
2022-10-06 01:22:58 -05:00
labels1 := models . InstanceLabels { "test1" : "testValue1" }
_ , hash1 , _ := labels1 . StringAndHash ( )
labels2 := models . InstanceLabels { "test2" : "testValue2" }
_ , hash2 , _ := labels2 . StringAndHash ( )
instances := [ ] models . AlertInstance {
{
AlertInstanceKey : models . AlertInstanceKey {
RuleOrgID : rule . OrgID ,
RuleUID : rule . UID ,
LabelsHash : hash1 ,
} ,
CurrentState : models . InstanceStateNormal ,
Labels : labels1 ,
LastEvalTime : lastEval ,
CurrentStateSince : lastEval ,
CurrentStateEnd : lastEval . Add ( 3 * interval ) ,
} ,
{
AlertInstanceKey : models . AlertInstanceKey {
RuleOrgID : rule . OrgID ,
RuleUID : rule . UID ,
LabelsHash : hash2 ,
} ,
CurrentState : models . InstanceStateFiring ,
Labels : labels2 ,
LastEvalTime : lastEval ,
CurrentStateSince : lastEval ,
CurrentStateEnd : lastEval . Add ( 3 * interval ) ,
} ,
2022-09-09 10:44:06 -05:00
}
2022-10-06 01:22:58 -05:00
_ = dbstore . SaveAlertInstances ( ctx , instances ... )
2021-07-26 11:12:04 -05:00
testCases := [ ] struct {
desc string
evalResults [ ] eval . Results
expectedStates map [ string ] * state . State
startingStateCount int
finalStateCount int
} {
{
desc : "stale cache entries are removed" ,
evalResults : [ ] eval . Results {
{
eval . Result {
Instance : data . Labels { "test1" : "testValue1" } ,
State : eval . Normal ,
2022-06-21 17:16:53 -05:00
EvaluatedAt : evaluationTime ,
2021-07-26 11:12:04 -05:00
} ,
} ,
} ,
expectedStates : map [ string ] * state . State {
` [["__alert_rule_namespace_uid__","namespace"],["__alert_rule_uid__"," ` + rule . UID + ` "],["alertname"," ` + rule . Title + ` "],["test1","testValue1"]] ` : {
AlertRuleUID : rule . UID ,
OrgID : 1 ,
2022-10-11 03:30:33 -05:00
CacheID : ` [["__alert_rule_namespace_uid__","namespace"],["__alert_rule_uid__"," ` + rule . UID + ` "],["alertname"," ` + rule . Title + ` "],["test1","testValue1"]] ` ,
2021-07-26 11:12:04 -05:00
Labels : data . Labels {
"__alert_rule_namespace_uid__" : "namespace" ,
"__alert_rule_uid__" : rule . UID ,
"alertname" : rule . Title ,
"test1" : "testValue1" ,
} ,
2022-10-10 07:40:21 -05:00
Values : make ( map [ string ] float64 ) ,
State : eval . Normal ,
2021-07-26 11:12:04 -05:00
Results : [ ] state . Evaluation {
{
2022-06-21 17:16:53 -05:00
EvaluationTime : evaluationTime ,
2021-07-26 11:12:04 -05:00
EvaluationState : eval . Normal ,
2022-01-31 10:56:43 -06:00
Values : make ( map [ string ] * float64 ) ,
2022-04-05 13:36:42 -05:00
Condition : "A" ,
2021-07-26 11:12:04 -05:00
} ,
} ,
2022-06-21 17:16:53 -05:00
LastEvaluationTime : evaluationTime ,
2021-07-26 11:12:04 -05:00
EvaluationDuration : 0 ,
Annotations : map [ string ] string { "testAnnoKey" : "testAnnoValue" } ,
} ,
} ,
startingStateCount : 2 ,
finalStateCount : 1 ,
} ,
}
for _ , tc := range testCases {
2022-02-08 02:52:03 -06:00
ctx := context . Background ( )
2023-01-10 15:26:15 -06:00
cfg := state . ManagerCfg {
Metrics : testMetrics . GetStateMetrics ( ) ,
ExternalURL : nil ,
InstanceStore : dbstore ,
Images : & state . NoopImageService { } ,
Clock : clock . New ( ) ,
Historian : & state . FakeHistorian { } ,
}
st := state . NewManager ( cfg )
2022-11-04 13:23:08 -05:00
st . Warm ( ctx , dbstore )
2021-07-26 11:12:04 -05:00
existingStatesForRule := st . GetStatesForRuleUID ( rule . OrgID , rule . UID )
// We have loaded the expected number of entries from the db
assert . Equal ( t , tc . startingStateCount , len ( existingStatesForRule ) )
for _ , res := range tc . evalResults {
2022-06-21 17:16:53 -05:00
evalTime := evaluationTime
for _ , re := range res {
if re . EvaluatedAt . After ( evalTime ) {
evalTime = re . EvaluatedAt
}
}
2022-07-14 14:59:59 -05:00
st . ProcessEvalResults ( context . Background ( ) , evalTime , rule , res , data . Labels {
"alertname" : rule . Title ,
"__alert_rule_namespace_uid__" : rule . NamespaceUID ,
"__alert_rule_uid__" : rule . UID ,
} )
2021-07-26 11:12:04 -05:00
for _ , s := range tc . expectedStates {
2022-10-11 03:30:33 -05:00
cachedState := st . Get ( s . OrgID , s . AlertRuleUID , s . CacheID )
2021-07-26 11:12:04 -05:00
assert . Equal ( t , s , cachedState )
}
}
existingStatesForRule = st . GetStatesForRuleUID ( rule . OrgID , rule . UID )
// The expected number of state entries remains after results are processed
assert . Equal ( t , tc . finalStateCount , len ( existingStatesForRule ) )
}
}
2022-09-21 12:24:47 -05:00
func TestStaleResults ( t * testing . T ) {
getCacheID := func ( t * testing . T , rule * models . AlertRule , result eval . Result ) string {
t . Helper ( )
labels := data . Labels { }
for key , value := range rule . Labels {
labels [ key ] = value
}
for key , value := range result . Instance {
labels [ key ] = value
}
lbls := models . InstanceLabels ( labels )
key , err := lbls . StringKey ( )
require . NoError ( t , err )
return key
}
2022-12-06 12:07:39 -06:00
checkExpectedStates := func ( t * testing . T , actual [ ] * state . State , expected map [ string ] struct { } ) map [ string ] * state . State {
t . Helper ( )
result := make ( map [ string ] * state . State )
require . Len ( t , actual , len ( expected ) )
for _ , currentState := range actual {
_ , ok := expected [ currentState . CacheID ]
result [ currentState . CacheID ] = currentState
require . Truef ( t , ok , "State %s is not expected. States: %v" , currentState . CacheID , expected )
}
return result
}
checkExpectedStateTransitions := func ( t * testing . T , actual [ ] state . StateTransition , expected map [ string ] struct { } ) {
2022-09-21 12:24:47 -05:00
t . Helper ( )
require . Len ( t , actual , len ( expected ) )
for _ , currentState := range actual {
2022-10-11 03:30:33 -05:00
_ , ok := expected [ currentState . CacheID ]
require . Truef ( t , ok , "State %s is not expected. States: %v" , currentState . CacheID , expected )
2022-09-21 12:24:47 -05:00
}
}
2022-12-06 12:07:39 -06:00
ctx := context . Background ( )
clk := clock . NewMock ( )
2022-09-21 12:24:47 -05:00
2022-12-06 12:07:39 -06:00
store := & state . FakeInstanceStore { }
2022-09-21 12:24:47 -05:00
2023-01-10 15:26:15 -06:00
cfg := state . ManagerCfg {
Metrics : testMetrics . GetStateMetrics ( ) ,
ExternalURL : nil ,
InstanceStore : store ,
Images : & state . NoopImageService { } ,
Clock : clk ,
Historian : & state . FakeHistorian { } ,
}
st := state . NewManager ( cfg )
2022-09-21 12:24:47 -05:00
2022-12-06 12:07:39 -06:00
rule := models . AlertRuleGen ( models . WithFor ( 0 ) ) ( )
2022-09-21 12:24:47 -05:00
2022-12-06 12:07:39 -06:00
initResults := eval . Results {
eval . ResultGen ( eval . WithEvaluatedAt ( clk . Now ( ) ) ) ( ) ,
eval . ResultGen ( eval . WithState ( eval . Alerting ) , eval . WithEvaluatedAt ( clk . Now ( ) ) ) ( ) ,
eval . ResultGen ( eval . WithState ( eval . Normal ) , eval . WithEvaluatedAt ( clk . Now ( ) ) ) ( ) ,
}
2022-09-21 12:24:47 -05:00
2022-12-06 12:07:39 -06:00
state1 := getCacheID ( t , rule , initResults [ 0 ] )
state2 := getCacheID ( t , rule , initResults [ 1 ] )
state3 := getCacheID ( t , rule , initResults [ 2 ] )
2022-09-21 12:24:47 -05:00
2022-12-06 12:07:39 -06:00
initStates := map [ string ] struct { } {
state1 : { } ,
state2 : { } ,
state3 : { } ,
}
// Init
processed := st . ProcessEvalResults ( ctx , clk . Now ( ) , rule , initResults , nil )
checkExpectedStateTransitions ( t , processed , initStates )
currentStates := st . GetStatesForRuleUID ( rule . OrgID , rule . UID )
statesMap := checkExpectedStates ( t , currentStates , initStates )
require . Equal ( t , eval . Alerting , statesMap [ state2 ] . State ) // make sure the state is alerting because we need it to be resolved later
staleDuration := 2 * time . Duration ( rule . IntervalSeconds ) * time . Second
clk . Add ( staleDuration )
result := initResults [ 0 ]
result . EvaluatedAt = clk . Now ( )
results := eval . Results {
result ,
}
var expectedStaleKeys [ ] models . AlertInstanceKey
t . Run ( "should mark missing states as stale" , func ( t * testing . T ) {
2022-09-21 12:24:47 -05:00
processed = st . ProcessEvalResults ( ctx , clk . Now ( ) , rule , results , nil )
2022-12-06 12:07:39 -06:00
checkExpectedStateTransitions ( t , processed , initStates )
2022-09-21 12:24:47 -05:00
for _ , s := range processed {
2022-12-06 12:07:39 -06:00
if s . CacheID == state1 {
continue
}
assert . Equal ( t , eval . Normal , s . State . State )
assert . Equal ( t , models . StateReasonMissingSeries , s . StateReason )
assert . Equal ( t , clk . Now ( ) , s . EndsAt )
if s . CacheID == state2 {
2022-09-21 12:24:47 -05:00
assert . Truef ( t , s . Resolved , "Returned stale state should have Resolved set to true" )
}
2022-12-06 12:07:39 -06:00
key , err := s . GetAlertInstanceKey ( )
require . NoError ( t , err )
expectedStaleKeys = append ( expectedStaleKeys , key )
2022-09-21 12:24:47 -05:00
}
2022-12-06 12:07:39 -06:00
} )
t . Run ( "should remove stale states from cache" , func ( t * testing . T ) {
currentStates = st . GetStatesForRuleUID ( rule . OrgID , rule . UID )
2022-09-21 12:24:47 -05:00
checkExpectedStates ( t , currentStates , map [ string ] struct { } {
getCacheID ( t , rule , results [ 0 ] ) : { } ,
} )
} )
2022-12-06 12:07:39 -06:00
t . Run ( "should delete stale states from the database" , func ( t * testing . T ) {
for _ , op := range store . RecordedOps {
switch q := op . ( type ) {
case state . FakeInstanceStoreOp :
keys , ok := q . Args [ 1 ] . ( [ ] models . AlertInstanceKey )
require . Truef ( t , ok , "Failed to parse fake store operations" )
require . Len ( t , keys , 2 )
require . EqualValues ( t , expectedStaleKeys , keys )
}
}
} )
2022-09-21 12:24:47 -05:00
}
2023-01-26 11:29:10 -06:00
func TestDeleteStateByRuleUID ( t * testing . T ) {
interval := time . Minute
ctx := context . Background ( )
_ , dbstore := tests . SetupTestEnv ( t , 1 )
const mainOrgID int64 = 1
rule := tests . CreateTestAlertRule ( t , ctx , dbstore , int64 ( interval . Seconds ( ) ) , mainOrgID )
labels1 := models . InstanceLabels { "test1" : "testValue1" }
_ , hash1 , _ := labels1 . StringAndHash ( )
labels2 := models . InstanceLabels { "test2" : "testValue2" }
_ , hash2 , _ := labels2 . StringAndHash ( )
instances := [ ] models . AlertInstance {
{
AlertInstanceKey : models . AlertInstanceKey {
RuleOrgID : rule . OrgID ,
RuleUID : rule . UID ,
LabelsHash : hash1 ,
} ,
CurrentState : models . InstanceStateNormal ,
Labels : labels1 ,
} ,
{
AlertInstanceKey : models . AlertInstanceKey {
RuleOrgID : rule . OrgID ,
RuleUID : rule . UID ,
LabelsHash : hash2 ,
} ,
CurrentState : models . InstanceStateFiring ,
Labels : labels2 ,
} ,
}
_ = dbstore . SaveAlertInstances ( ctx , instances ... )
testCases := [ ] struct {
desc string
instanceStore state . InstanceStore
expectedStates map [ string ] * state . State
startingStateCacheCount int
finalStateCacheCount int
startingInstanceDBCount int
finalInstanceDBCount int
} {
{
desc : "all states/instances are removed from cache and DB" ,
instanceStore : dbstore ,
expectedStates : map [ string ] * state . State {
` [["test1","testValue1"]] ` : {
AlertRuleUID : rule . UID ,
OrgID : 1 ,
CacheID : ` [["test1","testValue1"]] ` ,
Labels : data . Labels { "test1" : "testValue1" } ,
State : eval . Normal ,
EvaluationDuration : 0 ,
Annotations : map [ string ] string { "testAnnoKey" : "testAnnoValue" } ,
} ,
` [["test2","testValue2"]] ` : {
AlertRuleUID : rule . UID ,
OrgID : 1 ,
CacheID : ` [["test2","testValue2"]] ` ,
Labels : data . Labels { "test2" : "testValue2" } ,
State : eval . Alerting ,
EvaluationDuration : 0 ,
Annotations : map [ string ] string { "testAnnoKey" : "testAnnoValue" } ,
} ,
} ,
startingStateCacheCount : 2 ,
finalStateCacheCount : 0 ,
startingInstanceDBCount : 2 ,
finalInstanceDBCount : 0 ,
} ,
}
for _ , tc := range testCases {
t . Run ( tc . desc , func ( t * testing . T ) {
ctx := context . Background ( )
2023-01-27 02:46:21 -06:00
clk := clock . NewMock ( )
clk . Set ( time . Now ( ) )
2023-01-26 11:29:10 -06:00
cfg := state . ManagerCfg {
Metrics : testMetrics . GetStateMetrics ( ) ,
ExternalURL : nil ,
InstanceStore : dbstore ,
Images : & state . NoopImageService { } ,
2023-01-27 02:46:21 -06:00
Clock : clk ,
2023-01-26 11:29:10 -06:00
Historian : & state . FakeHistorian { } ,
}
st := state . NewManager ( cfg )
st . Warm ( ctx , dbstore )
q := & models . ListAlertInstancesQuery { RuleOrgID : rule . OrgID , RuleUID : rule . UID }
2023-03-28 03:34:35 -05:00
alerts , _ := dbstore . ListAlertInstances ( ctx , q )
2023-01-26 11:29:10 -06:00
existingStatesForRule := st . GetStatesForRuleUID ( rule . OrgID , rule . UID )
// We have loaded the expected number of entries from the db
assert . Equal ( t , tc . startingStateCacheCount , len ( existingStatesForRule ) )
2023-03-28 03:34:35 -05:00
assert . Equal ( t , tc . startingInstanceDBCount , len ( alerts ) )
2023-01-26 11:29:10 -06:00
2023-01-27 02:46:21 -06:00
expectedReason := util . GenerateShortUID ( )
transitions := st . DeleteStateByRuleUID ( ctx , rule . GetKey ( ) , expectedReason )
2023-01-26 11:29:10 -06:00
// Check that the deleted states are the same as the ones that were in cache
2023-01-27 02:46:21 -06:00
assert . Equal ( t , tc . startingStateCacheCount , len ( transitions ) )
for _ , s := range transitions {
assert . Contains ( t , tc . expectedStates , s . CacheID )
oldState := tc . expectedStates [ s . CacheID ]
assert . Equal ( t , oldState . State , s . PreviousState )
assert . Equal ( t , oldState . StateReason , s . PreviousStateReason )
assert . Equal ( t , eval . Normal , s . State . State )
assert . Equal ( t , expectedReason , s . StateReason )
if oldState . State == eval . Normal {
assert . Equal ( t , oldState . StartsAt , s . StartsAt )
assert . False ( t , s . Resolved )
} else {
assert . Equal ( t , clk . Now ( ) , s . StartsAt )
if oldState . State == eval . Alerting {
assert . True ( t , s . Resolved )
}
}
assert . Equal ( t , clk . Now ( ) , s . EndsAt )
2023-01-26 11:29:10 -06:00
}
q = & models . ListAlertInstancesQuery { RuleOrgID : rule . OrgID , RuleUID : rule . UID }
2023-03-28 03:34:35 -05:00
alertInstances , _ := dbstore . ListAlertInstances ( ctx , q )
2023-01-26 11:29:10 -06:00
existingStatesForRule = st . GetStatesForRuleUID ( rule . OrgID , rule . UID )
// The expected number of state entries remains after states are deleted
assert . Equal ( t , tc . finalStateCacheCount , len ( existingStatesForRule ) )
2023-03-28 03:34:35 -05:00
assert . Equal ( t , tc . finalInstanceDBCount , len ( alertInstances ) )
2023-01-26 11:29:10 -06:00
} )
}
}
func TestResetStateByRuleUID ( t * testing . T ) {
interval := time . Minute
ctx := context . Background ( )
_ , dbstore := tests . SetupTestEnv ( t , 1 )
const mainOrgID int64 = 1
rule := tests . CreateTestAlertRule ( t , ctx , dbstore , int64 ( interval . Seconds ( ) ) , mainOrgID )
labels1 := models . InstanceLabels { "test1" : "testValue1" }
_ , hash1 , _ := labels1 . StringAndHash ( )
labels2 := models . InstanceLabels { "test2" : "testValue2" }
_ , hash2 , _ := labels2 . StringAndHash ( )
instances := [ ] models . AlertInstance {
{
AlertInstanceKey : models . AlertInstanceKey {
RuleOrgID : rule . OrgID ,
RuleUID : rule . UID ,
LabelsHash : hash1 ,
} ,
CurrentState : models . InstanceStateNormal ,
Labels : labels1 ,
} ,
{
AlertInstanceKey : models . AlertInstanceKey {
RuleOrgID : rule . OrgID ,
RuleUID : rule . UID ,
LabelsHash : hash2 ,
} ,
CurrentState : models . InstanceStateFiring ,
Labels : labels2 ,
} ,
}
_ = dbstore . SaveAlertInstances ( ctx , instances ... )
testCases := [ ] struct {
desc string
instanceStore state . InstanceStore
expectedStates map [ string ] * state . State
startingStateCacheCount int
finalStateCacheCount int
startingInstanceDBCount int
finalInstanceDBCount int
newHistorianEntriesCount int
} {
{
desc : "all states/instances are removed from cache and DB and saved in historian" ,
instanceStore : dbstore ,
expectedStates : map [ string ] * state . State {
` [["test1","testValue1"]] ` : {
AlertRuleUID : rule . UID ,
OrgID : 1 ,
CacheID : ` [["test1","testValue1"]] ` ,
Labels : data . Labels { "test1" : "testValue1" } ,
State : eval . Normal ,
EvaluationDuration : 0 ,
Annotations : map [ string ] string { "testAnnoKey" : "testAnnoValue" } ,
} ,
` [["test2","testValue2"]] ` : {
AlertRuleUID : rule . UID ,
OrgID : 1 ,
CacheID : ` [["test2","testValue2"]] ` ,
Labels : data . Labels { "test2" : "testValue2" } ,
State : eval . Alerting ,
EvaluationDuration : 0 ,
Annotations : map [ string ] string { "testAnnoKey" : "testAnnoValue" } ,
} ,
} ,
startingStateCacheCount : 2 ,
finalStateCacheCount : 0 ,
startingInstanceDBCount : 2 ,
finalInstanceDBCount : 0 ,
newHistorianEntriesCount : 2 ,
} ,
}
for _ , tc := range testCases {
t . Run ( tc . desc , func ( t * testing . T ) {
ctx := context . Background ( )
fakeHistorian := & state . FakeHistorian { StateTransitions : make ( [ ] state . StateTransition , 0 ) }
2023-01-27 02:46:21 -06:00
clk := clock . NewMock ( )
clk . Set ( time . Now ( ) )
2023-01-26 11:29:10 -06:00
cfg := state . ManagerCfg {
Metrics : testMetrics . GetStateMetrics ( ) ,
ExternalURL : nil ,
InstanceStore : dbstore ,
Images : & state . NoopImageService { } ,
2023-01-27 02:46:21 -06:00
Clock : clk ,
2023-01-26 11:29:10 -06:00
Historian : fakeHistorian ,
}
st := state . NewManager ( cfg )
st . Warm ( ctx , dbstore )
q := & models . ListAlertInstancesQuery { RuleOrgID : rule . OrgID , RuleUID : rule . UID }
2023-03-28 03:34:35 -05:00
alerts , _ := dbstore . ListAlertInstances ( ctx , q )
2023-01-26 11:29:10 -06:00
existingStatesForRule := st . GetStatesForRuleUID ( rule . OrgID , rule . UID )
// We have loaded the expected number of entries from the db
assert . Equal ( t , tc . startingStateCacheCount , len ( existingStatesForRule ) )
2023-03-28 03:34:35 -05:00
assert . Equal ( t , tc . startingInstanceDBCount , len ( alerts ) )
2023-01-26 11:29:10 -06:00
2023-01-27 02:46:21 -06:00
transitions := st . ResetStateByRuleUID ( ctx , rule , models . StateReasonPaused )
2023-01-26 11:29:10 -06:00
// Check that the deleted states are the same as the ones that were in cache
2023-01-27 02:46:21 -06:00
assert . Equal ( t , tc . startingStateCacheCount , len ( transitions ) )
for _ , s := range transitions {
assert . Contains ( t , tc . expectedStates , s . CacheID )
oldState := tc . expectedStates [ s . CacheID ]
assert . Equal ( t , oldState . State , s . PreviousState )
assert . Equal ( t , oldState . StateReason , s . PreviousStateReason )
assert . Equal ( t , eval . Normal , s . State . State )
assert . Equal ( t , models . StateReasonPaused , s . StateReason )
if oldState . State == eval . Normal {
assert . Equal ( t , oldState . StartsAt , s . StartsAt )
assert . False ( t , s . Resolved )
} else {
assert . Equal ( t , clk . Now ( ) , s . StartsAt )
if oldState . State == eval . Alerting {
assert . True ( t , s . Resolved )
}
}
assert . Equal ( t , clk . Now ( ) , s . EndsAt )
2023-01-26 11:29:10 -06:00
}
// Check if both entries have been added to the historian
assert . Equal ( t , tc . newHistorianEntriesCount , len ( fakeHistorian . StateTransitions ) )
2023-01-27 02:46:21 -06:00
assert . Equal ( t , transitions , fakeHistorian . StateTransitions )
2023-01-26 11:29:10 -06:00
q = & models . ListAlertInstancesQuery { RuleOrgID : rule . OrgID , RuleUID : rule . UID }
2023-03-28 03:34:35 -05:00
alertInstances , _ := dbstore . ListAlertInstances ( ctx , q )
2023-01-26 11:29:10 -06:00
existingStatesForRule = st . GetStatesForRuleUID ( rule . OrgID , rule . UID )
// The expected number of state entries remains after states are deleted
assert . Equal ( t , tc . finalStateCacheCount , len ( existingStatesForRule ) )
2023-03-28 03:34:35 -05:00
assert . Equal ( t , tc . finalInstanceDBCount , len ( alertInstances ) )
2023-01-26 11:29:10 -06:00
} )
}
}