|
|
|
|
@ -44,7 +44,7 @@ type AlertingStore interface { |
|
|
|
|
store.ImageStore |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type Alertmanager struct { |
|
|
|
|
type alertmanager struct { |
|
|
|
|
Base *alertingNotify.GrafanaAlertmanager |
|
|
|
|
logger log.Logger |
|
|
|
|
|
|
|
|
|
@ -85,7 +85,7 @@ func (m maintenanceOptions) MaintenanceFunc(state alertingNotify.State) (int64, |
|
|
|
|
|
|
|
|
|
func newAlertmanager(ctx context.Context, orgID int64, cfg *setting.Cfg, store AlertingStore, kvStore kvstore.KVStore, |
|
|
|
|
peer alertingNotify.ClusterPeer, decryptFn alertingNotify.GetDecryptedValueFn, ns notifications.Service, |
|
|
|
|
m *metrics.Alertmanager) (*Alertmanager, error) { |
|
|
|
|
m *metrics.Alertmanager) (*alertmanager, error) { |
|
|
|
|
workingPath := filepath.Join(cfg.DataPath, workingDir, strconv.Itoa(int(orgID))) |
|
|
|
|
fileStore := NewFileStore(orgID, kvStore, workingPath) |
|
|
|
|
|
|
|
|
|
@ -133,7 +133,7 @@ func newAlertmanager(ctx context.Context, orgID int64, cfg *setting.Cfg, store A |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
am := &Alertmanager{ |
|
|
|
|
am := &alertmanager{ |
|
|
|
|
Base: gam, |
|
|
|
|
ConfigMetrics: m.AlertmanagerConfigMetrics, |
|
|
|
|
Settings: cfg, |
|
|
|
|
@ -148,20 +148,20 @@ func newAlertmanager(ctx context.Context, orgID int64, cfg *setting.Cfg, store A |
|
|
|
|
return am, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (am *Alertmanager) Ready() bool { |
|
|
|
|
func (am *alertmanager) Ready() bool { |
|
|
|
|
// We consider AM as ready only when the config has been
|
|
|
|
|
// applied at least once successfully. Until then, some objects
|
|
|
|
|
// can still be nil.
|
|
|
|
|
return am.Base.Ready() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (am *Alertmanager) StopAndWait() { |
|
|
|
|
func (am *alertmanager) StopAndWait() { |
|
|
|
|
am.Base.StopAndWait() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// SaveAndApplyDefaultConfig saves the default configuration to the database and applies it to the Alertmanager.
|
|
|
|
|
// It rolls back the save if we fail to apply the configuration.
|
|
|
|
|
func (am *Alertmanager) SaveAndApplyDefaultConfig(ctx context.Context) error { |
|
|
|
|
func (am *alertmanager) SaveAndApplyDefaultConfig(ctx context.Context) error { |
|
|
|
|
var outerErr error |
|
|
|
|
am.Base.WithLock(func() { |
|
|
|
|
cmd := &ngmodels.SaveAlertmanagerConfigurationCmd{ |
|
|
|
|
@ -193,7 +193,7 @@ func (am *Alertmanager) SaveAndApplyDefaultConfig(ctx context.Context) error { |
|
|
|
|
|
|
|
|
|
// SaveAndApplyConfig saves the configuration the database and applies the configuration to the Alertmanager.
|
|
|
|
|
// It rollbacks the save if we fail to apply the configuration.
|
|
|
|
|
func (am *Alertmanager) SaveAndApplyConfig(ctx context.Context, cfg *apimodels.PostableUserConfig) error { |
|
|
|
|
func (am *alertmanager) SaveAndApplyConfig(ctx context.Context, cfg *apimodels.PostableUserConfig) error { |
|
|
|
|
rawConfig, err := json.Marshal(&cfg) |
|
|
|
|
if err != nil { |
|
|
|
|
return fmt.Errorf("failed to serialize to the Alertmanager configuration: %w", err) |
|
|
|
|
@ -222,7 +222,7 @@ func (am *Alertmanager) SaveAndApplyConfig(ctx context.Context, cfg *apimodels.P |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// ApplyConfig applies the configuration to the Alertmanager.
|
|
|
|
|
func (am *Alertmanager) ApplyConfig(ctx context.Context, dbCfg *ngmodels.AlertConfiguration) error { |
|
|
|
|
func (am *alertmanager) ApplyConfig(ctx context.Context, dbCfg *ngmodels.AlertConfiguration) error { |
|
|
|
|
var err error |
|
|
|
|
cfg, err := Load([]byte(dbCfg.AlertmanagerConfiguration)) |
|
|
|
|
if err != nil { |
|
|
|
|
@ -247,7 +247,7 @@ type AggregateMatchersUsage struct { |
|
|
|
|
ObjectMatchers int |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (am *Alertmanager) updateConfigMetrics(cfg *apimodels.PostableUserConfig) { |
|
|
|
|
func (am *alertmanager) updateConfigMetrics(cfg *apimodels.PostableUserConfig) { |
|
|
|
|
var amu AggregateMatchersUsage |
|
|
|
|
am.aggregateRouteMatchers(cfg.AlertmanagerConfig.Route, &amu) |
|
|
|
|
am.aggregateInhibitMatchers(cfg.AlertmanagerConfig.InhibitRules, &amu) |
|
|
|
|
@ -257,7 +257,7 @@ func (am *Alertmanager) updateConfigMetrics(cfg *apimodels.PostableUserConfig) { |
|
|
|
|
am.ConfigMetrics.ObjectMatchers.Set(float64(amu.ObjectMatchers)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (am *Alertmanager) aggregateRouteMatchers(r *apimodels.Route, amu *AggregateMatchersUsage) { |
|
|
|
|
func (am *alertmanager) aggregateRouteMatchers(r *apimodels.Route, amu *AggregateMatchersUsage) { |
|
|
|
|
amu.Matchers += len(r.Matchers) |
|
|
|
|
amu.MatchRE += len(r.MatchRE) |
|
|
|
|
amu.Match += len(r.Match) |
|
|
|
|
@ -267,7 +267,7 @@ func (am *Alertmanager) aggregateRouteMatchers(r *apimodels.Route, amu *Aggregat |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (am *Alertmanager) aggregateInhibitMatchers(rules []config.InhibitRule, amu *AggregateMatchersUsage) { |
|
|
|
|
func (am *alertmanager) aggregateInhibitMatchers(rules []config.InhibitRule, amu *AggregateMatchersUsage) { |
|
|
|
|
for _, r := range rules { |
|
|
|
|
amu.Matchers += len(r.SourceMatchers) |
|
|
|
|
amu.Matchers += len(r.TargetMatchers) |
|
|
|
|
@ -281,7 +281,7 @@ func (am *Alertmanager) aggregateInhibitMatchers(rules []config.InhibitRule, amu |
|
|
|
|
// applyConfig applies a new configuration by re-initializing all components using the configuration provided.
|
|
|
|
|
// It returns a boolean indicating whether the user config was changed and an error.
|
|
|
|
|
// It is not safe to call concurrently.
|
|
|
|
|
func (am *Alertmanager) applyConfig(cfg *apimodels.PostableUserConfig, rawConfig []byte) (bool, error) { |
|
|
|
|
func (am *alertmanager) applyConfig(cfg *apimodels.PostableUserConfig, rawConfig []byte) (bool, error) { |
|
|
|
|
// First, let's make sure this config is not already loaded
|
|
|
|
|
var amConfigChanged bool |
|
|
|
|
if rawConfig == nil { |
|
|
|
|
@ -331,7 +331,7 @@ func (am *Alertmanager) applyConfig(cfg *apimodels.PostableUserConfig, rawConfig |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// applyAndMarkConfig applies a configuration and marks it as applied if no errors occur.
|
|
|
|
|
func (am *Alertmanager) applyAndMarkConfig(ctx context.Context, hash string, cfg *apimodels.PostableUserConfig, rawConfig []byte) error { |
|
|
|
|
func (am *alertmanager) applyAndMarkConfig(ctx context.Context, hash string, cfg *apimodels.PostableUserConfig, rawConfig []byte) error { |
|
|
|
|
configChanged, err := am.applyConfig(cfg, rawConfig) |
|
|
|
|
if err != nil { |
|
|
|
|
return err |
|
|
|
|
@ -348,12 +348,12 @@ func (am *Alertmanager) applyAndMarkConfig(ctx context.Context, hash string, cfg |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (am *Alertmanager) AppURL() string { |
|
|
|
|
func (am *alertmanager) AppURL() string { |
|
|
|
|
return am.Settings.AppURL |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// buildReceiverIntegrations builds a list of integration notifiers off of a receiver config.
|
|
|
|
|
func (am *Alertmanager) buildReceiverIntegrations(receiver *alertingNotify.APIReceiver, tmpl *alertingTemplates.Template) ([]*alertingNotify.Integration, error) { |
|
|
|
|
func (am *alertmanager) buildReceiverIntegrations(receiver *alertingNotify.APIReceiver, tmpl *alertingTemplates.Template) ([]*alertingNotify.Integration, error) { |
|
|
|
|
receiverCfg, err := alertingNotify.BuildReceiverConfiguration(context.Background(), receiver, am.decryptFn) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
@ -381,7 +381,7 @@ func (am *Alertmanager) buildReceiverIntegrations(receiver *alertingNotify.APIRe |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// PutAlerts receives the alerts and then sends them through the corresponding route based on whenever the alert has a receiver embedded or not
|
|
|
|
|
func (am *Alertmanager) PutAlerts(postableAlerts apimodels.PostableAlerts) error { |
|
|
|
|
func (am *alertmanager) PutAlerts(postableAlerts apimodels.PostableAlerts) error { |
|
|
|
|
alerts := make(alertingNotify.PostableAlerts, 0, len(postableAlerts.PostableAlerts)) |
|
|
|
|
for _, pa := range postableAlerts.PostableAlerts { |
|
|
|
|
alerts = append(alerts, &alertingNotify.PostableAlert{ |
|
|
|
|
@ -395,6 +395,18 @@ func (am *Alertmanager) PutAlerts(postableAlerts apimodels.PostableAlerts) error |
|
|
|
|
return am.Base.PutAlerts(alerts) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (am *alertmanager) ConfigHash() [16]byte { |
|
|
|
|
return am.Base.ConfigHash() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (am *alertmanager) OrgID() int64 { |
|
|
|
|
return am.orgID |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (am *alertmanager) FileStore() *FileStore { |
|
|
|
|
return am.fileStore |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// AlertValidationError is the error capturing the validation errors
|
|
|
|
|
// faced on the alerts.
|
|
|
|
|
type AlertValidationError struct { |
|
|
|
|
|