Files
worker/app/models/stats_data.go
Gleb Tv 2c7a0236da feat: publish standalone worker
Separate worker packaging and service lifecycle from the control plane.
2026-07-13 17:55:14 +03:00

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
}