cloudflare/pint

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.22.2

Branches

Tags

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

Clone

HTTPS

Download ZIP

internal/checks/alerts_comparison.go

91lines · modecode

1package checks
2
3import (
4 "context"
5
6 "github.com/cloudflare/pint/internal/discovery"
7 "github.com/cloudflare/pint/internal/parser"
8
9 promParser "github.com/prometheus/prometheus/promql/parser"
10)
11
12const (
13 ComparisonCheckName = "alerts/comparison"
14)
15
16func NewComparisonCheck() ComparisonCheck {
17 return ComparisonCheck{}
18}
19
20type ComparisonCheck struct{}
21
22func (c ComparisonCheck) String() string {
23 return ComparisonCheckName
24}
25
26func (c ComparisonCheck) Reporter() string {
27 return ComparisonCheckName
28}
29
30func (c ComparisonCheck) Check(ctx context.Context, rule parser.Rule, entries []discovery.Entry) (problems []Problem) {
31 if rule.AlertingRule == nil {
32 return
33 }
34
35 if rule.AlertingRule.Expr.SyntaxError != nil {
36 return
37 }
38
39 if isAbsent(rule.Expr().Query) {
40 return
41 }
42
43 if expr := hasComparision(rule.Expr().Query); expr != nil {
44 if expr.ReturnBool {
45 problems = append(problems, Problem{
46 Fragment: rule.AlertingRule.Expr.Value.Value,
47 Lines: rule.AlertingRule.Expr.Lines(),
48 Reporter: c.Reporter(),
49 Text: "alert query uses bool modifier for comparison, this means it will always return a result and the alert will always fire",
50 Severity: Bug,
51 })
52 }
53 return
54 }
55
56 problems = append(problems, Problem{
57 Fragment: rule.AlertingRule.Expr.Value.Value,
58 Lines: rule.AlertingRule.Expr.Lines(),
59 Reporter: c.Reporter(),
60 Text: "alert query doesn't have any condition, it will always fire if the metric exists",
61 Severity: Warning,
62 })
63
64 return
65}
66
67func hasComparision(n *parser.PromQLNode) *promParser.BinaryExpr {
68 if node, ok := n.Node.(*promParser.BinaryExpr); ok {
69 if node.Op.IsComparisonOperator() {
70 return node
71 }
72 if node.Op == promParser.LUNLESS {
73 return node
74 }
75 }
76
77 for _, child := range n.Children {
78 if node := hasComparision(child); node != nil {
79 return node
80 }
81 }
82
83 return nil
84}
85
86func isAbsent(n *parser.PromQLNode) bool {
87 if node, ok := n.Node.(*promParser.Call); ok && (node.Func.Name == "absent") {
88 return true
89 }
90 return false
91}
92