Update package promql for new labels.Labels type

We use `labels.Builder` to parse metrics, to avoid depending on the
internal implementation. This is not efficient, but the feature is only
used in tests. It wasn't efficient previously either - calling `Sort()`
after adding each label.

`createLabelsForAbsentFunction` also uses a Builder now, and gets
an extra `map` to replace the previous `Has()` usage.

Signed-off-by: Bryan Boreham <bjboreham@gmail.com>

Fix up promql to compile with changes to Labels
This commit is contained in:
Bryan Boreham 2022-03-09 22:14:58 +00:00
parent d6b97f631a
commit 56fefcd812
5 changed files with 42 additions and 40 deletions

View file

@ -1567,7 +1567,7 @@ func (ev *evaluator) eval(expr parser.Expr) (parser.Value, storage.Warnings) {
case *parser.NumberLiteral: case *parser.NumberLiteral:
return ev.rangeEval(nil, func(v []parser.Value, _ [][]EvalSeriesHelper, enh *EvalNodeHelper) (Vector, storage.Warnings) { return ev.rangeEval(nil, func(v []parser.Value, _ [][]EvalSeriesHelper, enh *EvalNodeHelper) (Vector, storage.Warnings) {
return append(enh.Out, Sample{Point: Point{V: e.Val}}), nil return append(enh.Out, Sample{Point: Point{V: e.Val}, Metric: labels.EmptyLabels()}), nil
}) })
case *parser.StringLiteral: case *parser.StringLiteral:
@ -2190,7 +2190,7 @@ func resultMetric(lhs, rhs labels.Labels, op parser.ItemType, matching *parser.V
} }
} }
ret := enh.lb.Labels(nil) ret := enh.lb.Labels(labels.EmptyLabels())
enh.resultMetric[str] = ret enh.resultMetric[str] = ret
return ret return ret
} }
@ -2230,7 +2230,7 @@ func (ev *evaluator) VectorscalarBinop(op parser.ItemType, lhs Vector, rhs Scala
} }
func dropMetricName(l labels.Labels) labels.Labels { func dropMetricName(l labels.Labels) labels.Labels {
return labels.NewBuilder(l).Del(labels.MetricName).Labels(nil) return labels.NewBuilder(l).Del(labels.MetricName).Labels(labels.EmptyLabels())
} }
// scalarBinop evaluates a binary operation between two Scalars. // scalarBinop evaluates a binary operation between two Scalars.
@ -2357,7 +2357,7 @@ func (ev *evaluator) aggregation(op parser.ItemType, grouping []string, without
} }
} }
lb := labels.NewBuilder(nil) lb := labels.NewBuilder(labels.EmptyLabels())
var buf []byte var buf []byte
for si, s := range vec { for si, s := range vec {
metric := s.Metric metric := s.Metric
@ -2365,7 +2365,7 @@ func (ev *evaluator) aggregation(op parser.ItemType, grouping []string, without
if op == parser.COUNT_VALUES { if op == parser.COUNT_VALUES {
lb.Reset(metric) lb.Reset(metric)
lb.Set(valueLabel, strconv.FormatFloat(s.V, 'f', -1, 64)) lb.Set(valueLabel, strconv.FormatFloat(s.V, 'f', -1, 64))
metric = lb.Labels(nil) metric = lb.Labels(labels.EmptyLabels())
// We've changed the metric so we have to recompute the grouping key. // We've changed the metric so we have to recompute the grouping key.
recomputeGroupingKey = true recomputeGroupingKey = true
@ -2389,7 +2389,7 @@ func (ev *evaluator) aggregation(op parser.ItemType, grouping []string, without
} else { } else {
lb.Keep(grouping...) lb.Keep(grouping...)
} }
m := lb.Labels(nil) m := lb.Labels(labels.EmptyLabels())
newAgg := &groupedAggregation{ newAgg := &groupedAggregation{
labels: m, labels: m,
value: s.V, value: s.V,

View file

@ -957,7 +957,7 @@ func funcHistogramQuantile(vals []parser.Value, args parser.Expressions, enh *Ev
if !ok { if !ok {
sample.Metric = labels.NewBuilder(sample.Metric). sample.Metric = labels.NewBuilder(sample.Metric).
Del(excludedLabels...). Del(excludedLabels...).
Labels(nil) Labels(labels.EmptyLabels())
mb = &metricWithBuckets{sample.Metric, nil} mb = &metricWithBuckets{sample.Metric, nil}
enh.signatureToMetricWithBuckets[string(enh.lblBuf)] = mb enh.signatureToMetricWithBuckets[string(enh.lblBuf)] = mb
@ -1077,7 +1077,7 @@ func funcLabelReplace(vals []parser.Value, args parser.Expressions, enh *EvalNod
if len(res) > 0 { if len(res) > 0 {
lb.Set(dst, string(res)) lb.Set(dst, string(res))
} }
outMetric = lb.Labels(nil) outMetric = lb.Labels(labels.EmptyLabels())
enh.Dmn[h] = outMetric enh.Dmn[h] = outMetric
} }
} }
@ -1145,7 +1145,7 @@ func funcLabelJoin(vals []parser.Value, args parser.Expressions, enh *EvalNodeHe
lb.Set(dst, strval) lb.Set(dst, strval)
} }
outMetric = lb.Labels(nil) outMetric = lb.Labels(labels.EmptyLabels())
enh.Dmn[h] = outMetric enh.Dmn[h] = outMetric
} }
@ -1383,7 +1383,7 @@ func (s *vectorByReverseValueHeap) Pop() interface{} {
// createLabelsForAbsentFunction returns the labels that are uniquely and exactly matched // createLabelsForAbsentFunction returns the labels that are uniquely and exactly matched
// in a given expression. It is used in the absent functions. // in a given expression. It is used in the absent functions.
func createLabelsForAbsentFunction(expr parser.Expr) labels.Labels { func createLabelsForAbsentFunction(expr parser.Expr) labels.Labels {
m := labels.Labels{} b := labels.NewBuilder(labels.EmptyLabels())
var lm []*labels.Matcher var lm []*labels.Matcher
switch n := expr.(type) { switch n := expr.(type) {
@ -1392,25 +1392,26 @@ func createLabelsForAbsentFunction(expr parser.Expr) labels.Labels {
case *parser.MatrixSelector: case *parser.MatrixSelector:
lm = n.VectorSelector.(*parser.VectorSelector).LabelMatchers lm = n.VectorSelector.(*parser.VectorSelector).LabelMatchers
default: default:
return m return labels.EmptyLabels()
} }
empty := []string{} // The 'has' map implements backwards-compatibility for historic behaviour:
// e.g. in `absent(x{job="a",job="b",foo="bar"})` then `job` is removed from the output.
// Note this gives arguably wrong behaviour for `absent(x{job="a",job="a",foo="bar"})`.
has := make(map[string]bool, len(lm))
for _, ma := range lm { for _, ma := range lm {
if ma.Name == labels.MetricName { if ma.Name == labels.MetricName {
continue continue
} }
if ma.Type == labels.MatchEqual && !m.Has(ma.Name) { if ma.Type == labels.MatchEqual && !has[ma.Name] {
m = labels.NewBuilder(m).Set(ma.Name, ma.Value).Labels(nil) b.Set(ma.Name, ma.Value)
has[ma.Name] = true
} else { } else {
empty = append(empty, ma.Name) b.Del(ma.Name)
} }
} }
for _, v := range empty { return b.Labels(labels.EmptyLabels())
m = labels.NewBuilder(m).Del(v).Labels(nil)
}
return m
} }
func stringFromArg(e parser.Expr) string { func stringFromArg(e parser.Expr) string {

View file

@ -16,13 +16,13 @@ package parser
import ( import (
"math" "math"
"sort"
"strconv" "strconv"
"time" "time"
"github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/model/value" "github.com/prometheus/prometheus/model/value"
) )
%} %}
%union { %union {
@ -32,6 +32,7 @@ import (
matcher *labels.Matcher matcher *labels.Matcher
label labels.Label label labels.Label
labels labels.Labels labels labels.Labels
lblList []labels.Label
strings []string strings []string
series []SequenceValue series []SequenceValue
uint uint64 uint uint64
@ -138,10 +139,9 @@ START_METRIC_SELECTOR
// Type definitions for grammar rules. // Type definitions for grammar rules.
%type <matchers> label_match_list %type <matchers> label_match_list
%type <matcher> label_matcher %type <matcher> label_matcher
%type <item> aggregate_op grouping_label match_op maybe_label metric_identifier unary_op at_modifier_preprocessors %type <item> aggregate_op grouping_label match_op maybe_label metric_identifier unary_op at_modifier_preprocessors
%type <labels> label_set metric
%type <labels> label_set label_set_list metric %type <lblList> label_set_list
%type <label> label_set_item %type <label> label_set_item
%type <strings> grouping_label_list grouping_labels maybe_grouping_labels %type <strings> grouping_label_list grouping_labels maybe_grouping_labels
%type <series> series_item series_values %type <series> series_item series_values
@ -567,7 +567,7 @@ label_matcher : IDENTIFIER match_op STRING
*/ */
metric : metric_identifier label_set metric : metric_identifier label_set
{ $$ = append($2, labels.Label{Name: labels.MetricName, Value: $1.Val}); sort.Sort($$) } { b := labels.NewBuilder($2); b.Set(labels.MetricName, $1.Val); $$ = b.Labels(labels.EmptyLabels()) }
| label_set | label_set
{$$ = $1} {$$ = $1}
; ;

View file

@ -9,7 +9,6 @@ import __yyfmt__ "fmt"
import ( import (
"math" "math"
"sort"
"strconv" "strconv"
"time" "time"
@ -26,6 +25,7 @@ type yySymType struct {
matcher *labels.Matcher matcher *labels.Matcher
label labels.Label label labels.Label
labels labels.Labels labels labels.Labels
lblList []labels.Label
strings []string strings []string
series []SequenceValue series []SequenceValue
uint uint64 uint uint64
@ -458,7 +458,7 @@ var yyPact = [...]int{
var yyPgo = [...]int{ var yyPgo = [...]int{
0, 267, 7, 265, 2, 264, 262, 164, 261, 257, 0, 267, 7, 265, 2, 264, 262, 164, 261, 257,
115, 253, 181, 8, 252, 4, 5, 251, 250, 0, 115, 181, 253, 8, 252, 4, 5, 251, 250, 0,
23, 248, 6, 247, 246, 245, 10, 64, 244, 239, 23, 248, 6, 247, 246, 245, 10, 64, 244, 239,
1, 231, 230, 9, 217, 21, 214, 213, 205, 201, 1, 231, 230, 9, 217, 21, 214, 213, 205, 201,
198, 196, 189, 188, 206, 3, 180, 165, 127, 198, 196, 189, 188, 206, 3, 180, 165, 127,
@ -474,10 +474,10 @@ var yyR1 = [...]int{
31, 33, 33, 32, 32, 32, 40, 38, 38, 38, 31, 33, 33, 32, 32, 32, 40, 38, 38, 38,
24, 24, 24, 9, 9, 36, 42, 42, 42, 42, 24, 24, 24, 9, 9, 36, 42, 42, 42, 42,
42, 43, 44, 44, 44, 35, 35, 35, 1, 1, 42, 43, 44, 44, 44, 35, 35, 35, 1, 1,
1, 2, 2, 2, 2, 12, 12, 7, 7, 7, 1, 2, 2, 2, 2, 11, 11, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 10,
10, 10, 10, 11, 11, 11, 13, 13, 13, 13, 10, 10, 10, 12, 12, 12, 13, 13, 13, 13,
48, 18, 18, 18, 18, 17, 17, 17, 17, 17, 48, 18, 18, 18, 18, 17, 17, 17, 17, 17,
21, 21, 21, 3, 3, 3, 3, 3, 3, 3, 21, 21, 21, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 6, 6, 6, 6, 6,
@ -513,14 +513,14 @@ var yyR2 = [...]int{
} }
var yyChk = [...]int{ var yyChk = [...]int{
-1000, -47, 75, 76, 77, 78, 2, 10, -12, -7, -1000, -47, 75, 76, 77, 78, 2, 10, -11, -7,
-10, 47, 48, 62, 49, 50, 51, 12, 32, 33, -10, 47, 48, 62, 49, 50, 51, 12, 32, 33,
36, 52, 16, 53, 66, 54, 55, 56, 57, 58, 36, 52, 16, 53, 66, 54, 55, 56, 57, 58,
68, 71, 72, 13, -48, -12, 10, -30, -25, -28, 68, 71, 72, 13, -48, -11, 10, -30, -25, -28,
-31, -36, -37, -38, -40, -41, -42, -43, -44, -24, -31, -36, -37, -38, -40, -41, -42, -43, -44, -24,
-3, 12, 17, 15, 23, -8, -7, -35, 47, 48, -3, 12, 17, 15, 23, -8, -7, -35, 47, 48,
49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
26, 42, 13, -44, -10, -11, 18, -13, 12, 2, 26, 42, 13, -44, -10, -12, 18, -13, 12, 2,
-18, 2, 26, 44, 27, 28, 30, 31, 32, 33, -18, 2, 26, 44, 27, 28, 30, 31, 32, 33,
34, 35, 36, 37, 38, 39, 41, 42, 66, 43, 34, 35, 36, 37, 38, 39, 41, 42, 66, 43,
14, -26, -33, 2, 62, 68, 15, -33, -30, -30, 14, -26, -33, 2, 62, 68, 15, -33, -30, -30,
@ -1492,8 +1492,9 @@ yydefault:
yyDollar = yyS[yypt-2 : yypt+1] yyDollar = yyS[yypt-2 : yypt+1]
//line promql/parser/generated_parser.y:570 //line promql/parser/generated_parser.y:570
{ {
yyVAL.labels = append(yyDollar[2].labels, labels.Label{Name: labels.MetricName, Value: yyDollar[1].item.Val}) b := labels.NewBuilder(yyDollar[2].labels)
sort.Sort(yyVAL.labels) b.Set(labels.MetricName, yyDollar[1].item.Val)
yyVAL.labels = b.Labels(labels.EmptyLabels())
} }
case 96: case 96:
yyDollar = yyS[yypt-1 : yypt+1] yyDollar = yyS[yypt-1 : yypt+1]
@ -1505,13 +1506,13 @@ yydefault:
yyDollar = yyS[yypt-3 : yypt+1] yyDollar = yyS[yypt-3 : yypt+1]
//line promql/parser/generated_parser.y:579 //line promql/parser/generated_parser.y:579
{ {
yyVAL.labels = labels.New(yyDollar[2].labels...) yyVAL.labels = labels.New(yyDollar[2].lblList...)
} }
case 120: case 120:
yyDollar = yyS[yypt-4 : yypt+1] yyDollar = yyS[yypt-4 : yypt+1]
//line promql/parser/generated_parser.y:581 //line promql/parser/generated_parser.y:581
{ {
yyVAL.labels = labels.New(yyDollar[2].labels...) yyVAL.labels = labels.New(yyDollar[2].lblList...)
} }
case 121: case 121:
yyDollar = yyS[yypt-2 : yypt+1] yyDollar = yyS[yypt-2 : yypt+1]
@ -1529,20 +1530,20 @@ yydefault:
yyDollar = yyS[yypt-3 : yypt+1] yyDollar = yyS[yypt-3 : yypt+1]
//line promql/parser/generated_parser.y:589 //line promql/parser/generated_parser.y:589
{ {
yyVAL.labels = append(yyDollar[1].labels, yyDollar[3].label) yyVAL.lblList = append(yyDollar[1].lblList, yyDollar[3].label)
} }
case 124: case 124:
yyDollar = yyS[yypt-1 : yypt+1] yyDollar = yyS[yypt-1 : yypt+1]
//line promql/parser/generated_parser.y:591 //line promql/parser/generated_parser.y:591
{ {
yyVAL.labels = []labels.Label{yyDollar[1].label} yyVAL.lblList = []labels.Label{yyDollar[1].label}
} }
case 125: case 125:
yyDollar = yyS[yypt-2 : yypt+1] yyDollar = yyS[yypt-2 : yypt+1]
//line promql/parser/generated_parser.y:593 //line promql/parser/generated_parser.y:593
{ {
yylex.(*parser).unexpected("label set", "\",\" or \"}\"") yylex.(*parser).unexpected("label set", "\",\" or \"}\"")
yyVAL.labels = yyDollar[1].labels yyVAL.lblList = yyDollar[1].lblList
} }
case 126: case 126:
yyDollar = yyS[yypt-3 : yypt+1] yyDollar = yyS[yypt-3 : yypt+1]

View file

@ -202,7 +202,7 @@ func (t *Test) parseEval(lines []string, i int) (int, *evalCmd, error) {
break break
} }
if f, err := parseNumber(defLine); err == nil { if f, err := parseNumber(defLine); err == nil {
cmd.expect(0, nil, parser.SequenceValue{Value: f}) cmd.expect(0, labels.EmptyLabels(), parser.SequenceValue{Value: f})
break break
} }
metric, vals, err := parser.ParseSeriesDesc(defLine) metric, vals, err := parser.ParseSeriesDesc(defLine)
@ -371,7 +371,7 @@ func (ev *evalCmd) String() string {
// expect adds a new metric with a sequence of values to the set of expected // expect adds a new metric with a sequence of values to the set of expected
// results for the query. // results for the query.
func (ev *evalCmd) expect(pos int, m labels.Labels, vals ...parser.SequenceValue) { func (ev *evalCmd) expect(pos int, m labels.Labels, vals ...parser.SequenceValue) {
if m == nil { if m.IsEmpty() {
ev.expected[0] = entry{pos: pos, vals: vals} ev.expected[0] = entry{pos: pos, vals: vals}
return return
} }