Merge pull request #1300 from prometheus/oldalerts

Support old alerting rule syntax
This commit is contained in:
Fabian Reinartz 2016-01-11 12:14:47 +01:00
commit 37d28bf91a
4 changed files with 106 additions and 20 deletions

View File

@ -162,6 +162,11 @@ const (
itemGroupLeft itemGroupLeft
itemGroupRight itemGroupRight
itemBool itemBool
// Old alerting syntax
itemWith
itemSummary
itemRunbook
itemDescription
keywordsEnd keywordsEnd
) )
@ -193,6 +198,12 @@ var key = map[string]itemType{
"group_left": itemGroupLeft, "group_left": itemGroupLeft,
"group_right": itemGroupRight, "group_right": itemGroupRight,
"bool": itemBool, "bool": itemBool,
// Old alerting syntax.
"with": itemWith,
"summary": itemSummary,
"runbook": itemRunbook,
"description": itemDescription,
} }
// These are the default string representations for common items. It does not // These are the default string representations for common items. It does not

View File

@ -243,6 +243,18 @@ var tests = []struct {
}, { }, {
input: "annotations", input: "annotations",
expected: []item{{itemAnnotations, 0, "annotations"}}, expected: []item{{itemAnnotations, 0, "annotations"}},
}, {
input: "description",
expected: []item{{itemDescription, 0, "description"}},
}, {
input: "summary",
expected: []item{{itemSummary, 0, "summary"}},
}, {
input: "runbook",
expected: []item{{itemRunbook, 0, "runbook"}},
}, {
input: "with",
expected: []item{{itemWith, 0, "with"}},
}, { }, {
input: "offset", input: "offset",
expected: []item{{itemOffset, 0, "offset"}}, expected: []item{{itemOffset, 0, "offset"}},

View File

@ -371,9 +371,10 @@ func (p *parser) alertStmt() *AlertStmt {
expr := p.expr() expr := p.expr()
// Optional for clause. // Optional for clause.
var duration time.Duration var (
var err error duration time.Duration
err error
)
if p.peek().typ == itemFor { if p.peek().typ == itemFor {
p.next() p.next()
dur := p.expect(itemDuration, ctx) dur := p.expect(itemDuration, ctx)
@ -383,23 +384,64 @@ func (p *parser) alertStmt() *AlertStmt {
} }
} }
lset := model.LabelSet{} // Accepting WITH instead of LABELS is temporary compatibility
if p.peek().typ == itemLabels { // with the old alerting syntax.
var (
hasLabels bool
oldSyntax bool
labels = model.LabelSet{}
annotations = model.LabelSet{}
)
if t := p.peek().typ; t == itemLabels {
p.expect(itemLabels, ctx) p.expect(itemLabels, ctx)
lset = p.labelSet() labels = p.labelSet()
hasLabels = true
} else if t == itemWith {
p.expect(itemWith, ctx)
labels = p.labelSet()
oldSyntax = true
} }
annotations := model.LabelSet{} // Only allow old annotation syntax if new label syntax isn't used.
if p.peek().typ == itemAnnotations { if !hasLabels {
p.expect(itemAnnotations, ctx) Loop:
annotations = p.labelSet() for {
switch p.next().typ {
case itemSummary:
annotations["summary"] = model.LabelValue(p.unquoteString(p.expect(itemString, ctx).val))
case itemDescription:
annotations["description"] = model.LabelValue(p.unquoteString(p.expect(itemString, ctx).val))
case itemRunbook:
annotations["runbook"] = model.LabelValue(p.unquoteString(p.expect(itemString, ctx).val))
default:
p.backup()
break Loop
}
}
if len(annotations) > 0 {
oldSyntax = true
}
}
// Only allow new annotation syntax if WITH or old annotation
// syntax weren't used.
if !oldSyntax {
if p.peek().typ == itemAnnotations {
p.expect(itemAnnotations, ctx)
annotations = p.labelSet()
}
} else {
log.Warnf("Alerting rule with old syntax found. Support for this syntax will be removed with 0.18. Please update to the new syntax.")
} }
return &AlertStmt{ return &AlertStmt{
Name: name.val, Name: name.val,
Expr: expr, Expr: expr,
Duration: duration, Duration: duration,
Labels: lset, Labels: labels,
Annotations: annotations, Annotations: annotations,
} }
} }

View File

@ -1256,10 +1256,37 @@ var testStatement = []struct {
}, },
}, },
}, { }, {
input: `ALERT SomeName IF some_metric > 1 input: `ALERT SomeName IF some_metric > 1
WITH {}
SUMMARY "Global request rate low"
DESCRIPTION "The global request rate is low"
`,
expected: Statements{
&AlertStmt{
Name: "SomeName",
Expr: &BinaryExpr{
Op: itemGTR,
LHS: &VectorSelector{
Name: "some_metric",
LabelMatchers: metric.LabelMatchers{
{Type: metric.Equal, Name: model.MetricNameLabel, Value: "some_metric"},
},
},
RHS: &NumberLiteral{1},
},
Labels: model.LabelSet{},
Annotations: model.LabelSet{
"summary": "Global request rate low",
"description": "The global request rate is low",
},
},
},
}, {
input: `ALERT SomeName IF some_metric > 1
LABELS {}
ANNOTATIONS { ANNOTATIONS {
summary = "Global request rate low", summary = "Global request rate low",
description = "The global request rate is low" description = "The global request rate is low",
} }
`, `,
expected: Statements{ expected: Statements{
@ -1333,12 +1360,6 @@ var testStatement = []struct {
}, { }, {
input: `foo{a!~"b"} = bar`, input: `foo{a!~"b"} = bar`,
fail: true, fail: true,
}, {
input: `ALERT SomeName IF time() LABELS {}
SUMMARY "Global request rate low"
DESCRIPTION "The global request rate is low"
`,
fail: true,
}, },
// Fuzzing regression tests. // Fuzzing regression tests.
{ {