rules: Allow recorded rules expressions to be scalars.

This is useful if you want to build up a constant metric,
such as a set of alert thresholds that vary by label value.
This commit is contained in:
Brian Brazil 2015-08-19 21:09:00 +01:00
parent 2b0c153288
commit e6a67476c2
3 changed files with 33 additions and 6 deletions

View file

@ -1009,7 +1009,10 @@ func (p *parser) checkType(node Node) (typ ExprType) {
}
case *RecordStmt:
p.expectType(n.Expr, ExprVector, "record statement")
ty := p.checkType(n.Expr)
if ty != ExprVector && ty != ExprScalar {
p.errorf("record statement must have a valid expression of type vector or scalar but got %s", ty)
}
case Expressions:
for _, e := range n {

View file

@ -1207,10 +1207,20 @@ var testStatement = []struct {
expected: Statements{},
}, {
input: "foo = time()",
fail: true,
expected: Statements{
&RecordStmt{
Name: "foo",
Expr: &Call{Func: mustGetFunction("time")},
Labels: nil,
}},
}, {
input: "foo = 1",
fail: true,
expected: Statements{
&RecordStmt{
Name: "foo",
Expr: &NumberLiteral{1},
Labels: nil,
}},
}, {
input: "foo = bar[5m]",
fail: true,

View file

@ -48,9 +48,23 @@ func (rule RecordingRule) eval(timestamp clientmodel.Timestamp, engine *promql.E
if err != nil {
return nil, err
}
vector, err := query.Exec().Vector()
if err != nil {
return nil, err
result := query.Exec()
var vector promql.Vector
switch result.Value.(type) {
case promql.Vector:
vector, err = result.Vector()
if err != nil {
return nil, err
}
case *promql.Scalar:
scalar, err := result.Scalar()
if err != nil {
return nil, err
}
vector = promql.Vector{&promql.Sample{Value: scalar.Value, Timestamp: scalar.Timestamp}}
default:
return nil, fmt.Errorf("rule result is not a vector or scalar")
}
// Override the metric name and labels.