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:
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:
@ -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
return ret
}
@ -2230,7 +2230,7 @@ func (ev *evaluator) VectorscalarBinop(op parser.ItemType, lhs Vector, rhs Scala
}
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.
@ -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
for si, s := range vec {
metric := s.Metric
@ -2365,7 +2365,7 @@ func (ev *evaluator) aggregation(op parser.ItemType, grouping []string, without
if op == parser.COUNT_VALUES {
lb.Reset(metric)
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.
recomputeGroupingKey = true
@ -2389,7 +2389,7 @@ func (ev *evaluator) aggregation(op parser.ItemType, grouping []string, without
} else {
lb.Keep(grouping...)
}
m := lb.Labels(nil)
m := lb.Labels(labels.EmptyLabels())
newAgg := &groupedAggregation{
labels: m,
value: s.V,

View File

@ -957,7 +957,7 @@ func funcHistogramQuantile(vals []parser.Value, args parser.Expressions, enh *Ev
if !ok {
sample.Metric = labels.NewBuilder(sample.Metric).
Del(excludedLabels...).
Labels(nil)
Labels(labels.EmptyLabels())
mb = &metricWithBuckets{sample.Metric, nil}
enh.signatureToMetricWithBuckets[string(enh.lblBuf)] = mb
@ -1077,7 +1077,7 @@ func funcLabelReplace(vals []parser.Value, args parser.Expressions, enh *EvalNod
if len(res) > 0 {
lb.Set(dst, string(res))
}
outMetric = lb.Labels(nil)
outMetric = lb.Labels(labels.EmptyLabels())
enh.Dmn[h] = outMetric
}
}
@ -1145,7 +1145,7 @@ func funcLabelJoin(vals []parser.Value, args parser.Expressions, enh *EvalNodeHe
lb.Set(dst, strval)
}
outMetric = lb.Labels(nil)
outMetric = lb.Labels(labels.EmptyLabels())
enh.Dmn[h] = outMetric
}
@ -1383,7 +1383,7 @@ func (s *vectorByReverseValueHeap) Pop() interface{} {
// createLabelsForAbsentFunction returns the labels that are uniquely and exactly matched
// in a given expression. It is used in the absent functions.
func createLabelsForAbsentFunction(expr parser.Expr) labels.Labels {
m := labels.Labels{}
b := labels.NewBuilder(labels.EmptyLabels())
var lm []*labels.Matcher
switch n := expr.(type) {
@ -1392,25 +1392,26 @@ func createLabelsForAbsentFunction(expr parser.Expr) labels.Labels {
case *parser.MatrixSelector:
lm = n.VectorSelector.(*parser.VectorSelector).LabelMatchers
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 {
if ma.Name == labels.MetricName {
continue
}
if ma.Type == labels.MatchEqual && !m.Has(ma.Name) {
m = labels.NewBuilder(m).Set(ma.Name, ma.Value).Labels(nil)
if ma.Type == labels.MatchEqual && !has[ma.Name] {
b.Set(ma.Name, ma.Value)
has[ma.Name] = true
} else {
empty = append(empty, ma.Name)
b.Del(ma.Name)
}
}
for _, v := range empty {
m = labels.NewBuilder(m).Del(v).Labels(nil)
}
return m
return b.Labels(labels.EmptyLabels())
}
func stringFromArg(e parser.Expr) string {

View File

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

View File

@ -9,7 +9,6 @@ import __yyfmt__ "fmt"
import (
"math"
"sort"
"strconv"
"time"
@ -26,6 +25,7 @@ type yySymType struct {
matcher *labels.Matcher
label labels.Label
labels labels.Labels
lblList []labels.Label
strings []string
series []SequenceValue
uint uint64
@ -458,7 +458,7 @@ var yyPact = [...]int{
var yyPgo = [...]int{
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,
1, 231, 230, 9, 217, 21, 214, 213, 205, 201,
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,
24, 24, 24, 9, 9, 36, 42, 42, 42, 42,
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, 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,
21, 21, 21, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 6, 6, 6, 6, 6,
@ -513,14 +513,14 @@ var yyR2 = [...]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,
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,
-3, 12, 17, 15, 23, -8, -7, -35, 47, 48,
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,
34, 35, 36, 37, 38, 39, 41, 42, 66, 43,
14, -26, -33, 2, 62, 68, 15, -33, -30, -30,
@ -1492,8 +1492,9 @@ yydefault:
yyDollar = yyS[yypt-2 : yypt+1]
//line promql/parser/generated_parser.y:570
{
yyVAL.labels = append(yyDollar[2].labels, labels.Label{Name: labels.MetricName, Value: yyDollar[1].item.Val})
sort.Sort(yyVAL.labels)
b := labels.NewBuilder(yyDollar[2].labels)
b.Set(labels.MetricName, yyDollar[1].item.Val)
yyVAL.labels = b.Labels(labels.EmptyLabels())
}
case 96:
yyDollar = yyS[yypt-1 : yypt+1]
@ -1505,13 +1506,13 @@ yydefault:
yyDollar = yyS[yypt-3 : yypt+1]
//line promql/parser/generated_parser.y:579
{
yyVAL.labels = labels.New(yyDollar[2].labels...)
yyVAL.labels = labels.New(yyDollar[2].lblList...)
}
case 120:
yyDollar = yyS[yypt-4 : yypt+1]
//line promql/parser/generated_parser.y:581
{
yyVAL.labels = labels.New(yyDollar[2].labels...)
yyVAL.labels = labels.New(yyDollar[2].lblList...)
}
case 121:
yyDollar = yyS[yypt-2 : yypt+1]
@ -1529,20 +1530,20 @@ yydefault:
yyDollar = yyS[yypt-3 : yypt+1]
//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:
yyDollar = yyS[yypt-1 : yypt+1]
//line promql/parser/generated_parser.y:591
{
yyVAL.labels = []labels.Label{yyDollar[1].label}
yyVAL.lblList = []labels.Label{yyDollar[1].label}
}
case 125:
yyDollar = yyS[yypt-2 : yypt+1]
//line promql/parser/generated_parser.y:593
{
yylex.(*parser).unexpected("label set", "\",\" or \"}\"")
yyVAL.labels = yyDollar[1].labels
yyVAL.lblList = yyDollar[1].lblList
}
case 126:
yyDollar = yyS[yypt-3 : yypt+1]

View File

@ -202,7 +202,7 @@ func (t *Test) parseEval(lines []string, i int) (int, *evalCmd, error) {
break
}
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
}
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
// results for the query.
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}
return
}