mirror of https://github.com/prometheus/prometheus
Merge pull request #12145 from bboreham/fix-label-builder
labels: cope with mutating Builder during Range callpull/11900/head
commit
a494c44746
|
@ -545,9 +545,12 @@ func (b *Builder) Get(n string) string {
|
|||
}
|
||||
|
||||
// Range calls f on each label in the Builder.
|
||||
// If f calls Set or Del on b then this may affect what callbacks subsequently happen.
|
||||
func (b *Builder) Range(f func(l Label)) {
|
||||
origAdd, origDel := b.add, b.del
|
||||
// Stack-based arrays to avoid heap allocation in most cases.
|
||||
var addStack [1024]Label
|
||||
var delStack [1024]string
|
||||
// Take a copy of add and del, so they are unaffected by calls to Set() or Del().
|
||||
origAdd, origDel := append(addStack[:0], b.add...), append(delStack[:0], b.del...)
|
||||
b.base.Range(func(l Label) {
|
||||
if !slices.Contains(origDel, l.Name) && !contains(origAdd, l.Name) {
|
||||
f(l)
|
||||
|
|
|
@ -599,9 +599,12 @@ func (b *Builder) Get(n string) string {
|
|||
}
|
||||
|
||||
// Range calls f on each label in the Builder.
|
||||
// If f calls Set or Del on b then this may affect what callbacks subsequently happen.
|
||||
func (b *Builder) Range(f func(l Label)) {
|
||||
origAdd, origDel := b.add, b.del
|
||||
// Stack-based arrays to avoid heap allocation in most cases.
|
||||
var addStack [1024]Label
|
||||
var delStack [1024]string
|
||||
// Take a copy of add and del, so they are unaffected by calls to Set() or Del().
|
||||
origAdd, origDel := append(addStack[:0], b.add...), append(delStack[:0], b.del...)
|
||||
b.base.Range(func(l Label) {
|
||||
if !slices.Contains(origDel, l.Name) && !contains(origAdd, l.Name) {
|
||||
f(l)
|
||||
|
|
|
@ -529,6 +529,11 @@ func TestBuilder(t *testing.T) {
|
|||
base: FromStrings("aaa", "111"),
|
||||
want: FromStrings("aaa", "111"),
|
||||
},
|
||||
{
|
||||
base: FromStrings("aaa", "111", "bbb", "222", "ccc", "333"),
|
||||
set: []Label{{"aaa", "444"}, {"bbb", "555"}, {"ccc", "666"}},
|
||||
want: FromStrings("aaa", "444", "bbb", "555", "ccc", "666"),
|
||||
},
|
||||
{
|
||||
base: FromStrings("aaa", "111", "bbb", "222", "ccc", "333"),
|
||||
del: []string{"bbb"},
|
||||
|
@ -591,7 +596,15 @@ func TestBuilder(t *testing.T) {
|
|||
b.Keep(tcase.keep...)
|
||||
}
|
||||
b.Del(tcase.del...)
|
||||
require.Equal(t, tcase.want, b.Labels(tcase.base))
|
||||
require.Equal(t, tcase.want, b.Labels(EmptyLabels()))
|
||||
|
||||
// Check what happens when we call Range and mutate the builder.
|
||||
b.Range(func(l Label) {
|
||||
if l.Name == "aaa" || l.Name == "bbb" {
|
||||
b.Del(l.Name)
|
||||
}
|
||||
})
|
||||
require.Equal(t, tcase.want.BytesWithoutLabels(nil, "aaa", "bbb"), b.Labels(tcase.base).Bytes(nil))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue