@@ -19,6 +19,7 @@ import (
19
19
"fmt"
20
20
"io"
21
21
"reflect"
22
+ "strings"
22
23
"testing"
23
24
"time"
24
25
@@ -936,97 +937,96 @@ func TestTimeMuteStage(t *testing.T) {
936
937
}
937
938
938
939
func TestTimeActiveStage (t * testing.T ) {
939
- // Route mutes alerts inside business hours if it is an active time interval
940
- muteIn := `
941
- ---
942
- - weekdays: ['monday:friday']
943
- times:
944
- - start_time: '00:00'
945
- end_time: '09:00'
946
- - start_time: '17:00'
947
- end_time: '24:00'
948
- - weekdays: ['saturday', 'sunday']`
949
-
950
- cases := []struct {
951
- fireTime string
952
- labels model.LabelSet
953
- shouldMute bool
954
- }{
955
- {
956
- // Friday during business hours
957
- fireTime : "01 Jan 21 09:00 +0000" ,
958
- labels : model.LabelSet {"mute" : "me" },
959
- shouldMute : true ,
960
- },
961
- {
962
- fireTime : "02 Dec 20 16:59 +0000" ,
963
- labels : model.LabelSet {"mute" : "me" },
964
- shouldMute : true ,
965
- },
966
- {
967
- // Tuesday before 5pm
968
- fireTime : "01 Dec 20 16:59 +0000" ,
969
- labels : model.LabelSet {"mute" : "me" },
970
- shouldMute : true ,
971
- },
972
- {
973
- // Saturday
974
- fireTime : "17 Oct 20 10:00 +0000" ,
975
- labels : model.LabelSet {"foo" : "bar" },
976
- shouldMute : false ,
977
- },
978
- {
979
- // Wednesday before 9am
980
- fireTime : "14 Oct 20 05:00 +0000" ,
981
- labels : model.LabelSet {"dont" : "mute" },
982
- shouldMute : false ,
983
- },
984
- }
985
- var intervals []timeinterval.TimeInterval
986
- err := yaml .Unmarshal ([]byte (muteIn ), & intervals )
940
+ sydney , err := time .LoadLocation ("Australia/Sydney" )
987
941
if err != nil {
988
- t .Fatalf ("Couldn't unmarshal time interval %s" , err )
989
- }
990
- m := map [string ][]timeinterval.TimeInterval {"test" : intervals }
991
- intervener := timeinterval .NewIntervener (m )
992
- metrics := NewMetrics (prometheus .NewRegistry (), featurecontrol.NoopFlags {})
993
- stage := NewTimeActiveStage (intervener , metrics )
994
-
995
- outAlerts := []* types.Alert {}
996
- nonMuteCount := 0
997
- for _ , tc := range cases {
998
- now , err := time .Parse (time .RFC822Z , tc .fireTime )
999
- if err != nil {
1000
- t .Fatalf ("Couldn't parse fire time %s %s" , tc .fireTime , err )
1001
- }
1002
- // Count alerts with shouldMute == false and compare to ensure none are muted incorrectly
1003
- if ! tc .shouldMute {
1004
- nonMuteCount ++
1005
- }
1006
- a := model.Alert {Labels : tc .labels }
1007
- alerts := []* types.Alert {{Alert : a }}
1008
- ctx := context .Background ()
1009
- ctx = WithNow (ctx , now )
1010
- ctx = WithActiveTimeIntervals (ctx , []string {"test" })
1011
- ctx = WithMuteTimeIntervals (ctx , []string {})
942
+ t .Fatalf ("Failed to load location Australia/Sydney: %s" , err )
943
+ }
944
+ weekdays := map [string ][]timeinterval.TimeInterval {
945
+ "weekdays" : {{
946
+ Weekdays : []timeinterval.WeekdayRange {{
947
+ InclusiveRange : timeinterval.InclusiveRange {
948
+ Begin : 1 , // Monday
949
+ End : 5 , // Friday
950
+ },
951
+ }},
952
+ Times : []timeinterval.TimeRange {{
953
+ StartMinute : 540 , // 09:00
954
+ EndMinute : 1020 , // 17:00
955
+ }},
956
+ Location : & timeinterval.Location {Location : sydney },
957
+ }},
958
+ }
959
+
960
+ tests := []struct {
961
+ name string
962
+ intervals map [string ][]timeinterval.TimeInterval
963
+ now time.Time
964
+ alerts []* types.Alert
965
+ mutedBy []string
966
+ }{{
967
+ name : "Should be muted outside working hours" ,
968
+ intervals : weekdays ,
969
+ now : time .Date (2024 , 1 , 1 , 0 , 0 , 0 , 0 , sydney ),
970
+ alerts : []* types.Alert {{Alert : model.Alert {Labels : model.LabelSet {"foo" : "bar" }}}},
971
+ mutedBy : []string {"weekdays" },
972
+ }, {
973
+ name : "Should not be muted during workings hours" ,
974
+ intervals : weekdays ,
975
+ now : time .Date (2024 , 1 , 1 , 9 , 0 , 0 , 0 , sydney ),
976
+ alerts : []* types.Alert {{Alert : model.Alert {Labels : model.LabelSet {"foo" : "bar" }}}},
977
+ mutedBy : nil ,
978
+ }, {
979
+ name : "Should be muted during weekends" ,
980
+ intervals : weekdays ,
981
+ now : time .Date (2024 , 1 , 6 , 10 , 0 , 0 , 0 , sydney ),
982
+ alerts : []* types.Alert {{Alert : model.Alert {Labels : model.LabelSet {"foo" : "bar" }}}},
983
+ mutedBy : []string {"weekdays" },
984
+ }, {
985
+ name : "Should be muted at 12pm UTC" ,
986
+ intervals : weekdays ,
987
+ now : time .Date (2024 , 1 , 6 , 10 , 0 , 0 , 0 , time .UTC ),
988
+ alerts : []* types.Alert {{Alert : model.Alert {Labels : model.LabelSet {"foo" : "bar" }}}},
989
+ mutedBy : []string {"weekdays" },
990
+ }}
991
+
992
+ for _ , test := range tests {
993
+ t .Run (test .name , func (t * testing.T ) {
994
+ r := prometheus .NewRegistry ()
995
+ metrics := NewMetrics (r , featurecontrol.NoopFlags {})
996
+ intervener := timeinterval .NewIntervener (test .intervals )
997
+ st := NewTimeActiveStage (intervener , metrics )
998
+
999
+ // Get the names of all time intervals for the context.
1000
+ activeTimeIntervalNames := make ([]string , 0 , len (test .intervals ))
1001
+ for name := range test .intervals {
1002
+ activeTimeIntervalNames = append (activeTimeIntervalNames , name )
1003
+ }
1012
1004
1013
- _ , out , err := stage .Exec (ctx , log .NewNopLogger (), alerts ... )
1014
- if err != nil {
1015
- t .Fatalf ("Unexpected error in time mute stage %s" , err )
1016
- }
1017
- outAlerts = append (outAlerts , out ... )
1018
- }
1019
- for _ , alert := range outAlerts {
1020
- if _ , ok := alert .Alert .Labels ["mute" ]; ok {
1021
- t .Fatalf ("Expected alert to be muted %+v" , alert .Alert )
1022
- }
1023
- }
1024
- if len (outAlerts ) != nonMuteCount {
1025
- t .Fatalf ("Expected %d alerts after time mute stage but got %d" , nonMuteCount , len (outAlerts ))
1026
- }
1027
- suppressed := int (prom_testutil .ToFloat64 (metrics .numNotificationSuppressedTotal ))
1028
- if (len (cases ) - nonMuteCount ) != suppressed {
1029
- t .Fatalf ("Expected %d alerts counted in suppressed metric but got %d" , (len (cases ) - nonMuteCount ), suppressed )
1005
+ ctx := context .Background ()
1006
+ ctx = WithNow (ctx , test .now )
1007
+ ctx = WithActiveTimeIntervals (ctx , activeTimeIntervalNames )
1008
+ ctx = WithMuteTimeIntervals (ctx , nil )
1009
+
1010
+ _ , active , err := st .Exec (ctx , log .NewNopLogger (), test .alerts ... )
1011
+ require .NoError (t , err )
1012
+
1013
+ if len (test .mutedBy ) == 0 {
1014
+ // All alerts should be active.
1015
+ require .Equal (t , len (test .alerts ), len (active ))
1016
+ // The metric for total suppressed notifications should not
1017
+ // have been incremented, which means it will not be collected.
1018
+ require .NoError (t , prom_testutil .GatherAndCompare (r , strings .NewReader ("" )))
1019
+ } else {
1020
+ // All alerts should be muted.
1021
+ require .Empty (t , active )
1022
+ // Gets the metric for total suppressed notifications.
1023
+ require .NoError (t , prom_testutil .GatherAndCompare (r , strings .NewReader (fmt .Sprintf (`
1024
+ # HELP alertmanager_notifications_suppressed_total The total number of notifications suppressed for being silenced, inhibited, outside of active time intervals or within muted time intervals.
1025
+ # TYPE alertmanager_notifications_suppressed_total counter
1026
+ alertmanager_notifications_suppressed_total{reason="active_time_interval"} %d
1027
+ ` , len (test .alerts )))))
1028
+ }
1029
+ })
1030
1030
}
1031
1031
}
1032
1032
0 commit comments