-
Notifications
You must be signed in to change notification settings - Fork 1
/
check_status.go
120 lines (103 loc) · 4.04 KB
/
check_status.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package job
import (
"database/sql"
"fmt"
"github.com/flanksource/duty/context"
"github.com/flanksource/duty/models"
"gorm.io/gorm/clause"
)
func RefreshCheckSizeSummary(ctx context.Context) error {
return ctx.DB().Exec("REFRESH MATERIALIZED VIEW check_size_summary").Error
}
func RefreshCheckStatusSummary(ctx context.Context) error {
return ctx.DB().Exec("REFRESH MATERIALIZED VIEW check_status_summary").Error
}
func RefreshCheckStatusSummaryAged(ctx context.Context) error {
return ctx.DB().Exec("REFRESH MATERIALIZED VIEW check_status_summary_aged").Error
}
func DeleteOldCheckStatuses(ctx context.Context, retention int) (int, error) {
tx := ctx.DB().Exec(`DELETE FROM check_statuses WHERE (NOW() - time) > INTERVAL '1 day' * ?`, retention)
return int(tx.RowsAffected), tx.Error
}
func DeleteOldCheckStatuses1d(ctx context.Context, retention int) (int, error) {
tx := ctx.DB().Exec(`DELETE FROM check_statuses_1d WHERE (NOW() - created_at) > INTERVAL '1 day' * ?`, retention)
return int(tx.RowsAffected), tx.Error
}
func DeleteOldCheckStatuses1h(ctx context.Context, retention int) (int, error) {
tx := ctx.DB().Exec(`DELETE FROM check_statuses_1h WHERE (NOW() - created_at) > INTERVAL '1 day' * ?`, retention)
return int(tx.RowsAffected), tx.Error
}
func AggregateCheckStatus1d(ctx context.Context) (int, error) {
const query = `
SELECT
check_statuses.check_id,
date_trunc(?, "time"),
count(*) AS total_checks,
count(*) FILTER (WHERE check_statuses.status = TRUE) AS passed,
count(*) FILTER (WHERE check_statuses.status = FALSE) AS failed,
SUM(duration) AS duration
FROM check_statuses
LEFT JOIN checks ON check_statuses.check_id = checks.id
WHERE check_statuses.time > NOW() - INTERVAL '1 hour' * ?
GROUP BY 1, 2
ORDER BY 1, 2 DESC`
var rows *sql.Rows
var err error
rows, err = ctx.DB().Raw(query, "day", 3*24).Rows() // Only look for aggregated data in the last 3 days
if err != nil {
return 0, fmt.Errorf("error aggregating check statuses 1h: %w", err)
} else if rows.Err() != nil {
return 0, fmt.Errorf("error aggregating check statuses 1h: %w", rows.Err())
}
defer rows.Close()
count := 0
for rows.Next() {
count++
var aggr models.CheckStatusAggregate1d
if err := rows.Scan(&aggr.CheckID, &aggr.CreatedAt, &aggr.Total, &aggr.Passed, &aggr.Failed, &aggr.Duration); err != nil {
return 0, fmt.Errorf("error scanning aggregated check statuses: %w", err)
}
cols := []clause.Column{{Name: "check_id"}, {Name: "created_at"}}
if err := ctx.DB().Clauses(clause.OnConflict{Columns: cols, UpdateAll: true}).Create(aggr).Error; err != nil {
return 0, fmt.Errorf("error upserting canaries: %w", err)
}
}
return count, nil
}
func AggregateCheckStatus1h(ctx context.Context) (int, error) {
const query = `
SELECT
check_statuses.check_id,
date_trunc(?, "time"),
count(*) AS total_checks,
count(*) FILTER (WHERE check_statuses.status = TRUE) AS passed,
count(*) FILTER (WHERE check_statuses.status = FALSE) AS failed,
SUM(duration) AS duration
FROM check_statuses
LEFT JOIN checks ON check_statuses.check_id = checks.id
WHERE check_statuses.time > NOW() - INTERVAL '1 hour' * ?
GROUP BY 1, 2
ORDER BY 1, 2 DESC`
var rows *sql.Rows
var err error
rows, err = ctx.DB().Raw(query, "hour", 3).Rows() // Only look for aggregated data in the last 3 hour
if err != nil {
return 0, fmt.Errorf("error aggregating check statuses 1h: %w", err)
} else if rows.Err() != nil {
return 0, fmt.Errorf("error aggregating check statuses 1h: %w", rows.Err())
}
defer rows.Close()
count := 0
for rows.Next() {
count += 0
var aggr models.CheckStatusAggregate1h
if err := rows.Scan(&aggr.CheckID, &aggr.CreatedAt, &aggr.Total, &aggr.Passed, &aggr.Failed, &aggr.Duration); err != nil {
return 0, fmt.Errorf("error scanning aggregated check statuses: %w", err)
}
cols := []clause.Column{{Name: "check_id"}, {Name: "created_at"}}
if err := ctx.DB().Clauses(clause.OnConflict{Columns: cols, UpdateAll: true}).Create(aggr).Error; err != nil {
return 0, fmt.Errorf("error upserting canaries: %w", err)
}
}
return count, nil
}