diff --git a/promql/engine.go b/promql/engine.go index 253dc4245..a343074df 100644 --- a/promql/engine.go +++ b/promql/engine.go @@ -120,7 +120,7 @@ func (r *Result) Matrix() (model.Matrix, error) { } v, ok := r.Value.(model.Matrix) if !ok { - return nil, fmt.Errorf("query result is not a matrix") + return nil, fmt.Errorf("query result is not a range vector") } return v, nil } @@ -286,7 +286,7 @@ func (ng *Engine) NewRangeQuery(qs string, start, end model.Time, interval time. return nil, err } if expr.Type() != model.ValVector && expr.Type() != model.ValScalar { - return nil, fmt.Errorf("invalid expression type %q for range query, must be scalar or vector", expr.Type()) + return nil, fmt.Errorf("invalid expression type %q for range query, must be scalar or instant vector", documentedType(expr.Type())) } qry := ng.newQuery(expr, start, end, interval) qry.q = qs @@ -581,7 +581,7 @@ func (ev *evaluator) evalScalar(e Expr) *model.Scalar { val := ev.eval(e) sv, ok := val.(*model.Scalar) if !ok { - ev.errorf("expected scalar but got %s", val.Type()) + ev.errorf("expected scalar but got %s", documentedType(val.Type())) } return sv } @@ -591,7 +591,7 @@ func (ev *evaluator) evalVector(e Expr) vector { val := ev.eval(e) vec, ok := val.(vector) if !ok { - ev.errorf("expected vector but got %s", val.Type()) + ev.errorf("expected instant vector but got %s", documentedType(val.Type())) } return vec } @@ -612,11 +612,13 @@ func (ev *evaluator) evalFloat(e Expr) float64 { } // evalMatrix attempts to evaluate e into a matrix and errors otherwise. +// The error message uses the term "range vector" to match the user facing +// documentation. func (ev *evaluator) evalMatrix(e Expr) matrix { val := ev.eval(e) mat, ok := val.(matrix) if !ok { - ev.errorf("expected matrix but got %s", val.Type()) + ev.errorf("expected range vector but got %s", documentedType(val.Type())) } return mat } @@ -626,7 +628,7 @@ func (ev *evaluator) evalString(e Expr) *model.String { val := ev.eval(e) sv, ok := val.(*model.String) if !ok { - ev.errorf("expected string but got %s", val.Type()) + ev.errorf("expected string but got %s", documentedType(val.Type())) } return sv } @@ -635,7 +637,7 @@ func (ev *evaluator) evalString(e Expr) *model.String { func (ev *evaluator) evalOneOf(e Expr, t1, t2 model.ValueType) model.Value { val := ev.eval(e) if val.Type() != t1 && val.Type() != t2 { - ev.errorf("expected %s or %s but got %s", t1, t2, val.Type()) + ev.errorf("expected %s or %s but got %s", documentedType(t1), documentedType(t2), documentedType(val.Type())) } return val } @@ -1337,3 +1339,16 @@ func (g *queryGate) Done() { panic("engine.queryGate.Done: more operations done than started") } } + +// documentedType returns the internal type to the equivalent +// user facing terminology as defined in the documentation. +func documentedType(t model.ValueType) string { + switch t.String() { + case "vector": + return "instant vector" + case "matrix": + return "range vector" + default: + return t.String() + } +} diff --git a/promql/parse.go b/promql/parse.go index 71ad87de0..891d46c90 100644 --- a/promql/parse.go +++ b/promql/parse.go @@ -990,7 +990,7 @@ func (p *parser) vectorSelector(name string) *VectorSelector { func (p *parser) expectType(node Node, want model.ValueType, context string) { t := p.checkType(node) if t != want { - p.errorf("expected type %s in %s, got %s", want, context, t) + p.errorf("expected type %s in %s, got %s", documentedType(want), context, documentedType(t)) } } @@ -1024,20 +1024,20 @@ func (p *parser) checkType(node Node) (typ model.ValueType) { case *EvalStmt: ty := p.checkType(n.Expr) if ty == model.ValNone { - p.errorf("evaluation statement must have a valid expression type but got %s", ty) + p.errorf("evaluation statement must have a valid expression type but got %s", documentedType(ty)) } case *RecordStmt: ty := p.checkType(n.Expr) if ty != model.ValVector && ty != model.ValScalar { - p.errorf("record statement must have a valid expression of type vector or scalar but got %s", ty) + p.errorf("record statement must have a valid expression of type instant vector or scalar but got %s", documentedType(ty)) } case Expressions: for _, e := range n { ty := p.checkType(e) if ty == model.ValNone { - p.errorf("expression must have a valid expression type but got %s", ty) + p.errorf("expression must have a valid expression type but got %s", documentedType(ty)) } } case *AggregateExpr: @@ -1060,12 +1060,12 @@ func (p *parser) checkType(node Node) (typ model.ValueType) { p.errorf("binary expression does not support operator %q", n.Op) } if (lt != model.ValScalar && lt != model.ValVector) || (rt != model.ValScalar && rt != model.ValVector) { - p.errorf("binary expression must contain only scalar and vector types") + p.errorf("binary expression must contain only scalar and instant vector types") } if (lt != model.ValVector || rt != model.ValVector) && n.VectorMatching != nil { if len(n.VectorMatching.MatchingLabels) > 0 { - p.errorf("vector matching only allowed between vectors") + p.errorf("vector matching only allowed between instant vectors") } n.VectorMatching = nil } else { @@ -1104,7 +1104,7 @@ func (p *parser) checkType(node Node) (typ model.ValueType) { p.errorf("only + and - operators allowed for unary expressions") } if t := p.checkType(n.Expr); t != model.ValScalar && t != model.ValVector { - p.errorf("unary expression only allowed on expressions of type scalar or vector, got %q", t) + p.errorf("unary expression only allowed on expressions of type scalar or instant vector, got %q", documentedType(t)) } case *NumberLiteral, *MatrixSelector, *StringLiteral, *VectorSelector: diff --git a/promql/parse_test.go b/promql/parse_test.go index 5dd97fc23..38f4c1f19 100644 --- a/promql/parse_test.go +++ b/promql/parse_test.go @@ -237,11 +237,11 @@ var testExpr = []struct { }, { input: `-"string"`, fail: true, - errMsg: `unary expression only allowed on expressions of type scalar or vector, got "string"`, + errMsg: `unary expression only allowed on expressions of type scalar or instant vector, got "string"`, }, { input: `-test[5m]`, fail: true, - errMsg: `unary expression only allowed on expressions of type scalar or vector, got "matrix"`, + errMsg: `unary expression only allowed on expressions of type scalar or instant vector, got "range vector"`, }, { input: `*test`, fail: true, @@ -772,11 +772,11 @@ var testExpr = []struct { }, { input: "1 or on(bar) foo", fail: true, - errMsg: "vector matching only allowed between vectors", + errMsg: "vector matching only allowed between instant vectors", }, { input: "foo == on(bar) 10", fail: true, - errMsg: "vector matching only allowed between vectors", + errMsg: "vector matching only allowed between instant vectors", }, { input: "foo and on(bar) group_left(baz) bar", fail: true, @@ -1286,7 +1286,7 @@ var testExpr = []struct { }, { input: `topk(some_metric, other_metric)`, fail: true, - errMsg: "parse error at char 32: expected type scalar in aggregation parameter, got vector", + errMsg: "parse error at char 32: expected type scalar in aggregation parameter, got instant vector", }, { input: `count_values(5, other_metric)`, fail: true, @@ -1364,7 +1364,7 @@ var testExpr = []struct { }, { input: "floor(1)", fail: true, - errMsg: "expected type vector in call to function \"floor\", got scalar", + errMsg: "expected type instant vector in call to function \"floor\", got scalar", }, { input: "non_existent_function_far_bar()", fail: true, @@ -1372,7 +1372,7 @@ var testExpr = []struct { }, { input: "rate(some_metric)", fail: true, - errMsg: "expected type matrix in call to function \"rate\", got vector", + errMsg: "expected type range vector in call to function \"rate\", got instant vector", }, // Fuzzing regression tests. {