cloudflare/pint

Public

mirrored from https://github.com/cloudflare/pintAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.62.2

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

internal/checks/alerts_comparison_test.go

234lines · modecode

1package checks_test
2
3import (
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
11func newComparisonCheck(_ *promapi.FailoverGroup) checks.RuleChecker {
12 return checks.NewComparisonCheck()
13}
14
15func TestComparisonCheck(t *testing.T) {
16 testCases := []checkTest{
17 {
18 description: "ignores recording rules",
19 content: "- record: foo\n expr: up == 0\n",
20 checker: newComparisonCheck,
21 prometheus: noProm,
22 problems: noProblems,
23 },
24 {
25 description: "ignores rules with syntax errors",
26 content: "- alert: Foo Is Down\n expr: sum(\n",
27 checker: newComparisonCheck,
28 prometheus: noProm,
29 problems: noProblems,
30 },
31 {
32 description: "alert expr with > condition",
33 content: "- alert: Foo Is Down\n for: 10m\n expr: up{job=\"foo\"} > 0\n",
34 checker: newComparisonCheck,
35 prometheus: noProm,
36 problems: noProblems,
37 },
38 {
39 description: "alert expr with >= condition",
40 content: "- alert: Foo Is Down\n for: 10m\n expr: up{job=\"foo\"} >= 1\n",
41 checker: newComparisonCheck,
42 prometheus: noProm,
43 problems: noProblems,
44 },
45 {
46 description: "alert expr with == condition",
47 content: "- alert: Foo Is Down\n for: 10m\n expr: up{job=\"foo\"} == 1\n",
48 checker: newComparisonCheck,
49 prometheus: noProm,
50 problems: noProblems,
51 },
52 {
53 description: "alert expr without any condition",
54 content: "- alert: Foo Is Down\n expr: up{job=\"foo\"}\n",
55 checker: newComparisonCheck,
56 prometheus: noProm,
57 problems: func(_ string) []checks.Problem {
58 return []checks.Problem{
59 {
60 Lines: parser.LineRange{
61 First: 2,
62 Last: 2,
63 },
64 Reporter: checks.ComparisonCheckName,
65 Text: "Alert query doesn't have any condition, it will always fire if the metric exists.",
66 Details: checks.ComparisonCheckDetails,
67 Severity: checks.Warning,
68 },
69 }
70 },
71 },
72 {
73 description: "deep level comparison",
74 content: `
75- alert: High_UDP_Receive_Errors
76 expr: quantile_over_time(0.7,(irate(udp_packets_drops[2m]))[10m:2m]) > 200
77 AND ON (instance)
78 (rate(node_netstat_Udp_RcvbufErrors[5m])+rate(node_netstat_Udp6_RcvbufErrors[5m])) > 200
79`,
80 checker: newComparisonCheck,
81 prometheus: noProm,
82 problems: noProblems,
83 },
84 {
85 description: "deep level without comparison",
86 content: `
87- alert: High_UDP_Receive_Errors
88 expr: quantile_over_time(0.7,(irate(udp_packets_drops[2m]))[10m:2m])
89 AND ON (instance)
90 rate(node_netstat_Udp_RcvbufErrors[5m])+rate(node_netstat_Udp6_RcvbufErrors[5m])
91`,
92 checker: newComparisonCheck,
93 prometheus: noProm,
94 problems: func(_ string) []checks.Problem {
95 return []checks.Problem{
96 {
97 Lines: parser.LineRange{
98 First: 3,
99 Last: 3,
100 },
101 Reporter: checks.ComparisonCheckName,
102 Text: "Alert query doesn't have any condition, it will always fire if the metric exists.",
103 Details: checks.ComparisonCheckDetails,
104 Severity: checks.Warning,
105 },
106 }
107 },
108 },
109 {
110 description: "alert unless condition",
111 content: "- alert: Foo Is Down\n for: 10m\n expr: foo unless bar\n",
112 checker: newComparisonCheck,
113 prometheus: noProm,
114 problems: noProblems,
115 },
116 {
117 description: "alert expr with bool",
118 content: "- alert: Error rate is high\n expr: rate(error_count[5m]) > bool 5\n",
119 checker: newComparisonCheck,
120 prometheus: noProm,
121 problems: func(_ string) []checks.Problem {
122 return []checks.Problem{
123 {
124 Lines: parser.LineRange{
125 First: 2,
126 Last: 2,
127 },
128 Reporter: checks.ComparisonCheckName,
129 Text: "Alert query uses `bool` modifier for comparison, this means it will always return a result and the alert will always fire.",
130 Details: checks.ComparisonCheckDetails,
131 Severity: checks.Bug,
132 },
133 }
134 },
135 },
136 {
137 description: "alert expr with bool and condition",
138 content: "- alert: Error rate is high\n expr: rate(error_count[5m]) > bool 5 == 1\n",
139 checker: newComparisonCheck,
140 prometheus: noProm,
141 problems: noProblems,
142 },
143 {
144 description: "alert on absent",
145 content: "- alert: Foo Is Missing\n expr: absent(foo)\n",
146 checker: newComparisonCheck,
147 prometheus: noProm,
148 problems: noProblems,
149 },
150 {
151 description: "absent or absent",
152 content: "- alert: Foo Is Missing\n expr: absent(foo) or absent(bar)\n",
153 checker: newComparisonCheck,
154 prometheus: noProm,
155 problems: noProblems,
156 },
157 {
158 description: "absent or absent or absent",
159 content: "- alert: Foo Is Missing\n expr: absent(foo) or absent(bar) or absent(bob{job=\"xx\"})\n",
160 checker: newComparisonCheck,
161 prometheus: noProm,
162 problems: noProblems,
163 },
164 {
165 description: "(foo > 1) > bool 1",
166 content: "- alert: Foo Is Missing\n expr: (foo > 1) > bool 1\n",
167 checker: newComparisonCheck,
168 prometheus: noProm,
169 problems: noProblems,
170 },
171 {
172 description: "vector(0) or (foo > 0)",
173 content: "- alert: Foo Is Down\n expr: (foo > 0) or vector(0)\n",
174 checker: newComparisonCheck,
175 prometheus: noProm,
176 problems: func(_ string) []checks.Problem {
177 return []checks.Problem{
178 {
179 Lines: parser.LineRange{
180 First: 2,
181 Last: 2,
182 },
183 Reporter: checks.ComparisonCheckName,
184 Text: "Alert query uses `or` operator with one side of the query that will always return a result, this alert will always fire.",
185 Details: checks.ComparisonCheckDetails,
186 Severity: checks.Bug,
187 },
188 }
189 },
190 },
191 {
192 description: "(foo > 0) or vector(0)",
193 content: "- alert: Foo Is Down\n expr: (foo > 0) or vector(0)\n",
194 checker: newComparisonCheck,
195 prometheus: noProm,
196 problems: func(_ string) []checks.Problem {
197 return []checks.Problem{
198 {
199 Lines: parser.LineRange{
200 First: 2,
201 Last: 2,
202 },
203 Reporter: checks.ComparisonCheckName,
204 Text: "Alert query uses `or` operator with one side of the query that will always return a result, this alert will always fire.",
205 Details: checks.ComparisonCheckDetails,
206 Severity: checks.Bug,
207 },
208 }
209 },
210 },
211 {
212 description: "absent(foo) or vector(0)",
213 content: "- alert: Foo Is Down\n expr: (foo > 0) or vector(0)\n",
214 checker: newComparisonCheck,
215 prometheus: noProm,
216 problems: func(_ string) []checks.Problem {
217 return []checks.Problem{
218 {
219 Lines: parser.LineRange{
220 First: 2,
221 Last: 2,
222 },
223 Reporter: checks.ComparisonCheckName,
224 Text: "Alert query uses `or` operator with one side of the query that will always return a result, this alert will always fire.",
225 Details: checks.ComparisonCheckDetails,
226 Severity: checks.Bug,
227 },
228 }
229 },
230 },
231 }
232
233 runTests(t, testCases)
234}
235