@@ -28,7 +28,6 @@ import (
2828 prom_testutil "github.com/prometheus/client_golang/prometheus/testutil"
2929 "github.com/prometheus/common/model"
3030 "github.com/stretchr/testify/require"
31- "gopkg.in/yaml.v2"
3231
3332 "github.com/prometheus/alertmanager/featurecontrol"
3433 "github.com/prometheus/alertmanager/nflog"
@@ -822,117 +821,107 @@ func TestMuteStageWithSilences(t *testing.T) {
822821}
823822
824823func TestTimeMuteStage (t * testing.T ) {
825- // Route mutes alerts outside business hours in November, using the +1100 timezone.
826- muteIn := `
827- ---
828- - weekdays: ['monday:friday']
829- location: 'Australia/Sydney'
830- months: ['November']
831- times:
832- - start_time: '00:00'
833- end_time: '09:00'
834- - start_time: '17:00'
835- end_time: '24:00'
836- - weekdays: ['saturday', 'sunday']
837- months: ['November']
838- location: 'Australia/Sydney'`
839-
840- cases := []struct {
841- fireTime string
842- labels model.LabelSet
843- shouldMute bool
844- }{
845- {
846- // Friday during business hours
847- fireTime : "19 Nov 21 13:00 +1100" ,
848- labels : model.LabelSet {"foo" : "bar" },
849- shouldMute : false ,
850- },
851- {
852- // Tuesday before 5pm
853- fireTime : "16 Nov 21 16:59 +1100" ,
854- labels : model.LabelSet {"dont" : "mute" },
855- shouldMute : false ,
856- },
857- {
858- // Saturday
859- fireTime : "20 Nov 21 10:00 +1100" ,
860- labels : model.LabelSet {"mute" : "me" },
861- shouldMute : true ,
862- },
863- {
864- // Wednesday before 9am
865- fireTime : "17 Nov 21 05:00 +1100" ,
866- labels : model.LabelSet {"mute" : "me" },
867- shouldMute : true ,
868- },
869- {
870- // Ensure comparisons with other time zones work as expected.
871- fireTime : "14 Nov 21 20:00 +0900" ,
872- labels : model.LabelSet {"mute" : "kst" },
873- shouldMute : true ,
874- },
875- {
876- fireTime : "14 Nov 21 21:30 +0000" ,
877- labels : model.LabelSet {"mute" : "utc" },
878- shouldMute : true ,
879- },
880- {
881- fireTime : "15 Nov 22 14:30 +0900" ,
882- labels : model.LabelSet {"kst" : "dont_mute" },
883- shouldMute : false ,
884- },
885- {
886- fireTime : "15 Nov 21 02:00 -0500" ,
887- labels : model.LabelSet {"mute" : "0500" },
888- shouldMute : true ,
889- },
890- }
891- var intervals []timeinterval.TimeInterval
892- err := yaml .Unmarshal ([]byte (muteIn ), & intervals )
824+ sydney , err := time .LoadLocation ("Australia/Sydney" )
893825 if err != nil {
894- t .Fatalf ("Couldn't unmarshal time interval %s" , err )
895- }
896- m := map [string ][]timeinterval.TimeInterval {"test" : intervals }
897- intervener := timeinterval .NewIntervener (m )
898- metrics := NewMetrics (prometheus .NewRegistry (), featurecontrol.NoopFlags {})
899- stage := NewTimeMuteStage (intervener , metrics )
900-
901- outAlerts := []* types.Alert {}
902- nonMuteCount := 0
903- for _ , tc := range cases {
904- now , err := time .Parse (time .RFC822Z , tc .fireTime )
905- if err != nil {
906- t .Fatalf ("Couldn't parse fire time %s %s" , tc .fireTime , err )
907- }
908- // Count alerts with shouldMute == false and compare to ensure none are muted incorrectly
909- if ! tc .shouldMute {
910- nonMuteCount ++
911- }
912- a := model.Alert {Labels : tc .labels }
913- alerts := []* types.Alert {{Alert : a }}
914- ctx := context .Background ()
915- ctx = WithNow (ctx , now )
916- ctx = WithActiveTimeIntervals (ctx , []string {})
917- ctx = WithMuteTimeIntervals (ctx , []string {"test" })
918-
919- _ , out , err := stage .Exec (ctx , log .NewNopLogger (), alerts ... )
920- if err != nil {
921- t .Fatalf ("Unexpected error in time mute stage %s" , err )
922- }
923- outAlerts = append (outAlerts , out ... )
924- }
925- for _ , alert := range outAlerts {
926- if _ , ok := alert .Alert .Labels ["mute" ]; ok {
927- t .Fatalf ("Expected alert to be muted %+v" , alert .Alert )
928- }
826+ t .Fatalf ("Failed to load location Australia/Sydney: %s" , err )
929827 }
930- if len (outAlerts ) != nonMuteCount {
931- t .Fatalf ("Expected %d alerts after time mute stage but got %d" , nonMuteCount , len (outAlerts ))
828+ eveningsAndWeekends := map [string ][]timeinterval.TimeInterval {
829+ "evenings" : {{
830+ Weekdays : []timeinterval.WeekdayRange {{
831+ InclusiveRange : timeinterval.InclusiveRange {
832+ Begin : 1 , // Monday
833+ End : 5 , // Friday
834+ },
835+ }},
836+ Times : []timeinterval.TimeRange {{
837+ StartMinute : 0 , // 00:00
838+ EndMinute : 540 , // 09:00
839+ }, {
840+ StartMinute : 1020 , // 17:00
841+ EndMinute : 1440 , // 24:00
842+ }},
843+ Location : & timeinterval.Location {Location : sydney },
844+ }},
845+ "weekends" : {{
846+ Weekdays : []timeinterval.WeekdayRange {{
847+ InclusiveRange : timeinterval.InclusiveRange {Begin : 6 , End : 6 }, // Saturday
848+ }, {
849+ InclusiveRange : timeinterval.InclusiveRange {Begin : 0 , End : 0 }, // Sunday
850+ }},
851+ Location : & timeinterval.Location {Location : sydney },
852+ }},
932853 }
933- suppressed := int (prom_testutil .ToFloat64 (metrics .numNotificationSuppressedTotal ))
934- if (len (cases ) - nonMuteCount ) != suppressed {
935- t .Fatalf ("Expected %d alerts counted in suppressed metric but got %d" , (len (cases ) - nonMuteCount ), suppressed )
854+
855+ tests := []struct {
856+ name string
857+ intervals map [string ][]timeinterval.TimeInterval
858+ now time.Time
859+ alerts []* types.Alert
860+ mutedBy []string
861+ }{{
862+ name : "Should be muted outside working hours" ,
863+ intervals : eveningsAndWeekends ,
864+ now : time .Date (2024 , 1 , 1 , 0 , 0 , 0 , 0 , sydney ),
865+ alerts : []* types.Alert {{Alert : model.Alert {Labels : model.LabelSet {"foo" : "bar" }}}},
866+ mutedBy : []string {"evenings" },
867+ }, {
868+ name : "Should not be muted during workings hours" ,
869+ intervals : eveningsAndWeekends ,
870+ now : time .Date (2024 , 1 , 1 , 9 , 0 , 0 , 0 , sydney ),
871+ alerts : []* types.Alert {{Alert : model.Alert {Labels : model.LabelSet {"foo" : "bar" }}}},
872+ mutedBy : nil ,
873+ }, {
874+ name : "Should be muted during weekends" ,
875+ intervals : eveningsAndWeekends ,
876+ now : time .Date (2024 , 1 , 6 , 10 , 0 , 0 , 0 , sydney ),
877+ alerts : []* types.Alert {{Alert : model.Alert {Labels : model.LabelSet {"foo" : "bar" }}}},
878+ mutedBy : []string {"weekends" },
879+ }, {
880+ name : "Should be muted at 12pm UTC" ,
881+ intervals : eveningsAndWeekends ,
882+ now : time .Date (2024 , 1 , 6 , 10 , 0 , 0 , 0 , time .UTC ),
883+ alerts : []* types.Alert {{Alert : model.Alert {Labels : model.LabelSet {"foo" : "bar" }}}},
884+ mutedBy : []string {"evenings" },
885+ }}
886+
887+ for _ , test := range tests {
888+ t .Run (test .name , func (t * testing.T ) {
889+ r := prometheus .NewRegistry ()
890+ metrics := NewMetrics (r , featurecontrol.NoopFlags {})
891+ intervener := timeinterval .NewIntervener (test .intervals )
892+ st := NewTimeMuteStage (intervener , metrics )
893+
894+ // Get the names of all time intervals for the context.
895+ muteTimeIntervalNames := make ([]string , 0 , len (test .intervals ))
896+ for name := range test .intervals {
897+ muteTimeIntervalNames = append (muteTimeIntervalNames , name )
898+ }
899+
900+ ctx := context .Background ()
901+ ctx = WithNow (ctx , test .now )
902+ ctx = WithActiveTimeIntervals (ctx , nil )
903+ ctx = WithMuteTimeIntervals (ctx , muteTimeIntervalNames )
904+
905+ _ , active , err := st .Exec (ctx , log .NewNopLogger (), test .alerts ... )
906+ require .NoError (t , err )
907+
908+ if len (test .mutedBy ) == 0 {
909+ // All alerts should be active.
910+ require .Equal (t , len (test .alerts ), len (active ))
911+ // The metric for total suppressed notifications should not
912+ // have been incremented, which means it will not be collected.
913+ require .NoError (t , prom_testutil .GatherAndCompare (r , strings .NewReader ("" )))
914+ } else {
915+ // All alerts should be muted.
916+ require .Empty (t , active )
917+ // Gets the metric for total suppressed notifications.
918+ require .NoError (t , prom_testutil .GatherAndCompare (r , strings .NewReader (fmt .Sprintf (`
919+ # 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.
920+ # TYPE alertmanager_notifications_suppressed_total counter
921+ alertmanager_notifications_suppressed_total{reason="mute_time_interval"} %d
922+ ` , len (test .alerts )))))
923+ }
924+ })
936925 }
937926}
938927
0 commit comments