promql: faster range-query of label_replace and label_join
These functions act on the labels only, so don't need to go step by step over the samples in a range query. Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
This commit is contained in:
parent
805d51f6d3
commit
fdd5b85e06
|
@ -1409,6 +1409,15 @@ func (ev *evaluator) eval(expr parser.Expr) (parser.Value, annotations.Annotatio
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Special handling for functions that work on series not samples.
|
||||||
|
switch e.Func.Name {
|
||||||
|
case "label_replace":
|
||||||
|
return ev.evalLabelReplace(e.Args)
|
||||||
|
case "label_join":
|
||||||
|
return ev.evalLabelJoin(e.Args)
|
||||||
|
}
|
||||||
|
|
||||||
if !matrixArg {
|
if !matrixArg {
|
||||||
// Does not have a matrix argument.
|
// Does not have a matrix argument.
|
||||||
return ev.rangeEval(nil, func(v []parser.Value, _ [][]EvalSeriesHelper, enh *EvalNodeHelper) (Vector, annotations.Annotations) {
|
return ev.rangeEval(nil, func(v []parser.Value, _ [][]EvalSeriesHelper, enh *EvalNodeHelper) (Vector, annotations.Annotations) {
|
||||||
|
|
|
@ -1321,59 +1321,47 @@ func funcChanges(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelp
|
||||||
return append(enh.Out, Sample{F: float64(changes)}), nil
|
return append(enh.Out, Sample{F: float64(changes)}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// === label_replace(Vector parser.ValueTypeVector, dst_label, replacement, src_labelname, regex parser.ValueTypeString) (Vector, Annotations) ===
|
// label_replace function operates only on series; does not look at timestamps or values.
|
||||||
func funcLabelReplace(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) {
|
func (ev *evaluator) evalLabelReplace(args parser.Expressions) (parser.Value, annotations.Annotations) {
|
||||||
var (
|
var (
|
||||||
vector = vals[0].(Vector)
|
|
||||||
dst = stringFromArg(args[1])
|
dst = stringFromArg(args[1])
|
||||||
repl = stringFromArg(args[2])
|
repl = stringFromArg(args[2])
|
||||||
src = stringFromArg(args[3])
|
src = stringFromArg(args[3])
|
||||||
regexStr = stringFromArg(args[4])
|
regexStr = stringFromArg(args[4])
|
||||||
)
|
)
|
||||||
|
|
||||||
if enh.regex == nil {
|
regex, err := regexp.Compile("^(?:" + regexStr + ")$")
|
||||||
var err error
|
if err != nil {
|
||||||
enh.regex, err = regexp.Compile("^(?:" + regexStr + ")$")
|
panic(fmt.Errorf("invalid regular expression in label_replace(): %s", regexStr))
|
||||||
if err != nil {
|
}
|
||||||
panic(fmt.Errorf("invalid regular expression in label_replace(): %s", regexStr))
|
if !model.LabelNameRE.MatchString(dst) {
|
||||||
}
|
panic(fmt.Errorf("invalid destination label name in label_replace(): %s", dst))
|
||||||
if !model.LabelNameRE.MatchString(dst) {
|
|
||||||
panic(fmt.Errorf("invalid destination label name in label_replace(): %s", dst))
|
|
||||||
}
|
|
||||||
enh.Dmn = make(map[uint64]labels.Labels, len(enh.Out))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, el := range vector {
|
val, ws := ev.eval(args[0])
|
||||||
h := el.Metric.Hash()
|
matrix := val.(Matrix)
|
||||||
var outMetric labels.Labels
|
lb := labels.NewBuilder(labels.EmptyLabels())
|
||||||
if l, ok := enh.Dmn[h]; ok {
|
|
||||||
outMetric = l
|
|
||||||
} else {
|
|
||||||
srcVal := el.Metric.Get(src)
|
|
||||||
indexes := enh.regex.FindStringSubmatchIndex(srcVal)
|
|
||||||
if indexes == nil {
|
|
||||||
// If there is no match, no replacement should take place.
|
|
||||||
outMetric = el.Metric
|
|
||||||
enh.Dmn[h] = outMetric
|
|
||||||
} else {
|
|
||||||
res := enh.regex.ExpandString([]byte{}, repl, srcVal, indexes)
|
|
||||||
|
|
||||||
lb := labels.NewBuilder(el.Metric).Del(dst)
|
for i, el := range matrix {
|
||||||
if len(res) > 0 {
|
srcVal := el.Metric.Get(src)
|
||||||
lb.Set(dst, string(res))
|
indexes := regex.FindStringSubmatchIndex(srcVal)
|
||||||
}
|
if indexes != nil { // Only replace when regexp matches.
|
||||||
outMetric = lb.Labels()
|
res := regex.ExpandString([]byte{}, repl, srcVal, indexes)
|
||||||
enh.Dmn[h] = outMetric
|
lb.Reset(el.Metric)
|
||||||
}
|
lb.Set(dst, string(res))
|
||||||
|
matrix[i].Metric = lb.Labels()
|
||||||
}
|
}
|
||||||
|
|
||||||
enh.Out = append(enh.Out, Sample{
|
|
||||||
Metric: outMetric,
|
|
||||||
F: el.F,
|
|
||||||
H: el.H,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
return enh.Out, nil
|
if matrix.ContainsSameLabelset() {
|
||||||
|
ev.errorf("vector cannot contain metrics with the same labelset")
|
||||||
|
}
|
||||||
|
|
||||||
|
return matrix, ws
|
||||||
|
}
|
||||||
|
|
||||||
|
// === label_replace(Vector parser.ValueTypeVector, dst_label, replacement, src_labelname, regex parser.ValueTypeString) (Vector, Annotations) ===
|
||||||
|
func funcLabelReplace(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) {
|
||||||
|
panic("funcLabelReplace wrong implementation called")
|
||||||
}
|
}
|
||||||
|
|
||||||
// === Vector(s Scalar) (Vector, Annotations) ===
|
// === Vector(s Scalar) (Vector, Annotations) ===
|
||||||
|
@ -1385,19 +1373,13 @@ func funcVector(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelpe
|
||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// === label_join(vector model.ValVector, dest_labelname, separator, src_labelname...) (Vector, Annotations) ===
|
// label_join function operates only on series; does not look at timestamps or values.
|
||||||
func funcLabelJoin(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) {
|
func (ev *evaluator) evalLabelJoin(args parser.Expressions) (parser.Value, annotations.Annotations) {
|
||||||
var (
|
var (
|
||||||
vector = vals[0].(Vector)
|
|
||||||
dst = stringFromArg(args[1])
|
dst = stringFromArg(args[1])
|
||||||
sep = stringFromArg(args[2])
|
sep = stringFromArg(args[2])
|
||||||
srcLabels = make([]string, len(args)-3)
|
srcLabels = make([]string, len(args)-3)
|
||||||
)
|
)
|
||||||
|
|
||||||
if enh.Dmn == nil {
|
|
||||||
enh.Dmn = make(map[uint64]labels.Labels, len(enh.Out))
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 3; i < len(args); i++ {
|
for i := 3; i < len(args); i++ {
|
||||||
src := stringFromArg(args[i])
|
src := stringFromArg(args[i])
|
||||||
if !model.LabelName(src).IsValid() {
|
if !model.LabelName(src).IsValid() {
|
||||||
|
@ -1406,42 +1388,27 @@ func funcLabelJoin(vals []parser.Value, args parser.Expressions, enh *EvalNodeHe
|
||||||
srcLabels[i-3] = src
|
srcLabels[i-3] = src
|
||||||
}
|
}
|
||||||
|
|
||||||
if !model.LabelName(dst).IsValid() {
|
val, ws := ev.eval(args[0])
|
||||||
panic(fmt.Errorf("invalid destination label name in label_join(): %s", dst))
|
matrix := val.(Matrix)
|
||||||
}
|
|
||||||
|
|
||||||
srcVals := make([]string, len(srcLabels))
|
srcVals := make([]string, len(srcLabels))
|
||||||
for _, el := range vector {
|
lb := labels.NewBuilder(labels.EmptyLabels())
|
||||||
h := el.Metric.Hash()
|
|
||||||
var outMetric labels.Labels
|
|
||||||
if l, ok := enh.Dmn[h]; ok {
|
|
||||||
outMetric = l
|
|
||||||
} else {
|
|
||||||
|
|
||||||
for i, src := range srcLabels {
|
for i, el := range matrix {
|
||||||
srcVals[i] = el.Metric.Get(src)
|
for i, src := range srcLabels {
|
||||||
}
|
srcVals[i] = el.Metric.Get(src)
|
||||||
|
|
||||||
lb := labels.NewBuilder(el.Metric)
|
|
||||||
|
|
||||||
strval := strings.Join(srcVals, sep)
|
|
||||||
if strval == "" {
|
|
||||||
lb.Del(dst)
|
|
||||||
} else {
|
|
||||||
lb.Set(dst, strval)
|
|
||||||
}
|
|
||||||
|
|
||||||
outMetric = lb.Labels()
|
|
||||||
enh.Dmn[h] = outMetric
|
|
||||||
}
|
}
|
||||||
|
strval := strings.Join(srcVals, sep)
|
||||||
enh.Out = append(enh.Out, Sample{
|
lb.Reset(el.Metric)
|
||||||
Metric: outMetric,
|
lb.Set(dst, strval)
|
||||||
F: el.F,
|
matrix[i].Metric = lb.Labels()
|
||||||
H: el.H,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
return enh.Out, nil
|
|
||||||
|
return matrix, ws
|
||||||
|
}
|
||||||
|
|
||||||
|
// === label_join(vector model.ValVector, dest_labelname, separator, src_labelname...) (Vector, Annotations) ===
|
||||||
|
func funcLabelJoin(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) {
|
||||||
|
panic("funcLabelReplace wrong implementation called")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Common code for date related functions.
|
// Common code for date related functions.
|
||||||
|
|
Loading…
Reference in New Issue