promql: make scalar public
This commit is contained in:
parent
b3f71df350
commit
09666e2e2a
|
@ -156,7 +156,7 @@ type StringLiteral struct {
|
|||
}
|
||||
|
||||
// UnaryExpr represents a unary operation on another expression.
|
||||
// Currently unary operations are only supported for scalars.
|
||||
// Currently unary operations are only supported for Scalars.
|
||||
type UnaryExpr struct {
|
||||
Op itemType
|
||||
Expr Expr
|
||||
|
|
|
@ -52,7 +52,7 @@ type Value interface {
|
|||
|
||||
func (Matrix) Type() ValueType { return ValueTypeMatrix }
|
||||
func (Vector) Type() ValueType { return ValueTypeVector }
|
||||
func (scalar) Type() ValueType { return ValueTypeScalar }
|
||||
func (Scalar) Type() ValueType { return ValueTypeScalar }
|
||||
func (stringVal) Type() ValueType { return ValueTypeString }
|
||||
|
||||
// ValueType describes a type of a value.
|
||||
|
@ -62,7 +62,7 @@ type ValueType string
|
|||
const (
|
||||
ValueTypeNone = "none"
|
||||
ValueTypeVector = "Vector"
|
||||
ValueTypeScalar = "scalar"
|
||||
ValueTypeScalar = "Scalar"
|
||||
ValueTypeMatrix = "Matrix"
|
||||
ValueTypeString = "string"
|
||||
)
|
||||
|
@ -76,12 +76,12 @@ func (s stringVal) String() string {
|
|||
return s.s
|
||||
}
|
||||
|
||||
type scalar struct {
|
||||
type Scalar struct {
|
||||
t int64
|
||||
v float64
|
||||
}
|
||||
|
||||
func (s scalar) String() string {
|
||||
func (s Scalar) String() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
|
@ -175,15 +175,15 @@ func (r *Result) Matrix() (Matrix, error) {
|
|||
return v, nil
|
||||
}
|
||||
|
||||
// Scalar returns a scalar value. An error is returned if
|
||||
// the result was an error or the result value is not a scalar.
|
||||
func (r *Result) Scalar() (scalar, error) {
|
||||
// Scalar returns a Scalar value. An error is returned if
|
||||
// the result was an error or the result value is not a Scalar.
|
||||
func (r *Result) Scalar() (Scalar, error) {
|
||||
if r.Err != nil {
|
||||
return scalar{}, r.Err
|
||||
return Scalar{}, r.Err
|
||||
}
|
||||
v, ok := r.Value.(scalar)
|
||||
v, ok := r.Value.(Scalar)
|
||||
if !ok {
|
||||
return scalar{}, fmt.Errorf("query result is not a scalar")
|
||||
return Scalar{}, fmt.Errorf("query result is not a Scalar")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
@ -336,7 +336,7 @@ func (ng *Engine) NewRangeQuery(qs string, start, end time.Time, interval time.D
|
|||
return nil, err
|
||||
}
|
||||
if expr.Type() != ValueTypeVector && expr.Type() != ValueTypeScalar {
|
||||
return nil, fmt.Errorf("invalid expression type %q for range query, must be scalar or instant Vector", documentedType(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
|
||||
|
@ -470,9 +470,9 @@ func (ng *Engine) execEvalStmt(ctx context.Context, query *query, s *EvalStmt) (
|
|||
}
|
||||
|
||||
switch v := val.(type) {
|
||||
case scalar:
|
||||
case Scalar:
|
||||
// As the expression type does not change we can safely default to 0
|
||||
// as the fingerprint for scalar expressions.
|
||||
// as the fingerprint for Scalar expressions.
|
||||
ss, ok := sampleStreams[0]
|
||||
if !ok {
|
||||
ss = sampleStream{Values: make([]samplePair, 0, numSteps)}
|
||||
|
@ -633,12 +633,12 @@ func (ev *evaluator) recover(errp *error) {
|
|||
}
|
||||
}
|
||||
|
||||
// evalScalar attempts to evaluate e to a scalar value and errors otherwise.
|
||||
func (ev *evaluator) evalScalar(e Expr) scalar {
|
||||
// evalScalar attempts to evaluate e to a Scalar value and errors otherwise.
|
||||
func (ev *evaluator) evalScalar(e Expr) Scalar {
|
||||
val := ev.eval(e)
|
||||
sv, ok := val.(scalar)
|
||||
sv, ok := val.(Scalar)
|
||||
if !ok {
|
||||
ev.errorf("expected scalar but got %s", documentedType(val.Type()))
|
||||
ev.errorf("expected Scalar but got %s", documentedType(val.Type()))
|
||||
}
|
||||
return sv
|
||||
}
|
||||
|
@ -657,7 +657,7 @@ func (ev *evaluator) evalVector(e Expr) Vector {
|
|||
func (ev *evaluator) evalInt(e Expr) int64 {
|
||||
sc := ev.evalScalar(e)
|
||||
if !convertibleToInt64(sc.v) {
|
||||
ev.errorf("scalar value %v overflows int64", sc.v)
|
||||
ev.errorf("Scalar value %v overflows int64", sc.v)
|
||||
}
|
||||
return int64(sc.v)
|
||||
}
|
||||
|
@ -723,8 +723,8 @@ func (ev *evaluator) eval(expr Expr) Value {
|
|||
|
||||
switch lt, rt := lhs.Type(), rhs.Type(); {
|
||||
case lt == ValueTypeScalar && rt == ValueTypeScalar:
|
||||
return scalar{
|
||||
v: scalarBinop(e.Op, lhs.(scalar).v, rhs.(scalar).v),
|
||||
return Scalar{
|
||||
v: ScalarBinop(e.Op, lhs.(Scalar).v, rhs.(Scalar).v),
|
||||
t: ev.Timestamp,
|
||||
}
|
||||
|
||||
|
@ -740,10 +740,10 @@ func (ev *evaluator) eval(expr Expr) Value {
|
|||
return ev.VectorBinop(e.Op, lhs.(Vector), rhs.(Vector), e.VectorMatching, e.ReturnBool)
|
||||
}
|
||||
case lt == ValueTypeVector && rt == ValueTypeScalar:
|
||||
return ev.VectorScalarBinop(e.Op, lhs.(Vector), rhs.(scalar), false, e.ReturnBool)
|
||||
return ev.VectorScalarBinop(e.Op, lhs.(Vector), rhs.(Scalar), false, e.ReturnBool)
|
||||
|
||||
case lt == ValueTypeScalar && rt == ValueTypeVector:
|
||||
return ev.VectorScalarBinop(e.Op, rhs.(Vector), lhs.(scalar), true, e.ReturnBool)
|
||||
return ev.VectorScalarBinop(e.Op, rhs.(Vector), lhs.(Scalar), true, e.ReturnBool)
|
||||
}
|
||||
|
||||
case *Call:
|
||||
|
@ -753,7 +753,7 @@ func (ev *evaluator) eval(expr Expr) Value {
|
|||
return ev.MatrixSelector(e)
|
||||
|
||||
case *NumberLiteral:
|
||||
return scalar{v: e.Val, t: ev.Timestamp}
|
||||
return Scalar{v: e.Val, t: ev.Timestamp}
|
||||
|
||||
case *ParenExpr:
|
||||
return ev.eval(e.Expr)
|
||||
|
@ -766,7 +766,7 @@ func (ev *evaluator) eval(expr Expr) Value {
|
|||
// Only + and - are possible operators.
|
||||
if e.Op == itemSUB {
|
||||
switch v := se.(type) {
|
||||
case scalar:
|
||||
case Scalar:
|
||||
v.v = -v.v
|
||||
case Vector:
|
||||
for i, sv := range v {
|
||||
|
@ -1116,8 +1116,8 @@ Outer:
|
|||
return res
|
||||
}
|
||||
|
||||
// VectorScalarBinop evaluates a binary operation between a Vector and a scalar.
|
||||
func (ev *evaluator) VectorScalarBinop(op itemType, lhs Vector, rhs scalar, swap, returnBool bool) Vector {
|
||||
// VectorScalarBinop evaluates a binary operation between a Vector and a Scalar.
|
||||
func (ev *evaluator) VectorScalarBinop(op itemType, lhs Vector, rhs Scalar, swap, returnBool bool) Vector {
|
||||
vec := make(Vector, 0, len(lhs))
|
||||
|
||||
for _, lhsSample := range lhs {
|
||||
|
@ -1161,8 +1161,8 @@ func copyLabels(metric labels.Labels, withName bool) labels.Labels {
|
|||
return cm
|
||||
}
|
||||
|
||||
// scalarBinop evaluates a binary operation between two scalars.
|
||||
func scalarBinop(op itemType, lhs, rhs float64) float64 {
|
||||
// ScalarBinop evaluates a binary operation between two Scalars.
|
||||
func ScalarBinop(op itemType, lhs, rhs float64) float64 {
|
||||
switch op {
|
||||
case itemADD:
|
||||
return lhs + rhs
|
||||
|
@ -1189,7 +1189,7 @@ func scalarBinop(op itemType, lhs, rhs float64) float64 {
|
|||
case itemLTE:
|
||||
return btos(lhs <= rhs)
|
||||
}
|
||||
panic(fmt.Errorf("operator %q not allowed for scalar operations", op))
|
||||
panic(fmt.Errorf("operator %q not allowed for Scalar operations", op))
|
||||
}
|
||||
|
||||
// VectorElemBinop evaluates a binary operation between two Vector elements.
|
||||
|
|
|
@ -36,7 +36,7 @@ type Function struct {
|
|||
|
||||
// === time() float64 ===
|
||||
func funcTime(ev *evaluator, args Expressions) Value {
|
||||
return scalar{
|
||||
return Scalar{
|
||||
v: float64(ev.Timestamp / 1000),
|
||||
t: ev.Timestamp,
|
||||
}
|
||||
|
@ -384,24 +384,24 @@ func funcRound(ev *evaluator, args Expressions) Value {
|
|||
return vec
|
||||
}
|
||||
|
||||
// === scalar(node ValueTypeVector) Scalar ===
|
||||
// === Scalar(node ValueTypeVector) Scalar ===
|
||||
func funcScalar(ev *evaluator, args Expressions) Value {
|
||||
v := ev.evalVector(args[0])
|
||||
if len(v) != 1 {
|
||||
return scalar{
|
||||
return Scalar{
|
||||
v: math.NaN(),
|
||||
t: ev.Timestamp,
|
||||
}
|
||||
}
|
||||
return scalar{
|
||||
return Scalar{
|
||||
v: v[0].Value,
|
||||
t: ev.Timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
// === count_scalar(Vector ValueTypeVector) float64 ===
|
||||
// === count_Scalar(Vector ValueTypeVector) float64 ===
|
||||
func funcCountScalar(ev *evaluator, args Expressions) Value {
|
||||
return scalar{
|
||||
return Scalar{
|
||||
v: float64(len(ev.evalVector(args[0]))),
|
||||
t: ev.Timestamp,
|
||||
}
|
||||
|
@ -840,7 +840,7 @@ func funcLabelReplace(ev *evaluator, args Expressions) Value {
|
|||
return Vector
|
||||
}
|
||||
|
||||
// === Vector(s scalar) Vector ===
|
||||
// === Vector(s Scalar) Vector ===
|
||||
func funcVector(ev *evaluator, args Expressions) Value {
|
||||
return Vector{
|
||||
sample{
|
||||
|
@ -872,49 +872,49 @@ func dateWrapper(ev *evaluator, args Expressions, f func(time.Time) float64) Val
|
|||
return v
|
||||
}
|
||||
|
||||
// === days_in_month(v Vector) scalar ===
|
||||
// === days_in_month(v Vector) Scalar ===
|
||||
func funcDaysInMonth(ev *evaluator, args Expressions) Value {
|
||||
return dateWrapper(ev, args, func(t time.Time) float64 {
|
||||
return float64(32 - time.Date(t.Year(), t.Month(), 32, 0, 0, 0, 0, time.UTC).Day())
|
||||
})
|
||||
}
|
||||
|
||||
// === day_of_month(v Vector) scalar ===
|
||||
// === day_of_month(v Vector) Scalar ===
|
||||
func funcDayOfMonth(ev *evaluator, args Expressions) Value {
|
||||
return dateWrapper(ev, args, func(t time.Time) float64 {
|
||||
return float64(t.Day())
|
||||
})
|
||||
}
|
||||
|
||||
// === day_of_week(v Vector) scalar ===
|
||||
// === day_of_week(v Vector) Scalar ===
|
||||
func funcDayOfWeek(ev *evaluator, args Expressions) Value {
|
||||
return dateWrapper(ev, args, func(t time.Time) float64 {
|
||||
return float64(t.Weekday())
|
||||
})
|
||||
}
|
||||
|
||||
// === hour(v Vector) scalar ===
|
||||
// === hour(v Vector) Scalar ===
|
||||
func funcHour(ev *evaluator, args Expressions) Value {
|
||||
return dateWrapper(ev, args, func(t time.Time) float64 {
|
||||
return float64(t.Hour())
|
||||
})
|
||||
}
|
||||
|
||||
// === minute(v Vector) scalar ===
|
||||
// === minute(v Vector) Scalar ===
|
||||
func funcMinute(ev *evaluator, args Expressions) Value {
|
||||
return dateWrapper(ev, args, func(t time.Time) float64 {
|
||||
return float64(t.Minute())
|
||||
})
|
||||
}
|
||||
|
||||
// === month(v Vector) scalar ===
|
||||
// === month(v Vector) Scalar ===
|
||||
func funcMonth(ev *evaluator, args Expressions) Value {
|
||||
return dateWrapper(ev, args, func(t time.Time) float64 {
|
||||
return float64(t.Month())
|
||||
})
|
||||
}
|
||||
|
||||
// === year(v Vector) scalar ===
|
||||
// === year(v Vector) Scalar ===
|
||||
func funcYear(ev *evaluator, args Expressions) Value {
|
||||
return dateWrapper(ev, args, func(t time.Time) float64 {
|
||||
return float64(t.Year())
|
||||
|
@ -970,8 +970,8 @@ var functions = map[string]*Function{
|
|||
ReturnType: ValueTypeVector,
|
||||
Call: funcCountOverTime,
|
||||
},
|
||||
"count_scalar": {
|
||||
Name: "count_scalar",
|
||||
"count_Scalar": {
|
||||
Name: "count_Scalar",
|
||||
ArgTypes: []ValueType{ValueTypeVector},
|
||||
ReturnType: ValueTypeScalar,
|
||||
Call: funcCountScalar,
|
||||
|
@ -1145,8 +1145,8 @@ var functions = map[string]*Function{
|
|||
ReturnType: ValueTypeVector,
|
||||
Call: funcRound,
|
||||
},
|
||||
"scalar": {
|
||||
Name: "scalar",
|
||||
"Scalar": {
|
||||
Name: "Scalar",
|
||||
ArgTypes: []ValueType{ValueTypeVector},
|
||||
ReturnType: ValueTypeScalar,
|
||||
Call: funcScalar,
|
||||
|
|
|
@ -506,7 +506,7 @@ func (p *parser) balance(lhs Expr, op itemType, rhs Expr, vecMatching *VectorMat
|
|||
if (precd < 0) || (precd == 0 && op.isRightAssociative()) {
|
||||
balanced := p.balance(lhsBE.RHS, op, rhs, vecMatching, returnBool)
|
||||
if lhsBE.Op.isComparisonOperator() && !lhsBE.ReturnBool && balanced.Type() == ValueTypeScalar && lhsBE.LHS.Type() == ValueTypeScalar {
|
||||
p.errorf("comparisons between scalars must use BOOL modifier")
|
||||
p.errorf("comparisons between Scalars must use BOOL modifier")
|
||||
}
|
||||
return &BinaryExpr{
|
||||
Op: lhsBE.Op,
|
||||
|
@ -518,7 +518,7 @@ func (p *parser) balance(lhs Expr, op itemType, rhs Expr, vecMatching *VectorMat
|
|||
}
|
||||
}
|
||||
if op.isComparisonOperator() && !returnBool && rhs.Type() == ValueTypeScalar && lhs.Type() == ValueTypeScalar {
|
||||
p.errorf("comparisons between scalars must use BOOL modifier")
|
||||
p.errorf("comparisons between Scalars must use BOOL modifier")
|
||||
}
|
||||
return &BinaryExpr{
|
||||
Op: op,
|
||||
|
@ -1028,7 +1028,7 @@ func (p *parser) checkType(node Node) (typ ValueType) {
|
|||
case *RecordStmt:
|
||||
ty := p.checkType(n.Expr)
|
||||
if ty != ValueTypeVector && ty != ValueTypeScalar {
|
||||
p.errorf("record statement must have a valid expression of type instant Vector or scalar but got %s", documentedType(ty))
|
||||
p.errorf("record statement must have a valid expression of type instant Vector or Scalar but got %s", documentedType(ty))
|
||||
}
|
||||
|
||||
case Expressions:
|
||||
|
@ -1058,7 +1058,7 @@ func (p *parser) checkType(node Node) (typ ValueType) {
|
|||
p.errorf("binary expression does not support operator %q", n.Op)
|
||||
}
|
||||
if (lt != ValueTypeScalar && lt != ValueTypeVector) || (rt != ValueTypeScalar && rt != ValueTypeVector) {
|
||||
p.errorf("binary expression must contain only scalar and instant Vector types")
|
||||
p.errorf("binary expression must contain only Scalar and instant Vector types")
|
||||
}
|
||||
|
||||
if (lt != ValueTypeVector || rt != ValueTypeVector) && n.VectorMatching != nil {
|
||||
|
@ -1079,7 +1079,7 @@ func (p *parser) checkType(node Node) (typ ValueType) {
|
|||
}
|
||||
|
||||
if (lt == ValueTypeScalar || rt == ValueTypeScalar) && n.Op.isSetOperator() {
|
||||
p.errorf("set operator %q not allowed in binary scalar expression", n.Op)
|
||||
p.errorf("set operator %q not allowed in binary Scalar expression", n.Op)
|
||||
}
|
||||
|
||||
case *Call:
|
||||
|
@ -1102,7 +1102,7 @@ func (p *parser) checkType(node Node) (typ ValueType) {
|
|||
p.errorf("only + and - operators allowed for unary expressions")
|
||||
}
|
||||
if t := p.checkType(n.Expr); t != ValueTypeScalar && t != ValueTypeVector {
|
||||
p.errorf("unary expression only allowed on expressions of type scalar or instant Vector, got %q", documentedType(t))
|
||||
p.errorf("unary expression only allowed on expressions of type Scalar or instant Vector, got %q", documentedType(t))
|
||||
}
|
||||
|
||||
case *NumberLiteral, *MatrixSelector, *StringLiteral, *VectorSelector:
|
||||
|
|
|
@ -404,9 +404,9 @@ func (ev *evalCmd) compareResult(result Value) error {
|
|||
}
|
||||
}
|
||||
|
||||
case scalar:
|
||||
case Scalar:
|
||||
if !almostEqual(ev.expected[0].vals[0].value, val.v) {
|
||||
return fmt.Errorf("expected scalar %v but got %v", val.v, ev.expected[0].vals[0].value)
|
||||
return fmt.Errorf("expected Scalar %v but got %v", val.v, ev.expected[0].vals[0].value)
|
||||
}
|
||||
|
||||
default:
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
html_template "html/template"
|
||||
text_template "text/template"
|
||||
|
@ -56,8 +57,8 @@ func (q queryResultByLabelSorter) Swap(i, j int) {
|
|||
q.results[i], q.results[j] = q.results[j], q.results[i]
|
||||
}
|
||||
|
||||
func query(ctx context.Context, q string, timestamp model.Time, queryEngine *promql.Engine) (queryResult, error) {
|
||||
query, err := queryEngine.NewInstantQuery(q, timestamp)
|
||||
func query(ctx context.Context, q string, ts time.Time, queryEngine *promql.Engine) (queryResult, error) {
|
||||
query, err := queryEngine.NewInstantQuery(q, ts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue