diff --git a/go.mod b/go.mod index ccad0253b6..68357c0e0f 100644 --- a/go.mod +++ b/go.mod @@ -66,7 +66,7 @@ require ( github.com/google/go-github/v57 v57.0.0 github.com/google/uuid v1.6.0 github.com/grafana-tools/sdk v0.0.0-20220919052116-6562121319fc - github.com/grafana/alerting v0.0.0-20250113170557-b4ab2ba363a8 + github.com/grafana/alerting v0.0.0-20250117230852-a5e8136407d4 github.com/grafana/regexp v0.0.0-20240607082908-2cb410fa05da github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/hashicorp/vault/api v1.15.0 diff --git a/go.sum b/go.sum index 9e253d1804..c01a70ee09 100644 --- a/go.sum +++ b/go.sum @@ -1269,8 +1269,8 @@ github.com/gosimple/slug v1.1.1 h1:fRu/digW+NMwBIP+RmviTK97Ho/bEj/C9swrCspN3D4= github.com/gosimple/slug v1.1.1/go.mod h1:ER78kgg1Mv0NQGlXiDe57DpCyfbNywXXZ9mIorhxAf0= github.com/grafana-tools/sdk v0.0.0-20220919052116-6562121319fc h1:PXZQA2WCxe85Tnn+WEvr8fDpfwibmEPgfgFEaC87G24= github.com/grafana-tools/sdk v0.0.0-20220919052116-6562121319fc/go.mod h1:AHHlOEv1+GGQ3ktHMlhuTUwo3zljV3QJbC0+8o2kn+4= -github.com/grafana/alerting v0.0.0-20250113170557-b4ab2ba363a8 h1:mdI6P22PgFD7bQ0Yf4h8cfHSldak4nxogvlsTHZyZmc= -github.com/grafana/alerting v0.0.0-20250113170557-b4ab2ba363a8/go.mod h1:QsnoKX/iYZxA4Cv+H+wC7uxutBD8qi8ZW5UJvD2TYmU= +github.com/grafana/alerting v0.0.0-20250117230852-a5e8136407d4 h1:616HUg7WVyLJLtVvk2pZ845M4Gk0fswgTwEZSuAZbJU= +github.com/grafana/alerting v0.0.0-20250117230852-a5e8136407d4/go.mod h1:QsnoKX/iYZxA4Cv+H+wC7uxutBD8qi8ZW5UJvD2TYmU= github.com/grafana/dskit v0.0.0-20250117173157-36b56b12711d h1:dAJOAzmZyZQgVpNjSK9bNnCvSBZP+HmGo0U+lXJ+ku0= github.com/grafana/dskit v0.0.0-20250117173157-36b56b12711d/go.mod h1:SPLNCARd4xdjCkue0O6hvuoveuS1dGJjDnfxYe405YQ= github.com/grafana/e2e v0.1.2-0.20240118170847-db90b84177fc h1:BW+LjKJDz0So5LI8UZfW5neWeKpSkWqhmGjQFzcFfLM= diff --git a/vendor/github.com/grafana/alerting/notify/grafana_alertmanager.go b/vendor/github.com/grafana/alerting/notify/grafana_alertmanager.go index 693dbff52c..fcbd00f4ab 100644 --- a/vendor/github.com/grafana/alerting/notify/grafana_alertmanager.go +++ b/vendor/github.com/grafana/alerting/notify/grafana_alertmanager.go @@ -18,8 +18,6 @@ import ( "github.com/go-openapi/strfmt" "golang.org/x/sync/errgroup" - "github.com/grafana/alerting/cluster" - "github.com/grafana/alerting/notify/nfstatus" amv2 "github.com/prometheus/alertmanager/api/v2/models" "github.com/prometheus/alertmanager/config" "github.com/prometheus/alertmanager/dispatch" @@ -37,6 +35,9 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/common/model" + "github.com/grafana/alerting/cluster" + "github.com/grafana/alerting/notify/nfstatus" + "github.com/grafana/alerting/models" "github.com/grafana/alerting/templates" ) @@ -663,13 +664,24 @@ func (am *GrafanaAlertmanager) ApplyConfig(cfg Configuration) (err error) { // Finally, build the integrations map using the receiver configuration and templates. apiReceivers := cfg.Receivers() + nameToReceiver := make(map[string]*APIReceiver, len(apiReceivers)) + for _, receiver := range apiReceivers { + if existing, ok := nameToReceiver[receiver.Name]; ok { + itypes := make([]string, 0, len(existing.GrafanaIntegrations.Integrations)) + for _, i := range existing.GrafanaIntegrations.Integrations { + itypes = append(itypes, i.Type) + } + level.Warn(am.logger).Log("msg", "receiver with same name is defined multiple times. Only the last one will be used", "receiver_name", receiver.Name, "overwritten_integrations", itypes) + } + nameToReceiver[receiver.Name] = receiver + } integrationsMap := make(map[string][]*Integration, len(apiReceivers)) - for _, apiReceiver := range apiReceivers { + for name, apiReceiver := range nameToReceiver { integrations, err := cfg.BuildReceiverIntegrationsFunc()(apiReceiver, tmpl) if err != nil { return err } - integrationsMap[apiReceiver.Name] = integrations + integrationsMap[name] = integrations } // Now, let's put together our notification pipeline diff --git a/vendor/github.com/grafana/alerting/templates/template_data.go b/vendor/github.com/grafana/alerting/templates/template_data.go index f9b452624e..21f8957971 100644 --- a/vendor/github.com/grafana/alerting/templates/template_data.go +++ b/vendor/github.com/grafana/alerting/templates/template_data.go @@ -8,7 +8,6 @@ import ( "net/url" "path" "slices" - "sort" "strings" tmpltext "text/template" "time" @@ -226,28 +225,45 @@ func extendAlert(alert template.Alert, externalURL string, logger log.Logger) *E extended.ValueString = alert.Annotations[models.ValueStringAnnotation] } - matchers := make([]string, 0) - for key, value := range alert.Labels { - if !(strings.HasPrefix(key, "__") && strings.HasSuffix(key, "__")) { - matchers = append(matchers, key+"="+value) - } - } - sort.Strings(matchers) - u.Path = path.Join(externalPath, "/alerting/silence/new") + extended.SilenceURL = generateSilenceURL(alert, *u, externalPath) + + return extended +} + +// generateSilenceURL generates a URL to silence the given alert in Grafana. +func generateSilenceURL(alert template.Alert, baseURL url.URL, externalPath string) string { + baseURL.Path = path.Join(externalPath, "/alerting/silence/new") query := make(url.Values) query.Add("alertmanager", "grafana") - for _, matcher := range matchers { - query.Add("matcher", matcher) + + ruleUID := alert.Labels[models.RuleUIDLabel] + if ruleUID != "" { + query.Add("matcher", models.RuleUIDLabel+"="+ruleUID) } - u.RawQuery = query.Encode() + for _, pair := range alert.Labels.SortedPairs() { + if strings.HasPrefix(pair.Name, "__") && strings.HasSuffix(pair.Name, "__") { + continue + } + + // If the alert has a rule uid available, it can more succinctly and accurately replace alertname + folder labels. + // In addition, using rule uid is more compatible with minimal permission RBAC users as they require the rule uid to silence. + if ruleUID != "" && (pair.Name == models.FolderTitleLabel || pair.Name == model.AlertNameLabel) { + continue + } + + query.Add("matcher", pair.Name+"="+pair.Value) + } + + baseURL.RawQuery = query.Encode() + + orgID := alert.Annotations[models.OrgIDAnnotation] if len(orgID) > 0 { - extended.SilenceURL = setOrgIDQueryParam(u, orgID) - } else { - extended.SilenceURL = u.String() + _ = setOrgIDQueryParam(&baseURL, orgID) } - return extended + + return baseURL.String() } func setOrgIDQueryParam(url *url.URL, orgID string) string { diff --git a/vendor/modules.txt b/vendor/modules.txt index 2f25c0937c..d280112aa9 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -610,7 +610,7 @@ github.com/gosimple/slug # github.com/grafana-tools/sdk v0.0.0-20220919052116-6562121319fc ## explicit; go 1.13 github.com/grafana-tools/sdk -# github.com/grafana/alerting v0.0.0-20250113170557-b4ab2ba363a8 +# github.com/grafana/alerting v0.0.0-20250117230852-a5e8136407d4 ## explicit; go 1.22 github.com/grafana/alerting/cluster github.com/grafana/alerting/definition