Skip to content

Commit c5ff536

Browse files
authored
Merge pull request #1208 from cloudflare/rule/report
Add rule/report check
2 parents 2a74f5b + bb7f1ad commit c5ff536

File tree

13 files changed

+479
-51
lines changed

13 files changed

+479
-51
lines changed

cmd/pint/tests/0025_config.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ level=INFO msg="Loading configuration file" path=.pint.hcl
3838
"rule/name",
3939
"rule/label",
4040
"rule/link",
41-
"rule/reject"
41+
"rule/reject",
42+
"rule/report"
4243
],
4344
"disabled": [
4445
"promql/fragile"

cmd/pint/tests/0113_config_env_expand.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ level=INFO msg="Loading configuration file" path=.pint.hcl
4343
"rule/name",
4444
"rule/label",
4545
"rule/link",
46-
"rule/reject"
46+
"rule/reject",
47+
"rule/report"
4748
]
4849
},
4950
"owners": {},
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
! exec pint --no-color lint rules
2+
! stdout .
3+
cmp stderr stderr.txt
4+
5+
-- stderr.txt --
6+
level=INFO msg="Loading configuration file" path=.pint.hcl
7+
level=INFO msg="Finding all rules to check" paths=["rules"]
8+
rules/1.yml:3-4 Bug: You cannot add any recording rules to this Prometheus server. (rule/report)
9+
3 | - record: bar
10+
4 | expr: sum(up)
11+
12+
level=INFO msg="Problems found" Bug=1
13+
level=ERROR msg="Fatal error" err="found 1 problem(s) with severity Bug or higher"
14+
-- rules/1.yml --
15+
- alert: foo
16+
expr: up == 0
17+
- record: bar
18+
expr: sum(up)
19+
20+
-- .pint.hcl --
21+
parser {
22+
relaxed = [".*"]
23+
}
24+
rule {
25+
match {
26+
kind = "recording"
27+
}
28+
report {
29+
comment = "You cannot add any recording rules to this Prometheus server."
30+
severity = "bug"
31+
}
32+
}
33+

docs/changelog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## v0.68.0
44

5+
### Added
6+
7+
- Added [rule/report](checks/rule/report.md) check.
8+
59
### Changed
610

711
- pint now uses [Prometheus 3.0](https://prometheus.io/blog/2024/11/14/prometheus-3-0/) libraries

docs/checks/rule/report.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
---
2+
layout: default
3+
parent: Checks
4+
grand_parent: Documentation
5+
---
6+
7+
# rule/report
8+
9+
This check will always report a problem for **every matching rule**.
10+
11+
## Configuration
12+
13+
Syntax:
14+
15+
```js
16+
report {
17+
comment = "..."
18+
severity = "bug|warning|info"
19+
}
20+
```
21+
22+
- `comment` - set a custom comment that will be added to reported problems.
23+
- `severity` - set custom severity for reported issues.
24+
25+
## How to enable it
26+
27+
This check is not enabled by default as it requires explicit configuration
28+
to work.
29+
To enable it add one or more `rule {...}` blocks that matches some rules and
30+
then add a `report` block there.
31+
32+
Example where we block all recording rule:
33+
34+
```js
35+
rule {
36+
match {
37+
kind = "recording"
38+
}
39+
40+
report {
41+
comment = "You cannot add any recording rules to this Prometheus server."
42+
severity = "bug"
43+
}
44+
}
45+
```
46+
47+
## How to disable it
48+
49+
You can disable this check globally by adding this config block:
50+
51+
```js
52+
checks {
53+
disabled = ["rule/report"]
54+
}
55+
```
56+
57+
You can also disable it for all rules inside given file by adding
58+
a comment anywhere in that file. Example:
59+
60+
```yaml
61+
# pint file/disable rule/report
62+
```
63+
64+
Or you can disable it per rule by adding a comment to it. Example:
65+
66+
```yaml
67+
# pint disable rule/report
68+
```
69+
70+
## How to snooze it
71+
72+
You can disable this check until given time by adding a comment to it. Example:
73+
74+
```yaml
75+
# pint snooze $TIMESTAMP rule/report
76+
```
77+
78+
Where `$TIMESTAMP` is either use [RFC3339](https://www.rfc-editor.org/rfc/rfc3339)
79+
formatted or `YYYY-MM-DD`.
80+
Adding this comment will disable `rule/report` _until_ `$TIMESTAMP`, after that
81+
check will be re-enabled.

internal/checks/base.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ var (
3737
LabelCheckName,
3838
RuleLinkCheckName,
3939
RejectCheckName,
40+
ReportCheckName,
4041
}
4142
OnlineChecks = []string{
4243
AlertsAbsentCheckName,

internal/checks/rule_report.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package checks
2+
3+
import (
4+
"context"
5+
6+
"github.com/cloudflare/pint/internal/discovery"
7+
"github.com/cloudflare/pint/internal/parser"
8+
)
9+
10+
const (
11+
ReportCheckName = "rule/report"
12+
)
13+
14+
func NewReportCheck(c string, s Severity) ReportCheck {
15+
return ReportCheck{comment: c, severity: s}
16+
}
17+
18+
type ReportCheck struct {
19+
comment string
20+
severity Severity
21+
}
22+
23+
func (c ReportCheck) Meta() CheckMeta {
24+
return CheckMeta{
25+
States: []discovery.ChangeType{
26+
discovery.Noop,
27+
discovery.Added,
28+
discovery.Modified,
29+
discovery.Moved,
30+
},
31+
IsOnline: false,
32+
}
33+
}
34+
35+
func (c ReportCheck) String() string {
36+
return ReportCheckName
37+
}
38+
39+
func (c ReportCheck) Reporter() string {
40+
return ReportCheckName
41+
}
42+
43+
func (c ReportCheck) Check(_ context.Context, _ discovery.Path, rule parser.Rule, _ []discovery.Entry) (problems []Problem) {
44+
problems = append(problems, Problem{
45+
Lines: rule.Lines,
46+
Reporter: c.Reporter(),
47+
Text: c.comment,
48+
Severity: c.severity,
49+
})
50+
return problems
51+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package checks_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/cloudflare/pint/internal/checks"
7+
"github.com/cloudflare/pint/internal/parser"
8+
"github.com/cloudflare/pint/internal/promapi"
9+
)
10+
11+
func TestReportCheck(t *testing.T) {
12+
testCases := []checkTest{
13+
{
14+
description: "report passed problem / warning",
15+
content: "- alert: foo\n expr: sum(foo)\n annotations:\n alert: foo\n",
16+
checker: func(_ *promapi.FailoverGroup) checks.RuleChecker {
17+
return checks.NewReportCheck("problem reported", checks.Warning)
18+
},
19+
prometheus: noProm,
20+
problems: func(_ string) []checks.Problem {
21+
return []checks.Problem{
22+
{
23+
Lines: parser.LineRange{
24+
First: 1,
25+
Last: 4,
26+
},
27+
Reporter: "rule/report",
28+
Text: "problem reported",
29+
Severity: checks.Warning,
30+
},
31+
}
32+
},
33+
},
34+
{
35+
description: "report passed problem / info",
36+
content: "- record: foo\n expr: sum(foo)\n",
37+
checker: func(_ *promapi.FailoverGroup) checks.RuleChecker {
38+
return checks.NewReportCheck("problem reported", checks.Information)
39+
},
40+
prometheus: noProm,
41+
problems: func(_ string) []checks.Problem {
42+
return []checks.Problem{
43+
{
44+
Lines: parser.LineRange{
45+
First: 1,
46+
Last: 2,
47+
},
48+
Reporter: "rule/report",
49+
Text: "problem reported",
50+
Severity: checks.Information,
51+
},
52+
}
53+
},
54+
},
55+
}
56+
runTests(t, testCases)
57+
}

0 commit comments

Comments
 (0)