cloudflare/pint

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.49.2

Branches

Tags

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

Clone

HTTPS

Download ZIP

internal/checks/alerts_comparison_test.go

221lines · modecode

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