cloudflare/pint

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.22.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

internal/checks/alerts_count.go

114lines · modecode

1package checks
2
3import (
4 "context"
5 "fmt"
6 "sort"
7 "time"
8
9 "github.com/cloudflare/pint/internal/discovery"
10 "github.com/cloudflare/pint/internal/output"
11 "github.com/cloudflare/pint/internal/parser"
12 "github.com/cloudflare/pint/internal/promapi"
13)
14
15const (
16 AlertsCheckName = "alerts/count"
17)
18
19func NewAlertsCheck(prom *promapi.FailoverGroup, lookBack, step, resolve time.Duration) AlertsCheck {
20 return AlertsCheck{
21 prom: prom,
22 lookBack: lookBack,
23 step: step,
24 resolve: resolve,
25 }
26}
27
28type AlertsCheck struct {
29 prom *promapi.FailoverGroup
30 lookBack time.Duration
31 step time.Duration
32 resolve time.Duration
33}
34
35func (c AlertsCheck) String() string {
36 return fmt.Sprintf("%s(%s)", AlertsCheckName, c.prom.Name())
37}
38
39func (c AlertsCheck) Reporter() string {
40 return AlertsCheckName
41}
42
43func (c AlertsCheck) Check(ctx context.Context, rule parser.Rule, entries []discovery.Entry) (problems []Problem) {
44 if rule.AlertingRule == nil {
45 return
46 }
47
48 if rule.AlertingRule.Expr.SyntaxError != nil {
49 return
50 }
51
52 end := time.Now()
53 start := end.Add(c.lookBack * -1)
54 qr, err := c.prom.RangeQuery(ctx, rule.AlertingRule.Expr.Value.Value, start, end, c.step)
55 if err != nil {
56 text, severity := textAndSeverityFromError(err, c.Reporter(), c.prom.Name(), Bug)
57 problems = append(problems, Problem{
58 Fragment: rule.AlertingRule.Expr.Value.Value,
59 Lines: rule.AlertingRule.Expr.Lines(),
60 Reporter: c.Reporter(),
61 Text: text,
62 Severity: severity,
63 })
64 return
65 }
66
67 var forDur time.Duration
68 if rule.AlertingRule.For != nil {
69 forDur, _ = time.ParseDuration(rule.AlertingRule.For.Value.Value)
70 }
71
72 var alerts int
73 for _, sample := range qr.Samples {
74 var isAlerting, isNew bool
75 var firstTime, lastTime time.Time
76 for _, value := range sample.Values {
77 isNew = value.Timestamp.Time().After(lastTime.Add(c.step))
78 if isNew {
79 if rule.AlertingRule.For != nil {
80 isAlerting = false
81 } else {
82 isAlerting = true
83 alerts++
84 }
85 firstTime = value.Timestamp.Time()
86 } else {
87 if !isAlerting && rule.AlertingRule.For != nil {
88 if !value.Timestamp.Time().Before(firstTime.Add(forDur)) {
89 isAlerting = true
90 alerts++
91 }
92 }
93 }
94 lastTime = value.Timestamp.Time()
95 }
96 }
97
98 lines := []int{}
99 lines = append(lines, rule.AlertingRule.Expr.Lines()...)
100 if rule.AlertingRule.For != nil {
101 lines = append(lines, rule.AlertingRule.For.Lines()...)
102 }
103 sort.Ints(lines)
104
105 delta := qr.End.Sub(qr.Start)
106 problems = append(problems, Problem{
107 Fragment: rule.AlertingRule.Expr.Value.Value,
108 Lines: lines,
109 Reporter: c.Reporter(),
110 Text: fmt.Sprintf("%s would trigger %d alert(s) in the last %s", promText(c.prom.Name(), qr.URI), alerts, output.HumanizeDuration(delta)),
111 Severity: Information,
112 })
113 return
114}
115