diff --git a/cmd/alertmanager/main.go b/cmd/alertmanager/main.go index 7566fba8d5..f353adb364 100644 --- a/cmd/alertmanager/main.go +++ b/cmd/alertmanager/main.go @@ -262,8 +262,8 @@ func run() int { SnapshotFile: filepath.Join(*dataDir, "silences"), Retention: *retention, Limits: silence.Limits{ - MaxSilences: *maxSilences, - MaxPerSilenceBytes: *maxPerSilenceBytes, + MaxSilences: func() int { return *maxSilences }, + MaxPerSilenceBytes: func() int { return *maxPerSilenceBytes }, }, Logger: log.With(logger, "component", "silences"), Metrics: prometheus.DefaultRegisterer, diff --git a/silence/silence.go b/silence/silence.go index c837e6fa99..31ec705d51 100644 --- a/silence/silence.go +++ b/silence/silence.go @@ -206,10 +206,10 @@ type Silences struct { type Limits struct { // MaxSilences limits the maximum number of silences, including expired // silences. - MaxSilences int + MaxSilences func() int // MaxPerSilenceBytes is the maximum size of an individual silence as // stored on disk. - MaxPerSilenceBytes int + MaxPerSilenceBytes func() int } // MaintenanceFunc represents the function to run as part of the periodic maintenance for silences. @@ -585,8 +585,11 @@ func (s *Silences) setSilence(sil *pb.Silence, now time.Time, skipValidate bool) // Check the limit unless the silence has been expired. This is to avoid // situations where silences cannot be expired after the limit has been // reduced. - if n := msil.Size(); s.limits.MaxPerSilenceBytes > 0 && n > s.limits.MaxPerSilenceBytes && sil.EndsAt.After(now) { - return fmt.Errorf("silence exceeded maximum size: %d bytes (limit: %d bytes)", n, s.limits.MaxPerSilenceBytes) + if s.limits.MaxPerSilenceBytes != nil { + n := msil.Size() + if m := s.limits.MaxPerSilenceBytes(); m > 0 && n > m && sil.EndsAt.After(now) { + return fmt.Errorf("silence exceeded maximum size: %d bytes (limit: %d bytes)", n, m) + } } if s.st.merge(msil, now) { @@ -622,9 +625,9 @@ func (s *Silences) Set(sil *pb.Silence) (string, error) { } // If we got here it's either a new silence or a replacing one. - if s.limits.MaxSilences > 0 { - if len(s.st)+1 > s.limits.MaxSilences { - return "", fmt.Errorf("exceeded maximum number of silences: %d (limit: %d)", len(s.st), s.limits.MaxSilences) + if s.limits.MaxSilences != nil { + if m := s.limits.MaxSilences(); m > 0 && len(s.st)+1 > m { + return "", fmt.Errorf("exceeded maximum number of silences: %d (limit: %d)", len(s.st), m) } } diff --git a/silence/silence_test.go b/silence/silence_test.go index a956d756b3..11b5fb13ec 100644 --- a/silence/silence_test.go +++ b/silence/silence_test.go @@ -462,8 +462,8 @@ func TestSilenceSet(t *testing.T) { func TestSilenceLimits(t *testing.T) { s, err := New(Options{ Limits: Limits{ - MaxSilences: 1, - MaxPerSilenceBytes: 2 << 11, // 4KB + MaxSilences: func() int { return 1 }, + MaxPerSilenceBytes: func() int { return 2 << 11 }, // 4KB }, }) require.NoError(t, err) @@ -535,6 +535,24 @@ func TestSilenceLimits(t *testing.T) { require.Equal(t, "", id3) } +func TestSilenceNoLimits(t *testing.T) { + s, err := New(Options{ + Limits: Limits{}, + }) + require.NoError(t, err) + + // Insert sil should succeed without error. + sil := &pb.Silence{ + Matchers: []*pb.Matcher{{Name: "a", Pattern: "b"}}, + StartsAt: time.Now(), + EndsAt: time.Now().Add(5 * time.Minute), + Comment: strings.Repeat("c", 2<<9), + } + id, err := s.Set(sil) + require.NoError(t, err) + require.NotEqual(t, "", id) +} + func TestSetActiveSilence(t *testing.T) { s, err := New(Options{ Retention: time.Hour,