121 строка
3.6 KiB
Go
121 строка
3.6 KiB
Go
package models
|
|
|
|
// StatsData provides functionality.
|
|
type StatsData struct {
|
|
MonitorID *int64 `json:"monitor_id,omitempty"`
|
|
Up30d *float64 `json:"up_30d"`
|
|
Up7d *float64 `json:"up_7d"`
|
|
Up1d *float64 `json:"up_1d"`
|
|
}
|
|
|
|
// Process provides functionality.
|
|
func (data *StatsData) Process() {
|
|
if data.Up1d == nil {
|
|
dv := 100.0
|
|
data.Up1d = &dv
|
|
}
|
|
if data.Up7d == nil {
|
|
dv := 100.0
|
|
data.Up7d = &dv
|
|
}
|
|
if data.Up30d == nil {
|
|
dv := 100.0
|
|
data.Up30d = &dv
|
|
}
|
|
}
|
|
|
|
// 86400 seconds / 1d
|
|
// 604800 seconds / 7d
|
|
// 2592000 seconds / 30d
|
|
|
|
// UptimeSQL provides functionality.
|
|
const UptimeSQL = `
|
|
SELECT
|
|
monitors.id AS monitor_id,
|
|
round(up1.up::numeric, 3) AS up1d,
|
|
round(up7.up::numeric, 3) AS up7d,
|
|
round(up30.up::numeric, 3) AS up30d
|
|
FROM monitors
|
|
LEFT JOIN (
|
|
select monitor_id, CAST(10000 - (10000 * sum(duration) / min(lt.least)) as float) / 100 as up from events
|
|
join (
|
|
select id, LEAST(extract(epoch from (NOW() - created_at))::int, 86400) from monitors
|
|
) lt ON lt.id = events.monitor_id
|
|
where start_time > NOW() - interval '1' day
|
|
group by monitor_id
|
|
) up1 ON monitors.id = up1.monitor_id
|
|
LEFT JOIN (
|
|
select monitor_id, CAST(10000 - (10000 * sum(duration) / min(lt.least)) as float) / 100 as up from events
|
|
join (
|
|
select id, LEAST(extract(epoch from (NOW() - created_at))::int, 604800) from monitors
|
|
) lt ON lt.id = events.monitor_id
|
|
where start_time > NOW() - interval '7' day
|
|
group by monitor_id
|
|
) up7 ON monitors.id = up7.monitor_id
|
|
LEFT JOIN (
|
|
select monitor_id, CAST(10000 - (10000 * sum(duration) / min(lt.least)) as float) / 100 as up from events
|
|
join (
|
|
select id, LEAST(extract(epoch from (NOW() - created_at))::int, 2592000) from monitors
|
|
) lt ON lt.id = events.monitor_id
|
|
where start_time > NOW() - interval '30' day
|
|
group by monitor_id
|
|
) up30 ON monitors.id = up30.monitor_id
|
|
`
|
|
|
|
// UptimeAllSQL provides functionality.
|
|
const UptimeAllSQL = `
|
|
SELECT
|
|
round(up1.up::numeric, 3) AS up1d,
|
|
round(up7.up::numeric, 3) AS up7d,
|
|
round(up30.up::numeric, 3) AS up30d
|
|
FROM (
|
|
select CAST(10000 - (10000 * sum(duration) / sum(lt.least)) as float) / 100 as up from events
|
|
join (
|
|
select id, LEAST(extract(epoch from (NOW() - created_at))::int, 86400) from monitors
|
|
) lt ON lt.id = events.monitor_id
|
|
where start_time > NOW() - interval '1' day AND events.monitor_id IN (?)
|
|
) up1, (
|
|
select CAST(10000 - (10000 * sum(duration) / sum(lt.least)) as float) / 100 as up from events
|
|
join (
|
|
select id, LEAST(extract(epoch from (NOW() - created_at))::int, 604800) from monitors
|
|
) lt ON lt.id = events.monitor_id
|
|
where start_time > NOW() - interval '7' day AND events.monitor_id IN (?)
|
|
) up7, (
|
|
select CAST(10000 - (10000 * sum(duration) / sum(lt.least)) as float) / 100 as up from events
|
|
join (
|
|
select id, LEAST(extract(epoch from (NOW() - created_at))::int, 2592000) from monitors
|
|
) lt ON lt.id = events.monitor_id
|
|
where start_time > NOW() - interval '30' day AND events.monitor_id IN (?)
|
|
) up30
|
|
`
|
|
|
|
// MonitorStats provides functionality.
|
|
func MonitorStats(monitors *[]Monitor) error {
|
|
ids := make([]int64, len(*monitors))
|
|
for i, m := range *monitors { //nolint:gocritic // range copy is acceptable here
|
|
ids[i] = m.ID
|
|
}
|
|
|
|
rows, err := DB().Raw(UptimeSQL+"WHERE monitors.id IN (?)", ids).Rows()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
stats := make(map[int64]StatsData, 0)
|
|
|
|
defer rows.Close() //nolint:errcheck
|
|
for rows.Next() {
|
|
data := StatsData{}
|
|
_ = DB().ScanRows(rows, &data)
|
|
data.Process()
|
|
|
|
stats[*data.MonitorID] = data
|
|
}
|
|
|
|
for i, m := range *monitors { //nolint:gocritic // range copy is acceptable here
|
|
(*monitors)[i].StatsData = stats[m.ID]
|
|
}
|
|
|
|
return nil
|
|
}
|