unit tests: make all Labels sorted alphabetically (#10532)

"Labels is a sorted set of labels. Order has to be guaranteed upon
instantiation." says the comment, so fix all the tests that break this
rule.

For `BenchmarkLabelValuesWithMatchers()` and
`BenchmarkHeadLabelValuesWithMatchers()` the amount of work done changes
significantly if you put the labels in order, because all series refs
get neatly partitioned by the `tens` label, so I renamed the labels
to maintain the previous behaviour.

Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
This commit is contained in:
Bryan Boreham 2022-05-04 22:41:36 +01:00 committed by GitHub
parent b9d4260b81
commit 4b9f248e85
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 25 additions and 21 deletions

View file

@ -48,8 +48,8 @@ func TestSampledReadEndpoint(t *testing.T) {
GlobalConfig: config.GlobalConfig{ GlobalConfig: config.GlobalConfig{
ExternalLabels: labels.Labels{ ExternalLabels: labels.Labels{
// We expect external labels to be added, with the source labels honored. // We expect external labels to be added, with the source labels honored.
{Name: "baz", Value: "a"},
{Name: "b", Value: "c"}, {Name: "b", Value: "c"},
{Name: "baz", Value: "a"},
{Name: "d", Value: "e"}, {Name: "d", Value: "e"},
}, },
}, },

View file

@ -141,8 +141,8 @@ func TestExternalLabelsQuerierAddExternalLabels(t *testing.T) {
}, },
{ {
el: labels.Labels{ el: labels.Labels{
{Name: "region", Value: "europe"},
{Name: "dc", Value: "berlin-01"}, {Name: "dc", Value: "berlin-01"},
{Name: "region", Value: "europe"},
}, },
inMatchers: []*labels.Matcher{ inMatchers: []*labels.Matcher{
labels.MustNewMatcher(labels.MatchEqual, "job", "api-server"), labels.MustNewMatcher(labels.MatchEqual, "job", "api-server"),

View file

@ -457,8 +457,8 @@ func labelsForTest(lName string, seriesCount int) []labels.Labels {
for i := 0; i < seriesCount; i++ { for i := 0; i < seriesCount; i++ {
lset := labels.Labels{ lset := labels.Labels{
{Name: "a", Value: lName}, {Name: "a", Value: lName},
{Name: "job", Value: "prometheus"},
{Name: "instance", Value: "localhost" + strconv.Itoa(i)}, {Name: "instance", Value: "localhost" + strconv.Itoa(i)},
{Name: "job", Value: "prometheus"},
} }
series = append(series, lset) series = append(series, lset)
} }

View file

@ -203,8 +203,8 @@ func TestLabelValuesWithMatchers(t *testing.T) {
var seriesEntries []storage.Series var seriesEntries []storage.Series
for i := 0; i < 100; i++ { for i := 0; i < 100; i++ {
seriesEntries = append(seriesEntries, storage.NewListSeries(labels.Labels{ seriesEntries = append(seriesEntries, storage.NewListSeries(labels.Labels{
{Name: "unique", Value: fmt.Sprintf("value%d", i)},
{Name: "tens", Value: fmt.Sprintf("value%d", i/10)}, {Name: "tens", Value: fmt.Sprintf("value%d", i/10)},
{Name: "unique", Value: fmt.Sprintf("value%d", i)},
}, []tsdbutil.Sample{sample{100, 0}})) }, []tsdbutil.Sample{sample{100, 0}}))
} }
@ -357,10 +357,12 @@ func BenchmarkLabelValuesWithMatchers(b *testing.B) {
var seriesEntries []storage.Series var seriesEntries []storage.Series
metricCount := 1000000 metricCount := 1000000
for i := 0; i < metricCount; i++ { for i := 0; i < metricCount; i++ {
// Note these series are not created in sort order: 'value2' sorts after 'value10'.
// This makes a big difference to the benchmark timing.
seriesEntries = append(seriesEntries, storage.NewListSeries(labels.Labels{ seriesEntries = append(seriesEntries, storage.NewListSeries(labels.Labels{
{Name: "unique", Value: fmt.Sprintf("value%d", i)}, {Name: "a_unique", Value: fmt.Sprintf("value%d", i)},
{Name: "tens", Value: fmt.Sprintf("value%d", i/(metricCount/10))}, {Name: "b_tens", Value: fmt.Sprintf("value%d", i/(metricCount/10))},
{Name: "ninety", Value: fmt.Sprintf("value%d", i/(metricCount/10)/9)}, // "0" for the first 90%, then "1" {Name: "c_ninety", Value: fmt.Sprintf("value%d", i/(metricCount/10)/9)}, // "0" for the first 90%, then "1"
}, []tsdbutil.Sample{sample{100, 0}})) }, []tsdbutil.Sample{sample{100, 0}}))
} }
@ -378,13 +380,13 @@ func BenchmarkLabelValuesWithMatchers(b *testing.B) {
require.NoError(b, err) require.NoError(b, err)
defer func() { require.NoError(b, indexReader.Close()) }() defer func() { require.NoError(b, indexReader.Close()) }()
matchers := []*labels.Matcher{labels.MustNewMatcher(labels.MatchEqual, "ninety", "value0")} matchers := []*labels.Matcher{labels.MustNewMatcher(labels.MatchEqual, "c_ninety", "value0")}
b.ResetTimer() b.ResetTimer()
b.ReportAllocs() b.ReportAllocs()
for benchIdx := 0; benchIdx < b.N; benchIdx++ { for benchIdx := 0; benchIdx < b.N; benchIdx++ {
actualValues, err := indexReader.LabelValues("tens", matchers...) actualValues, err := indexReader.LabelValues("b_tens", matchers...)
require.NoError(b, err) require.NoError(b, err)
require.Equal(b, 9, len(actualValues)) require.Equal(b, 9, len(actualValues))
} }
@ -401,16 +403,16 @@ func TestLabelNamesWithMatchers(t *testing.T) {
if i%10 == 0 { if i%10 == 0 {
seriesEntries = append(seriesEntries, storage.NewListSeries(labels.Labels{ seriesEntries = append(seriesEntries, storage.NewListSeries(labels.Labels{
{Name: "unique", Value: fmt.Sprintf("value%d", i)},
{Name: "tens", Value: fmt.Sprintf("value%d", i/10)}, {Name: "tens", Value: fmt.Sprintf("value%d", i/10)},
{Name: "unique", Value: fmt.Sprintf("value%d", i)},
}, []tsdbutil.Sample{sample{100, 0}})) }, []tsdbutil.Sample{sample{100, 0}}))
} }
if i%20 == 0 { if i%20 == 0 {
seriesEntries = append(seriesEntries, storage.NewListSeries(labels.Labels{ seriesEntries = append(seriesEntries, storage.NewListSeries(labels.Labels{
{Name: "unique", Value: fmt.Sprintf("value%d", i)},
{Name: "tens", Value: fmt.Sprintf("value%d", i/10)}, {Name: "tens", Value: fmt.Sprintf("value%d", i/10)},
{Name: "twenties", Value: fmt.Sprintf("value%d", i/20)}, {Name: "twenties", Value: fmt.Sprintf("value%d", i/20)},
{Name: "unique", Value: fmt.Sprintf("value%d", i)},
}, []tsdbutil.Sample{sample{100, 0}})) }, []tsdbutil.Sample{sample{100, 0}}))
} }

View file

@ -330,8 +330,8 @@ func TestSelectExemplar_DuplicateSeries(t *testing.T) {
} }
l := labels.Labels{ l := labels.Labels{
{Name: "service", Value: "asdf"},
{Name: "cluster", Value: "us-central1"}, {Name: "cluster", Value: "us-central1"},
{Name: "service", Value: "asdf"},
} }
// Lets just assume somehow the PromQL expression generated two separate lists of matchers, // Lets just assume somehow the PromQL expression generated two separate lists of matchers,

View file

@ -2228,8 +2228,8 @@ func TestHeadLabelValuesWithMatchers(t *testing.T) {
app := head.Appender(context.Background()) app := head.Appender(context.Background())
for i := 0; i < 100; i++ { for i := 0; i < 100; i++ {
_, err := app.Append(0, labels.Labels{ _, err := app.Append(0, labels.Labels{
{Name: "unique", Value: fmt.Sprintf("value%d", i)},
{Name: "tens", Value: fmt.Sprintf("value%d", i/10)}, {Name: "tens", Value: fmt.Sprintf("value%d", i/10)},
{Name: "unique", Value: fmt.Sprintf("value%d", i)},
}, 100, 0) }, 100, 0)
require.NoError(t, err) require.NoError(t, err)
} }
@ -2295,17 +2295,17 @@ func TestHeadLabelNamesWithMatchers(t *testing.T) {
if i%10 == 0 { if i%10 == 0 {
_, err := app.Append(0, labels.Labels{ _, err := app.Append(0, labels.Labels{
{Name: "unique", Value: fmt.Sprintf("value%d", i)},
{Name: "tens", Value: fmt.Sprintf("value%d", i/10)}, {Name: "tens", Value: fmt.Sprintf("value%d", i/10)},
{Name: "unique", Value: fmt.Sprintf("value%d", i)},
}, 100, 0) }, 100, 0)
require.NoError(t, err) require.NoError(t, err)
} }
if i%20 == 0 { if i%20 == 0 {
_, err := app.Append(0, labels.Labels{ _, err := app.Append(0, labels.Labels{
{Name: "unique", Value: fmt.Sprintf("value%d", i)},
{Name: "tens", Value: fmt.Sprintf("value%d", i/10)}, {Name: "tens", Value: fmt.Sprintf("value%d", i/10)},
{Name: "twenties", Value: fmt.Sprintf("value%d", i/20)}, {Name: "twenties", Value: fmt.Sprintf("value%d", i/20)},
{Name: "unique", Value: fmt.Sprintf("value%d", i)},
}, 100, 0) }, 100, 0)
require.NoError(t, err) require.NoError(t, err)
} }
@ -2448,23 +2448,25 @@ func BenchmarkHeadLabelValuesWithMatchers(b *testing.B) {
metricCount := 1000000 metricCount := 1000000
for i := 0; i < metricCount; i++ { for i := 0; i < metricCount; i++ {
// Note these series are not created in sort order: 'value2' sorts after 'value10'.
// This makes a big difference to the benchmark timing.
_, err := app.Append(0, labels.Labels{ _, err := app.Append(0, labels.Labels{
{Name: "unique", Value: fmt.Sprintf("value%d", i)}, {Name: "a_unique", Value: fmt.Sprintf("value%d", i)},
{Name: "tens", Value: fmt.Sprintf("value%d", i/(metricCount/10))}, {Name: "b_tens", Value: fmt.Sprintf("value%d", i/(metricCount/10))},
{Name: "ninety", Value: fmt.Sprintf("value%d", i/(metricCount/10)/9)}, // "0" for the first 90%, then "1" {Name: "c_ninety", Value: fmt.Sprintf("value%d", i/(metricCount/10)/9)}, // "0" for the first 90%, then "1"
}, 100, 0) }, 100, 0)
require.NoError(b, err) require.NoError(b, err)
} }
require.NoError(b, app.Commit()) require.NoError(b, app.Commit())
headIdxReader := head.indexRange(0, 200) headIdxReader := head.indexRange(0, 200)
matchers := []*labels.Matcher{labels.MustNewMatcher(labels.MatchEqual, "ninety", "value0")} matchers := []*labels.Matcher{labels.MustNewMatcher(labels.MatchEqual, "c_ninety", "value0")}
b.ResetTimer() b.ResetTimer()
b.ReportAllocs() b.ReportAllocs()
for benchIdx := 0; benchIdx < b.N; benchIdx++ { for benchIdx := 0; benchIdx < b.N; benchIdx++ {
actualValues, err := headIdxReader.LabelValues("tens", matchers...) actualValues, err := headIdxReader.LabelValues("b_tens", matchers...)
require.NoError(b, err) require.NoError(b, err)
require.Equal(b, 9, len(actualValues)) require.Equal(b, 9, len(actualValues))
} }

View file

@ -162,7 +162,7 @@ test_metric_without_labels{instance=""} 1001 6000000
}, },
"external labels are added if not already present": { "external labels are added if not already present": {
params: "match[]={__name__=~'.%2b'}", // '%2b' is an URL-encoded '+'. params: "match[]={__name__=~'.%2b'}", // '%2b' is an URL-encoded '+'.
externalLabels: labels.Labels{{Name: "zone", Value: "ie"}, {Name: "foo", Value: "baz"}}, externalLabels: labels.Labels{{Name: "foo", Value: "baz"}, {Name: "zone", Value: "ie"}},
code: 200, code: 200,
body: `# TYPE test_metric1 untyped body: `# TYPE test_metric1 untyped
test_metric1{foo="bar",instance="i",zone="ie"} 10000 6000000 test_metric1{foo="bar",instance="i",zone="ie"} 10000 6000000