mirror of
https://github.com/prometheus/prometheus.git
synced 2024-11-10 07:34:04 -08:00
Merge "Allow reversing vector and scalar arguments in binops."
This commit is contained in:
commit
95bc920f5f
|
@ -195,11 +195,12 @@ type (
|
|||
vector VectorNode
|
||||
}
|
||||
|
||||
// VectorArithExpr represents an arithmetic expression of
|
||||
// vector type.
|
||||
// VectorArithExpr represents an arithmetic expression of vector type. At
|
||||
// least one of the two operand Nodes must be a VectorNode. The other may be
|
||||
// a VectorNode or ScalarNode. Both criteria are checked at runtime.
|
||||
VectorArithExpr struct {
|
||||
opType BinOpType
|
||||
lhs VectorNode
|
||||
lhs Node
|
||||
rhs Node
|
||||
}
|
||||
)
|
||||
|
@ -639,9 +640,20 @@ func labelsEqual(labels1, labels2 clientmodel.Metric) bool {
|
|||
// Eval implements the VectorNode interface and returns the result of
|
||||
// the expression.
|
||||
func (node *VectorArithExpr) Eval(timestamp clientmodel.Timestamp, view *viewAdapter) Vector {
|
||||
lhs := node.lhs.Eval(timestamp, view)
|
||||
result := Vector{}
|
||||
if node.rhs.Type() == SCALAR {
|
||||
if node.lhs.Type() == SCALAR && node.rhs.Type() == VECTOR {
|
||||
lhs := node.lhs.(ScalarNode).Eval(timestamp, view)
|
||||
rhs := node.rhs.(VectorNode).Eval(timestamp, view)
|
||||
for _, rhsSample := range rhs {
|
||||
value, keep := evalVectorBinop(node.opType, lhs, rhsSample.Value)
|
||||
if keep {
|
||||
rhsSample.Value = value
|
||||
result = append(result, rhsSample)
|
||||
}
|
||||
}
|
||||
return result
|
||||
} else if node.lhs.Type() == VECTOR && node.rhs.Type() == SCALAR {
|
||||
lhs := node.lhs.(VectorNode).Eval(timestamp, view)
|
||||
rhs := node.rhs.(ScalarNode).Eval(timestamp, view)
|
||||
for _, lhsSample := range lhs {
|
||||
value, keep := evalVectorBinop(node.opType, lhsSample.Value, rhs)
|
||||
|
@ -651,7 +663,8 @@ func (node *VectorArithExpr) Eval(timestamp clientmodel.Timestamp, view *viewAda
|
|||
}
|
||||
}
|
||||
return result
|
||||
} else if node.rhs.Type() == VECTOR {
|
||||
} else if node.lhs.Type() == VECTOR && node.rhs.Type() == VECTOR {
|
||||
lhs := node.lhs.(VectorNode).Eval(timestamp, view)
|
||||
rhs := node.rhs.(VectorNode).Eval(timestamp, view)
|
||||
for _, lhsSample := range lhs {
|
||||
for _, rhsSample := range rhs {
|
||||
|
@ -804,9 +817,6 @@ func NewArithExpr(opType BinOpType, lhs Node, rhs Node) (Node, error) {
|
|||
if !nodesHaveTypes(Nodes{lhs, rhs}, []ExprType{SCALAR, VECTOR}) {
|
||||
return nil, errors.New("binary operands must be of vector or scalar type")
|
||||
}
|
||||
if lhs.Type() == SCALAR && rhs.Type() == VECTOR {
|
||||
return nil, errors.New("left side of vector binary operation must be of vector type")
|
||||
}
|
||||
|
||||
if opType == AND || opType == OR {
|
||||
if lhs.Type() == SCALAR || rhs.Type() == SCALAR {
|
||||
|
@ -817,7 +827,7 @@ func NewArithExpr(opType BinOpType, lhs Node, rhs Node) (Node, error) {
|
|||
if lhs.Type() == VECTOR || rhs.Type() == VECTOR {
|
||||
return &VectorArithExpr{
|
||||
opType: opType,
|
||||
lhs: lhs.(VectorNode),
|
||||
lhs: lhs,
|
||||
rhs: rhs,
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -209,6 +209,22 @@ func TestExpressions(t *testing.T) {
|
|||
},
|
||||
fullRanges: 0,
|
||||
intervalRanges: 8,
|
||||
}, {
|
||||
expr: `2 - SUM(http_requests) BY (job)`,
|
||||
output: []string{
|
||||
`http_requests{job="api-server"} => -998 @[%v]`,
|
||||
`http_requests{job="app-server"} => -2598 @[%v]`,
|
||||
},
|
||||
fullRanges: 0,
|
||||
intervalRanges: 8,
|
||||
}, {
|
||||
expr: `1000 / SUM(http_requests) BY (job)`,
|
||||
output: []string{
|
||||
`http_requests{job="api-server"} => 1 @[%v]`,
|
||||
`http_requests{job="app-server"} => 0.38461538461538464 @[%v]`,
|
||||
},
|
||||
fullRanges: 0,
|
||||
intervalRanges: 8,
|
||||
}, {
|
||||
expr: `SUM(http_requests) BY (job) - 2`,
|
||||
output: []string{
|
||||
|
@ -240,6 +256,13 @@ func TestExpressions(t *testing.T) {
|
|||
},
|
||||
fullRanges: 0,
|
||||
intervalRanges: 8,
|
||||
}, {
|
||||
expr: `1000 < SUM(http_requests) BY (job)`,
|
||||
output: []string{
|
||||
`http_requests{job="app-server"} => 1000 @[%v]`,
|
||||
},
|
||||
fullRanges: 0,
|
||||
intervalRanges: 8,
|
||||
}, {
|
||||
expr: `SUM(http_requests) BY (job) <= 1000`,
|
||||
output: []string{
|
||||
|
@ -398,14 +421,14 @@ func TestExpressions(t *testing.T) {
|
|||
// Empty expressions shouldn"t parse.
|
||||
expr: ``,
|
||||
shouldFail: true,
|
||||
}, {
|
||||
// Subtracting a vector from a scalar is not supported.
|
||||
expr: `1 - http_requests`,
|
||||
shouldFail: true,
|
||||
}, {
|
||||
// Interval durations can"t be in quotes.
|
||||
expr: `http_requests["1m"]`,
|
||||
shouldFail: true,
|
||||
}, {
|
||||
// Binop arguments need to be scalar or vector.
|
||||
expr: `http_requests - http_requests[1m]`,
|
||||
shouldFail: true,
|
||||
}, {
|
||||
expr: `http_requests{group!="canary"}`,
|
||||
output: []string{
|
||||
|
|
Loading…
Reference in a new issue