diff --git a/CHANGELOG.md b/CHANGELOG.md index cccbae7dd5..bf725d9665 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 2.43.0-rc.1 / 2023-03-16 + +* [BUGFIX] Fixed a bug where changes in the Builder's Range function could lead to skipped labels during iteration (#12145) + ## 2.43.0-rc.0 / 2023-03-09 We are working on some performance improvements in Prometheus, which are only diff --git a/VERSION b/VERSION index 1a38590b27..a55e12bb97 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.43.0-rc.0 +2.43.0-rc.1 diff --git a/model/labels/labels.go b/model/labels/labels.go index 5e06e3b8da..6de001c3ce 100644 --- a/model/labels/labels.go +++ b/model/labels/labels.go @@ -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) diff --git a/model/labels/labels_string.go b/model/labels/labels_string.go index 6fe14bedc2..98db29d254 100644 --- a/model/labels/labels_string.go +++ b/model/labels/labels_string.go @@ -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) diff --git a/model/labels/labels_test.go b/model/labels/labels_test.go index 4832be3375..588a84b984 100644 --- a/model/labels/labels_test.go +++ b/model/labels/labels_test.go @@ -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)) }) } } diff --git a/web/ui/module/codemirror-promql/package.json b/web/ui/module/codemirror-promql/package.json index 027029c15a..8d7a73ec70 100644 --- a/web/ui/module/codemirror-promql/package.json +++ b/web/ui/module/codemirror-promql/package.json @@ -1,6 +1,6 @@ { "name": "@prometheus-io/codemirror-promql", - "version": "0.43.0-rc.0", + "version": "0.43.0-rc.1", "description": "a CodeMirror mode for the PromQL language", "types": "dist/esm/index.d.ts", "module": "dist/esm/index.js", @@ -29,7 +29,7 @@ }, "homepage": "https://github.com/prometheus/prometheus/blob/main/web/ui/module/codemirror-promql/README.md", "dependencies": { - "@prometheus-io/lezer-promql": "0.43.0-rc.0", + "@prometheus-io/lezer-promql": "0.43.0-rc.1", "lru-cache": "^6.0.0" }, "devDependencies": { diff --git a/web/ui/module/lezer-promql/package.json b/web/ui/module/lezer-promql/package.json index b3f5ccceeb..0fb3bda0e8 100644 --- a/web/ui/module/lezer-promql/package.json +++ b/web/ui/module/lezer-promql/package.json @@ -1,6 +1,6 @@ { "name": "@prometheus-io/lezer-promql", - "version": "0.43.0-rc.0", + "version": "0.43.0-rc.1", "description": "lezer-based PromQL grammar", "main": "dist/index.cjs", "type": "module", diff --git a/web/ui/package-lock.json b/web/ui/package-lock.json index 6ff46f054e..736c438fd7 100644 --- a/web/ui/package-lock.json +++ b/web/ui/package-lock.json @@ -28,10 +28,10 @@ }, "module/codemirror-promql": { "name": "@prometheus-io/codemirror-promql", - "version": "0.43.0-rc.0", + "version": "0.43.0-rc.1", "license": "Apache-2.0", "dependencies": { - "@prometheus-io/lezer-promql": "0.43.0-rc.0", + "@prometheus-io/lezer-promql": "0.43.0-rc.1", "lru-cache": "^6.0.0" }, "devDependencies": { @@ -61,7 +61,7 @@ }, "module/lezer-promql": { "name": "@prometheus-io/lezer-promql", - "version": "0.43.0-rc.0", + "version": "0.43.0-rc.1", "license": "Apache-2.0", "devDependencies": { "@lezer/generator": "^1.2.2", @@ -20763,7 +20763,7 @@ }, "react-app": { "name": "@prometheus-io/app", - "version": "0.43.0-rc.0", + "version": "0.43.0-rc.1", "dependencies": { "@codemirror/autocomplete": "^6.4.0", "@codemirror/commands": "^6.2.0", @@ -20781,7 +20781,7 @@ "@lezer/lr": "^1.3.1", "@nexucis/fuzzy": "^0.4.1", "@nexucis/kvsearch": "^0.8.1", - "@prometheus-io/codemirror-promql": "0.43.0-rc.0", + "@prometheus-io/codemirror-promql": "0.43.0-rc.1", "bootstrap": "^4.6.2", "css.escape": "^1.5.1", "downshift": "^7.2.0", @@ -23417,7 +23417,7 @@ "@lezer/lr": "^1.3.1", "@nexucis/fuzzy": "^0.4.1", "@nexucis/kvsearch": "^0.8.1", - "@prometheus-io/codemirror-promql": "0.43.0-rc.0", + "@prometheus-io/codemirror-promql": "0.43.0-rc.1", "@testing-library/react-hooks": "^7.0.2", "@types/enzyme": "^3.10.12", "@types/flot": "0.0.32", @@ -23468,7 +23468,7 @@ "@lezer/common": "^1.0.2", "@lezer/highlight": "^1.1.3", "@lezer/lr": "^1.3.1", - "@prometheus-io/lezer-promql": "0.43.0-rc.0", + "@prometheus-io/lezer-promql": "0.43.0-rc.1", "@types/lru-cache": "^5.1.1", "isomorphic-fetch": "^3.0.0", "lru-cache": "^6.0.0", diff --git a/web/ui/react-app/package.json b/web/ui/react-app/package.json index 30ebd4922e..20f5819bb9 100644 --- a/web/ui/react-app/package.json +++ b/web/ui/react-app/package.json @@ -1,6 +1,6 @@ { "name": "@prometheus-io/app", - "version": "0.43.0-rc.0", + "version": "0.43.0-rc.1", "private": true, "dependencies": { "@codemirror/autocomplete": "^6.4.0", @@ -19,7 +19,7 @@ "@lezer/common": "^1.0.2", "@nexucis/fuzzy": "^0.4.1", "@nexucis/kvsearch": "^0.8.1", - "@prometheus-io/codemirror-promql": "0.43.0-rc.0", + "@prometheus-io/codemirror-promql": "0.43.0-rc.1", "bootstrap": "^4.6.2", "css.escape": "^1.5.1", "downshift": "^7.2.0",