Implement new alerting rule syntax
This commit is contained in:
parent
a8c0307db4
commit
af3a6661ed
|
@ -59,9 +59,7 @@ type AlertStmt struct {
|
|||
Expr Expr
|
||||
Duration time.Duration
|
||||
Labels model.LabelSet
|
||||
Summary string
|
||||
Description string
|
||||
Runbook string
|
||||
Annotations model.LabelSet
|
||||
}
|
||||
|
||||
// EvalStmt holds an expression and information on the range it should
|
||||
|
|
|
@ -154,9 +154,7 @@ const (
|
|||
itemIf
|
||||
itemFor
|
||||
itemWith
|
||||
itemSummary
|
||||
itemRunbook
|
||||
itemDescription
|
||||
itemAnnotations
|
||||
itemKeepCommon
|
||||
itemOffset
|
||||
itemBy
|
||||
|
@ -186,9 +184,7 @@ var key = map[string]itemType{
|
|||
"if": itemIf,
|
||||
"for": itemFor,
|
||||
"with": itemWith,
|
||||
"summary": itemSummary,
|
||||
"runbook": itemRunbook,
|
||||
"description": itemDescription,
|
||||
"annotations": itemAnnotations,
|
||||
"offset": itemOffset,
|
||||
"by": itemBy,
|
||||
"keeping_extra": itemKeepCommon,
|
||||
|
|
|
@ -241,14 +241,8 @@ var tests = []struct {
|
|||
input: "with",
|
||||
expected: []item{{itemWith, 0, "with"}},
|
||||
}, {
|
||||
input: "description",
|
||||
expected: []item{{itemDescription, 0, "description"}},
|
||||
}, {
|
||||
input: "summary",
|
||||
expected: []item{{itemSummary, 0, "summary"}},
|
||||
}, {
|
||||
input: "runbook",
|
||||
expected: []item{{itemRunbook, 0, "runbook"}},
|
||||
input: "annotations",
|
||||
expected: []item{{itemAnnotations, 0, "annotations"}},
|
||||
}, {
|
||||
input: "offset",
|
||||
expected: []item{{itemOffset, 0, "offset"}},
|
||||
|
|
|
@ -357,9 +357,9 @@ func (p *parser) stmt() Statement {
|
|||
|
||||
// alertStmt parses an alert rule.
|
||||
//
|
||||
// ALERT name IF expr [FOR duration] [WITH label_set]
|
||||
// SUMMARY "summary"
|
||||
// DESCRIPTION "description"
|
||||
// ALERT name IF expr [FOR duration]
|
||||
// [WITH label_set]
|
||||
// [ANNOTATIONS label_set]
|
||||
//
|
||||
func (p *parser) alertStmt() *AlertStmt {
|
||||
const ctx = "alert statement"
|
||||
|
@ -389,44 +389,10 @@ func (p *parser) alertStmt() *AlertStmt {
|
|||
lset = p.labelSet()
|
||||
}
|
||||
|
||||
var (
|
||||
hasSum, hasDesc, hasRunbook bool
|
||||
sum, desc, runbook string
|
||||
)
|
||||
Loop:
|
||||
for {
|
||||
switch p.next().typ {
|
||||
case itemSummary:
|
||||
if hasSum {
|
||||
p.errorf("summary must not be defined twice")
|
||||
}
|
||||
hasSum = true
|
||||
sum = p.unquoteString(p.expect(itemString, ctx).val)
|
||||
|
||||
case itemDescription:
|
||||
if hasDesc {
|
||||
p.errorf("description must not be defined twice")
|
||||
}
|
||||
hasDesc = true
|
||||
desc = p.unquoteString(p.expect(itemString, ctx).val)
|
||||
|
||||
case itemRunbook:
|
||||
if hasRunbook {
|
||||
p.errorf("runbook must not be defined twice")
|
||||
}
|
||||
hasRunbook = true
|
||||
runbook = p.unquoteString(p.expect(itemString, ctx).val)
|
||||
|
||||
default:
|
||||
p.backup()
|
||||
break Loop
|
||||
}
|
||||
}
|
||||
if sum == "" {
|
||||
p.errorf("alert summary missing")
|
||||
}
|
||||
if desc == "" {
|
||||
p.errorf("alert description missing")
|
||||
annotations := model.LabelSet{}
|
||||
if p.peek().typ == itemAnnotations {
|
||||
p.expect(itemAnnotations, ctx)
|
||||
annotations = p.labelSet()
|
||||
}
|
||||
|
||||
return &AlertStmt{
|
||||
|
@ -434,9 +400,7 @@ Loop:
|
|||
Expr: expr,
|
||||
Duration: duration,
|
||||
Labels: lset,
|
||||
Summary: sum,
|
||||
Description: desc,
|
||||
Runbook: runbook,
|
||||
Annotations: annotations,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -874,11 +838,20 @@ func (p *parser) labelMatchers(operators ...itemType) metric.LabelMatchers {
|
|||
|
||||
matchers = append(matchers, m)
|
||||
|
||||
if p.peek().typ == itemIdentifier {
|
||||
p.errorf("missing comma before next identifier %q", p.peek().val)
|
||||
}
|
||||
|
||||
// Terminate list if last matcher.
|
||||
if p.peek().typ != itemComma {
|
||||
break
|
||||
}
|
||||
p.next()
|
||||
|
||||
// Allow comma after each item in a multi-line listing.
|
||||
if p.peek().typ == itemRightBrace {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
p.expect(itemRightBrace, ctx)
|
||||
|
|
|
@ -1153,15 +1153,19 @@ var testStatement = []struct {
|
|||
service = "testservice"
|
||||
# ... more fields here ...
|
||||
}
|
||||
SUMMARY "Global request rate low"
|
||||
DESCRIPTION "The global request rate is low"
|
||||
ANNOTATIONS {
|
||||
summary = "Global request rate low",
|
||||
description = "The global request rate is low"
|
||||
}
|
||||
|
||||
foo = bar{label1="value1"}
|
||||
|
||||
ALERT BazAlert IF foo > 10
|
||||
DESCRIPTION "BazAlert"
|
||||
RUNBOOK "http://my.url"
|
||||
SUMMARY "Baz"
|
||||
ANNOTATIONS {
|
||||
description = "BazAlert",
|
||||
runbook = "http://my.url",
|
||||
summary = "Baz",
|
||||
}
|
||||
`,
|
||||
expected: Statements{
|
||||
&RecordStmt{
|
||||
|
@ -1198,8 +1202,10 @@ var testStatement = []struct {
|
|||
}},
|
||||
Labels: model.LabelSet{"service": "testservice"},
|
||||
Duration: 5 * time.Minute,
|
||||
Summary: "Global request rate low",
|
||||
Description: "The global request rate is low",
|
||||
Annotations: model.LabelSet{
|
||||
"summary": "Global request rate low",
|
||||
"description": "The global request rate is low",
|
||||
},
|
||||
},
|
||||
&RecordStmt{
|
||||
Name: "foo",
|
||||
|
@ -1225,9 +1231,11 @@ var testStatement = []struct {
|
|||
RHS: &NumberLiteral{10},
|
||||
},
|
||||
Labels: model.LabelSet{},
|
||||
Summary: "Baz",
|
||||
Description: "BazAlert",
|
||||
Runbook: "http://my.url",
|
||||
Annotations: model.LabelSet{
|
||||
"summary": "Baz",
|
||||
"description": "BazAlert",
|
||||
"runbook": "http://my.url",
|
||||
},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
|
@ -1248,8 +1256,10 @@ var testStatement = []struct {
|
|||
},
|
||||
}, {
|
||||
input: `ALERT SomeName IF some_metric > 1
|
||||
SUMMARY "Global request rate low"
|
||||
DESCRIPTION "The global request rate is low"
|
||||
ANNOTATIONS {
|
||||
summary = "Global request rate low",
|
||||
description = "The global request rate is low"
|
||||
}
|
||||
`,
|
||||
expected: Statements{
|
||||
&AlertStmt{
|
||||
|
@ -1265,8 +1275,10 @@ var testStatement = []struct {
|
|||
RHS: &NumberLiteral{1},
|
||||
},
|
||||
Labels: model.LabelSet{},
|
||||
Summary: "Global request rate low",
|
||||
Description: "The global request rate is low",
|
||||
Annotations: model.LabelSet{
|
||||
"summary": "Global request rate low",
|
||||
"description": "The global request rate is low",
|
||||
},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
|
@ -1276,8 +1288,10 @@ var testStatement = []struct {
|
|||
service = "testservice"
|
||||
# ... more fields here ...
|
||||
}
|
||||
SUMMARY "Global request rate low"
|
||||
DESCRIPTION "The global request rate is low"
|
||||
ANNOTATIONS {
|
||||
summary = "Global request rate low"
|
||||
description = "The global request rate is low"
|
||||
}
|
||||
`,
|
||||
fail: true,
|
||||
}, {
|
||||
|
@ -1323,16 +1337,6 @@ var testStatement = []struct {
|
|||
DESCRIPTION "The global request rate is low"
|
||||
`,
|
||||
fail: true,
|
||||
}, {
|
||||
input: `ALERT SomeName IF some_metric > 1 WITH {}
|
||||
SUMMARY "Global request rate low"
|
||||
`,
|
||||
fail: true,
|
||||
}, {
|
||||
input: `ALERT SomeName IF some_metric > 1
|
||||
DESCRIPTION "The global request rate is low"
|
||||
`,
|
||||
fail: true,
|
||||
},
|
||||
// Fuzzing regression tests.
|
||||
{
|
||||
|
|
|
@ -109,8 +109,9 @@ func (node *AlertStmt) String() string {
|
|||
if len(node.Labels) > 0 {
|
||||
s += fmt.Sprintf("\n\tWITH %s", node.Labels)
|
||||
}
|
||||
s += fmt.Sprintf("\n\tSUMMARY %q", node.Summary)
|
||||
s += fmt.Sprintf("\n\tDESCRIPTION %q", node.Description)
|
||||
if len(node.Annotations) > 0 {
|
||||
s += fmt.Sprintf("\n\tANNOTATIONS %s", node.Labels)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue