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

Update Alertmanager to f69a508 #7332

Merged
merged 10 commits into from
Feb 8, 2024
Merged
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
16 changes: 8 additions & 8 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ require (
github.com/opentracing-contrib/go-stdlib v1.0.0
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b
github.com/pkg/errors v0.9.1
github.com/prometheus/alertmanager v0.26.1-0.20240130102200-cab8ecbc95c4
github.com/prometheus/alertmanager v0.26.1-0.20240208095903-f69a5086657b
github.com/prometheus/client_golang v1.18.0
github.com/prometheus/client_model v0.5.0
github.com/prometheus/common v0.46.0
Expand Down Expand Up @@ -156,14 +156,14 @@ require (
github.com/go-logfmt/logfmt v0.6.0 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/analysis v0.21.4 // indirect
github.com/go-openapi/analysis v0.22.2 // indirect
github.com/go-openapi/errors v0.21.0 // indirect
github.com/go-openapi/jsonpointer v0.20.0 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/loads v0.21.2 // indirect
github.com/go-openapi/runtime v0.26.0 // indirect
github.com/go-openapi/spec v0.20.9 // indirect
github.com/go-openapi/validate v0.22.1 // indirect
github.com/go-openapi/jsonpointer v0.20.2 // indirect
github.com/go-openapi/jsonreference v0.20.4 // indirect
github.com/go-openapi/loads v0.21.5 // indirect
github.com/go-openapi/runtime v0.27.1 // indirect
github.com/go-openapi/spec v0.20.14 // indirect
github.com/go-openapi/validate v0.23.0 // indirect
github.com/go-redis/redis/v8 v8.11.5 // indirect
github.com/gofrs/uuid v4.4.0+incompatible // indirect
github.com/gogo/googleapis v1.4.1 // indirect
Expand Down
121 changes: 18 additions & 103 deletions go.sum

Large diffs are not rendered by default.

82 changes: 0 additions & 82 deletions integration/alertmanager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,88 +283,6 @@ func TestAlertmanagerUTF8StrictMode(t *testing.T) {
}))
}

// This test asserts that the correct metrics are incremented when configurations are uploaded,
// including configurations with disagreement, incompatible and invalid matchers. It can be deleted
// when the -alertmanager.utf8-strict-mode-enabled flag is removed.
func TestAlertmanagerMatchersMetrics(t *testing.T) {
s, err := e2e.NewScenario(networkName)
require.NoError(t, err)
defer s.Close()

consul := e2edb.NewConsul()
minio := e2edb.NewMinio(9000, alertsBucketName)
require.NoError(t, s.StartAndWaitReady(consul, minio))

// Upload the default configuration for two users.
require.NoError(t, uploadAlertmanagerConfig(minio, alertsBucketName, "user-1", mimirAlertmanagerUserConfigYaml))
require.NoError(t, uploadAlertmanagerConfig(minio, alertsBucketName, "user-2", mimirAlertmanagerUserConfigYaml))

alertmanager := e2emimir.NewAlertmanager(
"alertmanager",
mergeFlags(
AlertmanagerFlags(),
AlertmanagerS3Flags(),
AlertmanagerShardingFlags(consul.NetworkHTTPEndpoint(), 1),
),
)
require.NoError(t, s.StartAndWaitReady(alertmanager))
require.NoError(t, alertmanager.WaitSumMetrics(e2e.Equals(2), "cortex_alertmanager_config_last_reload_successful"))
require.NoError(t, alertmanager.WaitSumMetrics(e2e.Greater(0), "cortex_alertmanager_config_hash"))

c1, err := e2emimir.NewClient("", "", alertmanager.HTTPEndpoint(), "", "user-1")
require.NoError(t, err)
c2, err := e2emimir.NewClient("", "", alertmanager.HTTPEndpoint(), "", "user-2")
require.NoError(t, err)

// The metrics should all be zero as no configurations contain matchers.
metricNames := []string{
"alertmanager_matchers_parse_total",
"alertmanager_matchers_disagree_total",
"alertmanager_matchers_incompatible_total",
"alertmanager_matchers_invalid_total",
}
metrics, err := alertmanager.SumMetrics(metricNames, e2e.SkipMissingMetrics)
require.NoError(t, err)
require.Equal(t, []float64{0, 0, 0, 0}, metrics)

ctx, cancelFunc := context.WithTimeout(context.Background(), 15*time.Second)
defer cancelFunc()

// Upload a configuration for user1.
require.NoError(t, c1.SetAlertmanagerConfig(ctx, mimirAlertmanagerUserClassicConfigYaml, nil))
metrics, err = alertmanager.SumMetrics(metricNames, e2e.SkipMissingMetrics)
require.NoError(t, err)
// The sum for alertmanager_matchers_parse_total should be 4 as there are two matchers for origin=api
// and another two matchers for origin=config.
require.Equal(t, []float64{4, 0, 0, 0}, metrics)

// Upload a configuration for user2.
require.NoError(t, c2.SetAlertmanagerConfig(ctx, mimirAlertmanagerUserClassicConfigYaml, nil))
metrics, err = alertmanager.SumMetrics(metricNames, e2e.SkipMissingMetrics)
require.NoError(t, err)
// The sum for alertmanager_matchers_parse_total should be 8 as there are two matchers for origin=api
// and another two matchers for origin=config, and 4 from the previous sum.
require.Equal(t, []float64{8, 0, 0, 0}, metrics)

// Upload a configuration with disagreement.
require.NoError(t, c2.SetAlertmanagerConfig(ctx, mimirAlertmanagerDisagreementConfigYaml, nil))
metrics, err = alertmanager.SumMetrics(metricNames, e2e.SkipMissingMetrics)
require.NoError(t, err)
require.Equal(t, []float64{10, 1, 0, 0}, metrics)

// Upload a configuration with incompatible matchers.
require.NoError(t, c2.SetAlertmanagerConfig(ctx, mimirAlertmanagerIncompatibleConfigYaml, nil))
metrics, err = alertmanager.SumMetrics(metricNames, e2e.SkipMissingMetrics)
require.NoError(t, err)
require.Equal(t, []float64{12, 1, 1, 0}, metrics)

// Upload a configuration with invalid matchers.
require.EqualError(t, c2.SetAlertmanagerConfig(ctx, mimirAlertmanagerInvalidConfigYaml, nil), "setting config failed with status 400 and error error validating Alertmanager config: bad matcher format: \n")
metrics, err = alertmanager.SumMetrics(metricNames, e2e.SkipMissingMetrics)
require.NoError(t, err)
require.Equal(t, []float64{14, 1, 1, 2}, metrics)
}

func TestAlertmanagerV1Deprecated(t *testing.T) {
s, err := e2e.NewScenario(networkName)
require.NoError(t, err)
Expand Down
30 changes: 0 additions & 30 deletions integration/configs.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,36 +77,6 @@ receivers:
- name: test
`

mimirAlertmanagerDisagreementConfigYaml = `route:
receiver: test
group_by: [foo]
routes:
- matchers:
- foo="\xf0\x9f\x99\x82"
receivers:
- name: test
`

mimirAlertmanagerIncompatibleConfigYaml = `route:
receiver: test
group_by: [foo]
routes:
- matchers:
- foo=
receivers:
- name: test
`

mimirAlertmanagerInvalidConfigYaml = `route:
receiver: test
group_by: [foo]
routes:
- matchers:
- foo=,,
receivers:
- name: test
`

mimirRulerUserConfigYaml = `groups:
- name: rule
interval: 100s
Expand Down
4 changes: 2 additions & 2 deletions pkg/alertmanager/alertmanager_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ type matchersInhibitionRule struct {
// and disagreement. If no incompatible inputs or disagreement are found, then the Alertmanager
// can be switched to the UTF-8 strict mode. Otherwise, configurations should be fixed before
// enabling the mode.
func validateMatchersInConfigDesc(logger log.Logger, metrics *compat.Metrics, origin string, cfg alertspb.AlertConfigDesc) {
func validateMatchersInConfigDesc(logger log.Logger, origin string, cfg alertspb.AlertConfigDesc) {
// Do not add origin to the logger as it's added in the compat package.
logger = log.With(logger, "user", cfg.User)
parseFn := compat.FallbackMatchersParser(logger, metrics)
parseFn := compat.FallbackMatchersParser(logger)
matchersCfg := matchersConfig{}
if err := yaml.Unmarshal([]byte(cfg.RawConfig), &matchersCfg); err != nil {
level.Warn(logger).Log("msg", "Failed to load configuration in validateMatchersInConfigDesc", "origin", origin, "err", err)
Expand Down
83 changes: 51 additions & 32 deletions pkg/alertmanager/alertmanager_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,25 @@
package alertmanager

import (
"bytes"
"strings"
"testing"

"github.com/go-kit/log"
"github.com/prometheus/alertmanager/matchers/compat"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/testutil"
"github.com/stretchr/testify/require"

"github.com/grafana/mimir/pkg/alertmanager/alertspb"
)

func TestValidateMatchersInConfigDesc(t *testing.T) {
tests := []struct {
name string
config alertspb.AlertConfigDesc
total float64
disagreeTotal float64
incompatibleTotal float64
invalidTotal float64
name string
config alertspb.AlertConfigDesc
expected []string
}{{
name: "config is accepted",
config: alertspb.AlertConfigDesc{
User: "1",
RawConfig: `
route:
routes:
Expand All @@ -37,10 +34,15 @@ inhibit_rules:
- baz=qux
`,
},
total: 3,
expected: []string{
`level=debug user=1 msg="Parsing with UTF-8 matchers parser, with fallback to classic matchers parser" input="foo=bar" origin=test`,
`level=debug user=1 msg="Parsing with UTF-8 matchers parser, with fallback to classic matchers parser" input="bar=baz" origin=test`,
`level=debug user=1 msg="Parsing with UTF-8 matchers parser, with fallback to classic matchers parser" input="baz=qux" origin=test`,
},
}, {
name: "config contains invalid input",
config: alertspb.AlertConfigDesc{
User: "2",
RawConfig: `
route:
routes:
Expand All @@ -53,11 +55,18 @@ inhibit_rules:
- baz!qux
`,
},
total: 3,
invalidTotal: 3,
expected: []string{
`level=debug user=2 msg="Parsing with UTF-8 matchers parser, with fallback to classic matchers parser" input=foo!bar origin=test`,
`level=debug user=2 msg="Invalid matcher in route" input=foo!bar origin=test err="bad matcher format: foo!bar"`,
`level=debug user=2 msg="Parsing with UTF-8 matchers parser, with fallback to classic matchers parser" input=bar!baz origin=test`,
`level=debug user=2 msg="Invalid matcher in inhibition rule source matchers" input=bar!baz origin=test err="bad matcher format: bar!baz"`,
`level=debug user=2 msg="Parsing with UTF-8 matchers parser, with fallback to classic matchers parser" input=baz!qux origin=test`,
`level=debug user=2 msg="Invalid matcher in inhibition rule target matchers" input=baz!qux origin=test err="bad matcher format: baz!qux"`,
},
}, {
name: "config is accepted in matchers/parse but not pkg/labels",
config: alertspb.AlertConfigDesc{
User: "3",
RawConfig: `
route:
routes:
Expand All @@ -70,10 +79,15 @@ inhibit_rules:
- baz🙂=qux
`,
},
total: 3,
expected: []string{
`level=debug user=3 msg="Parsing with UTF-8 matchers parser, with fallback to classic matchers parser" input="foo🙂=bar" origin=test`,
`level=debug user=3 msg="Parsing with UTF-8 matchers parser, with fallback to classic matchers parser" input="bar🙂=baz" origin=test`,
`level=debug user=3 msg="Parsing with UTF-8 matchers parser, with fallback to classic matchers parser" input="baz🙂=qux" origin=test`,
},
}, {
name: "config is accepted in pkg/labels but not matchers/parse",
config: alertspb.AlertConfigDesc{
User: "4",
RawConfig: `
route:
routes:
Expand All @@ -86,11 +100,18 @@ inhibit_rules:
- baz=
`,
},
total: 3,
incompatibleTotal: 3,
expected: []string{
`level=debug user=4 msg="Parsing with UTF-8 matchers parser, with fallback to classic matchers parser" input="foo=" origin=test`,
`level=warn user=4 msg="Alertmanager is moving to a new parser for labels and matchers, and this input is incompatible. Alertmanager has instead parsed the input using the old matchers parser as a fallback. To make this input compatible with the new parser please make sure all regular expressions and values are double-quoted. If you are still seeing this message please open an issue." input="foo=" origin=test err="end of input: expected label value" suggestion="foo=\"\""`,
`level=debug user=4 msg="Parsing with UTF-8 matchers parser, with fallback to classic matchers parser" input="bar=" origin=test`,
`level=warn user=4 msg="Alertmanager is moving to a new parser for labels and matchers, and this input is incompatible. Alertmanager has instead parsed the input using the old matchers parser as a fallback. To make this input compatible with the new parser please make sure all regular expressions and values are double-quoted. If you are still seeing this message please open an issue." input="bar=" origin=test err="end of input: expected label value" suggestion="bar=\"\""`,
`level=debug user=4 msg="Parsing with UTF-8 matchers parser, with fallback to classic matchers parser" input="baz=" origin=test`,
`level=warn user=4 msg="Alertmanager is moving to a new parser for labels and matchers, and this input is incompatible. Alertmanager has instead parsed the input using the old matchers parser as a fallback. To make this input compatible with the new parser please make sure all regular expressions and values are double-quoted. If you are still seeing this message please open an issue." input="baz=" origin=test err="end of input: expected label value" suggestion="baz=\"\""`,
},
}, {
name: "config contains disagreement",
config: alertspb.AlertConfigDesc{
User: "5",
RawConfig: `
route:
routes:
Expand All @@ -103,27 +124,25 @@ inhibit_rules:
- baz="\xf0\x9f\x99\x82"
`,
},
total: 3,
disagreeTotal: 3,
expected: []string{
`level=debug user=5 msg="Parsing with UTF-8 matchers parser, with fallback to classic matchers parser" input="foo=\"\\xf0\\x9f\\x99\\x82\"" origin=test`,
`level=warn user=5 msg="Matchers input has disagreement" input="foo=\"\\xf0\\x9f\\x99\\x82\"" origin=test`,
`level=debug user=5 msg="Parsing with UTF-8 matchers parser, with fallback to classic matchers parser" input="bar=\"\\xf0\\x9f\\x99\\x82\"" origin=test`,
`level=warn user=5 msg="Matchers input has disagreement" input="bar=\"\\xf0\\x9f\\x99\\x82\"" origin=test`,
`level=debug user=5 msg="Parsing with UTF-8 matchers parser, with fallback to classic matchers parser" input="baz=\"\\xf0\\x9f\\x99\\x82\"" origin=test`,
`level=warn user=5 msg="Matchers input has disagreement" input="baz=\"\\xf0\\x9f\\x99\\x82\"" origin=test`,
},
}}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
m := compat.NewMetrics(prometheus.NewRegistry())
validateMatchersInConfigDesc(log.NewNopLogger(), m, "test", test.config)
requireMetric(t, test.total, m.Total)
requireMetric(t, test.disagreeTotal, m.DisagreeTotal)
requireMetric(t, test.incompatibleTotal, m.IncompatibleTotal)
requireMetric(t, test.invalidTotal, m.InvalidTotal)
buf := bytes.Buffer{}
validateMatchersInConfigDesc(log.NewLogfmtLogger(&buf), "test", test.config)
lines := strings.Split(strings.Trim(buf.String(), "\n"), "\n")
require.Equal(t, len(test.expected), len(lines))
for i := range lines {
require.Equal(t, test.expected[i], lines[i])
}
})
}
}

func requireMetric(t *testing.T, expected float64, m *prometheus.CounterVec) {
if expected == 0 {
require.Equal(t, 0, testutil.CollectAndCount(m))
} else {
require.Equal(t, 1, testutil.CollectAndCount(m))
require.Equal(t, expected, testutil.ToFloat64(m))
}
}
Loading
Loading