Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add silence logging option #4163

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cmd/alertmanager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ func run() int {
maxSilences = kingpin.Flag("silences.max-silences", "Maximum number of silences, including expired silences. If negative or zero, no limit is set.").Default("0").Int()
maxSilenceSizeBytes = kingpin.Flag("silences.max-silence-size-bytes", "Maximum silence size in bytes. If negative or zero, no limit is set.").Default("0").Int()
alertGCInterval = kingpin.Flag("alerts.gc-interval", "Interval between alert GC.").Default("30m").Duration()
silenceLogging = kingpin.Flag("log.silences", "Enable logging silences. If it is enabled, the status change of silence will be logged").Bool()

webConfig = webflag.AddFlags(kingpin.CommandLine, ":9093")
externalURL = kingpin.Flag("web.external-url", "The URL under which Alertmanager is externally reachable (for example, if Alertmanager is served via a reverse proxy). Used for generating relative and absolute links back to Alertmanager itself. If the URL has a path portion, it will be used to prefix all HTTP endpoints served by Alertmanager. If omitted, relevant URL components will be derived automatically.").String()
Expand Down Expand Up @@ -299,6 +300,7 @@ func run() int {
},
Logger: logger.With("component", "silences"),
Metrics: prometheus.DefaultRegisterer,
Logging: *silenceLogging,
}

silences, err := silence.New(silenceOpts)
Expand Down
46 changes: 46 additions & 0 deletions silence/silence.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"reflect"
"regexp"
"sort"
"strings"
"sync"
"time"

Expand Down Expand Up @@ -194,6 +195,7 @@ type Silences struct {
metrics *metrics
retention time.Duration
limits Limits
logging bool

mtx sync.RWMutex
st state
Expand Down Expand Up @@ -331,6 +333,8 @@ type Options struct {
Retention time.Duration
Limits Limits

Logging bool

// A logger used by background processing.
Logger *slog.Logger
Metrics prometheus.Registerer
Expand All @@ -355,6 +359,7 @@ func New(o Options) (*Silences, error) {
logger: promslog.NewNopLogger(),
retention: o.Retention,
limits: o.Limits,
logging: o.Logging,
broadcast: func([]byte) {},
st: state{},
}
Expand Down Expand Up @@ -616,6 +621,9 @@ func (s *Silences) Set(sil *pb.Silence) error {
if err := s.checkSizeLimits(msil); err != nil {
return err
}
if s.logging {
s.logginSilences("update silence", sil)
}
return s.setSilence(msil, now)
}

Expand Down Expand Up @@ -652,6 +660,9 @@ func (s *Silences) Set(sil *pb.Silence) error {
}
}

if s.logging {
s.logginSilences("create silence", sil)
}
return s.setSilence(msil, now)
}

Expand Down Expand Up @@ -711,6 +722,9 @@ func (s *Silences) expire(id string) error {
sil.EndsAt = now
}
sil.UpdatedAt = now
if s.logging {
s.logginSilences("expire silence", sil)
}
return s.setSilence(s.toMeshSilence(sil), now)
}

Expand Down Expand Up @@ -1053,3 +1067,35 @@ func openReplace(filename string) (*replaceFile, error) {
}
return rf, nil
}

// logging silence status changes.
//
// XXX: This rewrites some code present in cli/format/format.go,
// labelsMatcher() and cli/format/format_extended.go,
// FormatSilences(). Refactoring this seems a little out of scope for
// now.
func (s *Silences) logginSilences(msg string, sil *pb.Silence) {
var listMatchers []string
matcherTypeOperator := map[string]string{
"EQUAL": "=",
"REGEXP": "=~",
"NOT_EQUAL": "!=",
"NOT_REGEXP": "!~",
}
for _, matcher := range sil.Matchers {
ms := []string{matcher.Name, matcherTypeOperator[matcher.Type.String()], matcher.Pattern}
m := strings.Join(ms, ``)
listMatchers = append(listMatchers, m)
}
strMatchers := strings.Join(listMatchers, `,`)

s.logger.Info(
msg,
"Id", sil.Id,
"CreatedBy", sil.CreatedBy,
"Comment", sil.Comment,
"StartsAt", sil.StartsAt,
"EndsAt", sil.EndsAt,
"Matchers", strMatchers,
)
}