Store function implementations independently of their signatures

Signed-off-by: Tobias Guggenmos <tguggenm@redhat.com>
This commit is contained in:
Tobias Guggenmos 2020-02-03 18:19:54 +01:00
parent ff0ea1c1ac
commit 9a1366775e
3 changed files with 87 additions and 336 deletions

View file

@ -698,7 +698,7 @@ func (ng *Engine) populateSeries(ctx context.Context, q storage.Queryable, s *pa
level.Error(ng.logger).Log("msg", "error selecting series set", "err", err)
return err
}
n.unexpandedSeriesSet = set
n.UnexpandedSeriesSet = set
case *parser.MatrixSelector:
evalRange = n.Range
@ -744,12 +744,12 @@ func checkForSeriesSetExpansion(ctx context.Context, expr parser.Expr) {
case *parser.MatrixSelector:
checkForSeriesSetExpansion(ctx, e.VectorSelector)
case *parser.VectorSelector:
if e.series == nil {
series, err := expandSeriesSet(ctx, e.unexpandedSeriesSet)
if e.Series == nil {
series, err := expandSeriesSet(ctx, e.UnexpandedSeriesSet)
if err != nil {
panic(err)
} else {
e.series = series
e.Series = series
}
}
}
@ -1003,14 +1003,14 @@ func (ev *evaluator) evalSubquery(subq *parser.SubqueryExpr) *parser.MatrixSelec
val := ev.eval(subq).(Matrix)
vs := &parser.VectorSelector{
Offset: subq.Offset,
series: make([]storage.Series, 0, len(val)),
Series: make([]storage.Series, 0, len(val)),
}
ms := &parser.MatrixSelector{
Range: subq.Range,
parser.VectorSelector: vs,
Range: subq.Range,
VectorSelector: vs,
}
for _, s := range val {
vs.series = append(vs.series, NewStorageSeries(s))
vs.Series = append(vs.Series, NewStorageSeries(s))
}
return ms
}
@ -1025,12 +1025,12 @@ func (ev *evaluator) eval(expr parser.Expr) parser.Value {
numSteps := int((ev.endTimestamp-ev.startTimestamp)/ev.interval) + 1
switch e := expr.(type) {
case *AggregateExpr:
case *parser.AggregateExpr:
unwrapParenExpr(&e.Param)
if s, ok := e.Param.(*StringLiteral); ok {
if s, ok := e.Param.(*parser.StringLiteral); ok {
return ev.rangeEval(func(v []parser.Value, enh *EvalNodeHelper) Vector {
return ev.aggregation(e.Op, e.Grouping, e.Without, s.Val, v[0].(Vector), enh)
}, e.parser.Expr)
}, e.Expr)
}
return ev.rangeEval(func(v []parser.Value, enh *EvalNodeHelper) Vector {
var param float64
@ -1038,9 +1038,9 @@ func (ev *evaluator) eval(expr parser.Expr) parser.Value {
param = v[0].(Vector)[0].V
}
return ev.aggregation(e.Op, e.Grouping, e.Without, param, v[1].(Vector), enh)
}, e.Param, e.parser.Expr)
}, e.Param, e.Expr)
case *Call:
case *parser.Call:
if e.Func.Name == "timestamp" {
// Matrix evaluation always returns the evaluation time,
// so this function needs special handling when given
@ -1048,11 +1048,13 @@ func (ev *evaluator) eval(expr parser.Expr) parser.Value {
vs, ok := e.Args[0].(*parser.VectorSelector)
if ok {
return ev.rangeEval(func(v []parser.Value, enh *EvalNodeHelper) Vector {
return e.Func.Call([]parser.Value{ev.vectorSelector(vs, enh.ts)}, e.Args, enh)
return funcTimestamp([]parser.Value{ev.vectorSelector(vs, enh.ts)}, e.Args, enh)
})
}
}
call := FunctionCalls[e.Func.Name]
// Check if the function has a matrix argument.
var matrixArgIndex int
var matrixArg bool
@ -1076,7 +1078,7 @@ func (ev *evaluator) eval(expr parser.Expr) parser.Value {
if !matrixArg {
// Does not have a matrix argument.
return ev.rangeEval(func(v []parser.Value, enh *EvalNodeHelper) Vector {
return e.Func.Call(v, e.Args, enh)
return call(v, e.Args, enh)
}, e.Args...)
}
@ -1093,7 +1095,7 @@ func (ev *evaluator) eval(expr parser.Expr) parser.Value {
}
sel := e.Args[matrixArgIndex].(*parser.MatrixSelector)
selVS := sel.parser.VectorSelector.(*parser.VectorSelector)
selVS := sel.VectorSelector.(*parser.VectorSelector)
checkForSeriesSetExpansion(ev.ctx, sel)
mat := make(Matrix, 0, len(selVS.series)) // Output matrix.

View file

@ -28,29 +28,22 @@ import (
"github.com/prometheus/prometheus/promql/parser"
)
// Function represents a function of the expression language and is
// used by function nodes.
type Function struct {
Name string
ArgTypes []parser.ValueType
Variadic int
ReturnType parser.ValueType
// vals is a list of the evaluated arguments for the function call.
// For range vectors it will be a Matrix with one series, instant vectors a
// Vector, scalars a Vector with one series whose value is the scalar
// value,and nil for strings.
// args are the original arguments to the function, where you can access
// matrixSelectors, vectorSelectors, and StringLiterals.
// enh.out is a pre-allocated empty vector that you may use to accumulate
// output before returning it. The vectors in vals should not be returned.a
// Range vector functions need only return a vector with the right value,
// the metric and timestamp are not needed.
// Instant vector functions need only return a vector with the right values and
// metrics, the timestamp are not needed.
// Scalar results should be returned as the value of a sample in a Vector.
Call func(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) Vector
}
// FunctionCall is the type of a PromQL function implementation
//
// vals is a list of the evaluated arguments for the function call.
// For range vectors it will be a Matrix with one series, instant vectors a
// Vector, scalars a Vector with one series whose value is the scalar
// value,and nil for strings.
// args are the original arguments to the function, where you can access
// matrixSelectors, vectorSelectors, and StringLiterals.
// enh.out is a pre-allocated empty vector that you may use to accumulate
// output before returning it. The vectors in vals should not be returned.a
// Range vector functions need only return a vector with the right value,
// the metric and timestamp are not needed.
// Instant vector functions need only return a vector with the right values and
// metrics, the timestamp are not needed.
// Scalar results should be returned as the value of a sample in a Vector.
type FunctionCall func(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) Vector
// === time() float64 ===
func funcTime(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) Vector {
@ -614,7 +607,7 @@ func funcHistogramQuantile(vals []parser.Value, args parser.Expressions, enh *Ev
}
}
for _, el := range inVec {
upperBound, err := strconv.parser.ParseFloat(
upperBound, err := strconv.ParseFloat(
el.Metric.Get(model.BucketLabel), 64,
)
if err != nil {
@ -877,303 +870,59 @@ func funcYear(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper)
}
// Functions is a list of all functions supported by PromQL, including their types.
var Functions = map[string]*Function{
"abs": {
Name: "abs",
ArgTypes: []parser.ValueType{parser.ValueTypeVector},
ReturnType: parser.ValueTypeVector,
Call: funcAbs,
},
"absent": {
Name: "absent",
ArgTypes: []parser.ValueType{parser.ValueTypeVector},
ReturnType: parser.ValueTypeVector,
Call: funcAbsent,
},
"absent_over_time": {
Name: "absent_over_time",
ArgTypes: []parser.ValueType{parser.ValueTypeMatrix},
ReturnType: parser.ValueTypeVector,
Call: funcAbsentOverTime,
},
"avg_over_time": {
Name: "avg_over_time",
ArgTypes: []parser.ValueType{parser.ValueTypeMatrix},
ReturnType: parser.ValueTypeVector,
Call: funcAvgOverTime,
},
"ceil": {
Name: "ceil",
ArgTypes: []parser.ValueType{parser.ValueTypeVector},
ReturnType: parser.ValueTypeVector,
Call: funcCeil,
},
"changes": {
Name: "changes",
ArgTypes: []parser.ValueType{parser.ValueTypeMatrix},
ReturnType: parser.ValueTypeVector,
Call: funcChanges,
},
"clamp_max": {
Name: "clamp_max",
ArgTypes: []parser.ValueType{parser.ValueTypeVector, parser.ValueTypeScalar},
ReturnType: parser.ValueTypeVector,
Call: funcClampMax,
},
"clamp_min": {
Name: "clamp_min",
ArgTypes: []parser.ValueType{parser.ValueTypeVector, parser.ValueTypeScalar},
ReturnType: parser.ValueTypeVector,
Call: funcClampMin,
},
"count_over_time": {
Name: "count_over_time",
ArgTypes: []parser.ValueType{parser.ValueTypeMatrix},
ReturnType: parser.ValueTypeVector,
Call: funcCountOverTime,
},
"days_in_month": {
Name: "days_in_month",
ArgTypes: []parser.ValueType{parser.ValueTypeVector},
Variadic: 1,
ReturnType: parser.ValueTypeVector,
Call: funcDaysInMonth,
},
"day_of_month": {
Name: "day_of_month",
ArgTypes: []parser.ValueType{parser.ValueTypeVector},
Variadic: 1,
ReturnType: parser.ValueTypeVector,
Call: funcDayOfMonth,
},
"day_of_week": {
Name: "day_of_week",
ArgTypes: []parser.ValueType{parser.ValueTypeVector},
Variadic: 1,
ReturnType: parser.ValueTypeVector,
Call: funcDayOfWeek,
},
"delta": {
Name: "delta",
ArgTypes: []parser.ValueType{parser.ValueTypeMatrix},
ReturnType: parser.ValueTypeVector,
Call: funcDelta,
},
"deriv": {
Name: "deriv",
ArgTypes: []parser.ValueType{parser.ValueTypeMatrix},
ReturnType: parser.ValueTypeVector,
Call: funcDeriv,
},
"exp": {
Name: "exp",
ArgTypes: []parser.ValueType{parser.ValueTypeVector},
ReturnType: parser.ValueTypeVector,
Call: funcExp,
},
"floor": {
Name: "floor",
ArgTypes: []parser.ValueType{parser.ValueTypeVector},
ReturnType: parser.ValueTypeVector,
Call: funcFloor,
},
"histogram_quantile": {
Name: "histogram_quantile",
ArgTypes: []parser.ValueType{parser.ValueTypeScalar, parser.ValueTypeVector},
ReturnType: parser.ValueTypeVector,
Call: funcHistogramQuantile,
},
"holt_winters": {
Name: "holt_winters",
ArgTypes: []parser.ValueType{parser.ValueTypeMatrix, parser.ValueTypeScalar, parser.ValueTypeScalar},
ReturnType: parser.ValueTypeVector,
Call: funcHoltWinters,
},
"hour": {
Name: "hour",
ArgTypes: []parser.ValueType{parser.ValueTypeVector},
Variadic: 1,
ReturnType: parser.ValueTypeVector,
Call: funcHour,
},
"idelta": {
Name: "idelta",
ArgTypes: []parser.ValueType{parser.ValueTypeMatrix},
ReturnType: parser.ValueTypeVector,
Call: funcIdelta,
},
"increase": {
Name: "increase",
ArgTypes: []parser.ValueType{parser.ValueTypeMatrix},
ReturnType: parser.ValueTypeVector,
Call: funcIncrease,
},
"irate": {
Name: "irate",
ArgTypes: []parser.ValueType{parser.ValueTypeMatrix},
ReturnType: parser.ValueTypeVector,
Call: funcIrate,
},
"label_replace": {
Name: "label_replace",
ArgTypes: []parser.ValueType{parser.ValueTypeVector, parser.ValueTypeString, parser.ValueTypeString, parser.ValueTypeString, parser.ValueTypeString},
ReturnType: parser.ValueTypeVector,
Call: funcLabelReplace,
},
"label_join": {
Name: "label_join",
ArgTypes: []parser.ValueType{parser.ValueTypeVector, parser.ValueTypeString, parser.ValueTypeString, parser.ValueTypeString},
Variadic: -1,
ReturnType: parser.ValueTypeVector,
Call: funcLabelJoin,
},
"ln": {
Name: "ln",
ArgTypes: []parser.ValueType{parser.ValueTypeVector},
ReturnType: parser.ValueTypeVector,
Call: funcLn,
},
"log10": {
Name: "log10",
ArgTypes: []parser.ValueType{parser.ValueTypeVector},
ReturnType: parser.ValueTypeVector,
Call: funcLog10,
},
"log2": {
Name: "log2",
ArgTypes: []parser.ValueType{parser.ValueTypeVector},
ReturnType: parser.ValueTypeVector,
Call: funcLog2,
},
"max_over_time": {
Name: "max_over_time",
ArgTypes: []parser.ValueType{parser.ValueTypeMatrix},
ReturnType: parser.ValueTypeVector,
Call: funcMaxOverTime,
},
"min_over_time": {
Name: "min_over_time",
ArgTypes: []parser.ValueType{parser.ValueTypeMatrix},
ReturnType: parser.ValueTypeVector,
Call: funcMinOverTime,
},
"minute": {
Name: "minute",
ArgTypes: []parser.ValueType{parser.ValueTypeVector},
Variadic: 1,
ReturnType: parser.ValueTypeVector,
Call: funcMinute,
},
"month": {
Name: "month",
ArgTypes: []parser.ValueType{parser.ValueTypeVector},
Variadic: 1,
ReturnType: parser.ValueTypeVector,
Call: funcMonth,
},
"predict_linear": {
Name: "predict_linear",
ArgTypes: []parser.ValueType{parser.ValueTypeMatrix, parser.ValueTypeScalar},
ReturnType: parser.ValueTypeVector,
Call: funcPredictLinear,
},
"quantile_over_time": {
Name: "quantile_over_time",
ArgTypes: []parser.ValueType{parser.ValueTypeScalar, parser.ValueTypeMatrix},
ReturnType: parser.ValueTypeVector,
Call: funcQuantileOverTime,
},
"rate": {
Name: "rate",
ArgTypes: []parser.ValueType{parser.ValueTypeMatrix},
ReturnType: parser.ValueTypeVector,
Call: funcRate,
},
"resets": {
Name: "resets",
ArgTypes: []parser.ValueType{parser.ValueTypeMatrix},
ReturnType: parser.ValueTypeVector,
Call: funcResets,
},
"round": {
Name: "round",
ArgTypes: []parser.ValueType{parser.ValueTypeVector, parser.ValueTypeScalar},
Variadic: 1,
ReturnType: parser.ValueTypeVector,
Call: funcRound,
},
"scalar": {
Name: "scalar",
ArgTypes: []parser.ValueType{parser.ValueTypeVector},
ReturnType: parser.ValueTypeScalar,
Call: funcScalar,
},
"sort": {
Name: "sort",
ArgTypes: []parser.ValueType{parser.ValueTypeVector},
ReturnType: parser.ValueTypeVector,
Call: funcSort,
},
"sort_desc": {
Name: "sort_desc",
ArgTypes: []parser.ValueType{parser.ValueTypeVector},
ReturnType: parser.ValueTypeVector,
Call: funcSortDesc,
},
"sqrt": {
Name: "sqrt",
ArgTypes: []parser.ValueType{parser.ValueTypeVector},
ReturnType: parser.ValueTypeVector,
Call: funcSqrt,
},
"stddev_over_time": {
Name: "stddev_over_time",
ArgTypes: []parser.ValueType{parser.ValueTypeMatrix},
ReturnType: parser.ValueTypeVector,
Call: funcStddevOverTime,
},
"stdvar_over_time": {
Name: "stdvar_over_time",
ArgTypes: []parser.ValueType{parser.ValueTypeMatrix},
ReturnType: parser.ValueTypeVector,
Call: funcStdvarOverTime,
},
"sum_over_time": {
Name: "sum_over_time",
ArgTypes: []parser.ValueType{parser.ValueTypeMatrix},
ReturnType: parser.ValueTypeVector,
Call: funcSumOverTime,
},
"time": {
Name: "time",
ArgTypes: []parser.ValueType{},
ReturnType: parser.ValueTypeScalar,
Call: funcTime,
},
"timestamp": {
Name: "timestamp",
ArgTypes: []parser.ValueType{parser.ValueTypeVector},
ReturnType: parser.ValueTypeVector,
Call: funcTimestamp,
},
"vector": {
Name: "vector",
ArgTypes: []parser.ValueType{parser.ValueTypeScalar},
ReturnType: parser.ValueTypeVector,
Call: funcVector,
},
"year": {
Name: "year",
ArgTypes: []parser.ValueType{parser.ValueTypeVector},
Variadic: 1,
ReturnType: parser.ValueTypeVector,
Call: funcYear,
},
var FunctionCalls = map[string]FunctionCall{
"abs": funcAbs,
"absent": funcAbsent,
"absent_over_time": funcAbsentOverTime,
"avg_over_time": funcAvgOverTime,
"ceil": funcCeil,
"changes": funcChanges,
"clamp_max": funcClampMax,
"clamp_min": funcClampMin,
"count_over_time": funcCountOverTime,
"days_in_month": funcDaysInMonth,
"day_of_month": funcDayOfMonth,
"day_of_week": funcDayOfWeek,
"delta": funcDelta,
"deriv": funcDeriv,
"exp": funcExp,
"floor": funcFloor,
"histogram_quantile": funcHistogramQuantile,
"holt_winters": funcHoltWinters,
"hour": parser.ValueTypeVector,
"idelta": funcIdelta,
"increase": funcIncrease,
"irate": funcIrate,
"label_replace": funcLabelReplace,
"label_join": funcLabelJoin,
"ln": funcLn,
"log10": funcLog10,
"log2": funcLog2,
"max_over_time": funcMaxOverTime,
"min_over_time": funcMinOverTime,
"minute": funcMinute,
"month": funcMonth,
"predict_linear": funcPredictLinear,
"quantile_over_time": funcQuantileOverTime,
"rate": funcRate,
"resets": funcResets,
"round": funcRound,
"scalar": funcScalar,
"sort": funcSort,
"sort_desc": funcSortDesc,
"sqrt": funcSqrt,
"stddev_over_time": funcStddevOverTime,
"stdvar_over_time": funcStdvarOverTime,
"sum_over_time": funcSumOverTime,
"time": funcTime,
"timestamp": funcTimestamp,
"vector": funcVector,
"year": funcYear,
}
// getFunction returns a predefined Function object for the given name.
func getFunction(name string) (*Function, bool) {
function, ok := Functions[name]
func getFunctionCall(name string) (FunctionCall, bool) {
function, ok := FunctionCalls[name]
return function, ok
}

View file

@ -168,8 +168,8 @@ type VectorSelector struct {
LabelMatchers []*labels.Matcher
// The unexpanded seriesSet populated at query preparation time.
unexpandedSeriesSet storage.SeriesSet
series []storage.Series
UnexpandedSeriesSet storage.SeriesSet
Series []storage.Series
PosRange PositionRange
}