chore: 同步监控服务与前端卡片更新
This commit is contained in:
@@ -46,7 +46,7 @@ func GetConfig() *Config {
|
|||||||
Interval: parseDuration(getEnv("MONITOR_INTERVAL", "30m"), 30*time.Minute),
|
Interval: parseDuration(getEnv("MONITOR_INTERVAL", "30m"), 30*time.Minute),
|
||||||
Timeout: parseDuration(getEnv("MONITOR_TIMEOUT", "10s"), 10*time.Second),
|
Timeout: parseDuration(getEnv("MONITOR_TIMEOUT", "10s"), 10*time.Second),
|
||||||
RetryCount: parseInt(getEnv("MONITOR_RETRY_COUNT", "3"), 3),
|
RetryCount: parseInt(getEnv("MONITOR_RETRY_COUNT", "3"), 3),
|
||||||
HistoryDays: parseInt(getEnv("MONITOR_HISTORY_DAYS", "90"), 90),
|
HistoryDays: parseInt(getEnv("MONITOR_HISTORY_DAYS", "30"), 30),
|
||||||
},
|
},
|
||||||
DataPath: getEnv("DATA_PATH", "./data"),
|
DataPath: getEnv("DATA_PATH", "./data"),
|
||||||
Database: DatabaseConfig{
|
Database: DatabaseConfig{
|
||||||
|
|||||||
@@ -42,10 +42,10 @@ type WebsiteStatus struct {
|
|||||||
Website Website `json:"website"`
|
Website Website `json:"website"`
|
||||||
IsIntranet bool `json:"is_intranet"` // 主 URL 为内网 IP:不解析公网 DNS、不展示解析 IP,用内网图标
|
IsIntranet bool `json:"is_intranet"` // 主 URL 为内网 IP:不解析公网 DNS、不展示解析 IP,用内网图标
|
||||||
URLStatuses []URLStatus `json:"url_statuses"`
|
URLStatuses []URLStatus `json:"url_statuses"`
|
||||||
DailyHistory []DailyStats `json:"daily_history"` // 90天逐日统计
|
DailyHistory []DailyStats `json:"daily_history"` // 30天逐日统计
|
||||||
Uptime24h float64 `json:"uptime_24h"` // 24小时可用率
|
Uptime24h float64 `json:"uptime_24h"` // 24小时可用率
|
||||||
Uptime7d float64 `json:"uptime_7d"` // 7天可用率
|
Uptime7d float64 `json:"uptime_7d"` // 7天可用率
|
||||||
Uptime90d float64 `json:"uptime_90d"` // 90天可用率
|
Uptime30d float64 `json:"uptime_30d"` // 30天可用率
|
||||||
LastChecked time.Time `json:"last_checked"` // 最后检测时间
|
LastChecked time.Time `json:"last_checked"` // 最后检测时间
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -287,7 +287,7 @@ func (s *MonitorService) GetWebsiteStatus(websiteID string) *models.WebsiteStatu
|
|||||||
now := time.Now()
|
now := time.Now()
|
||||||
since24h := now.Add(-24 * time.Hour)
|
since24h := now.Add(-24 * time.Hour)
|
||||||
since7d := now.Add(-7 * 24 * time.Hour)
|
since7d := now.Add(-7 * 24 * time.Hour)
|
||||||
since90d := now.Add(-90 * 24 * time.Hour)
|
since30d := now.Add(-30 * 24 * time.Hour)
|
||||||
|
|
||||||
var totalUptime24h, totalUptime7d float64
|
var totalUptime24h, totalUptime7d float64
|
||||||
var urlCount int
|
var urlCount int
|
||||||
@@ -306,9 +306,9 @@ func (s *MonitorService) GetWebsiteStatus(websiteID string) *models.WebsiteStatu
|
|||||||
status.Uptime7d = totalUptime7d / float64(urlCount)
|
status.Uptime7d = totalUptime7d / float64(urlCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
status.DailyHistory = s.storage.GetWebsiteDailyAggregates(website.ID, since90d)
|
status.DailyHistory = s.storage.GetWebsiteDailyAggregates(website.ID, since30d)
|
||||||
if pt, ut := s.storage.GetWebsiteDayProbeTotals(website.ID, since90d); pt > 0 {
|
if pt, ut := s.storage.GetWebsiteDayProbeTotals(website.ID, since30d); pt > 0 {
|
||||||
status.Uptime90d = float64(ut) / float64(pt) * 100
|
status.Uptime30d = float64(ut) / float64(pt) * 100
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取最后检测时间
|
// 获取最后检测时间
|
||||||
@@ -414,18 +414,18 @@ func (s *MonitorService) GetAllWebsiteStatuses() []models.WebsiteStatus {
|
|||||||
now := time.Now()
|
now := time.Now()
|
||||||
since24h := now.Add(-24 * time.Hour)
|
since24h := now.Add(-24 * time.Hour)
|
||||||
since7d := now.Add(-7 * 24 * time.Hour)
|
since7d := now.Add(-7 * 24 * time.Hour)
|
||||||
since90d := now.Add(-90 * 24 * time.Hour)
|
since30d := now.Add(-30 * 24 * time.Hour)
|
||||||
since90dDay := time.Date(since90d.Year(), since90d.Month(), since90d.Day(), 0, 0, 0, 0, since90d.Location())
|
since30dDay := time.Date(since30d.Year(), since30d.Month(), since30d.Day(), 0, 0, 0, 0, since30d.Location())
|
||||||
|
|
||||||
latestMap := s.storage.GetProbeLatestKeyMap()
|
latestMap := s.storage.GetProbeLatestKeyMap()
|
||||||
hourMap := s.storage.GroupProbeHoursSince(since7d)
|
hourMap := s.storage.GroupProbeHoursSince(since7d)
|
||||||
dailyBySite, uptime90dBySite := s.storage.LoadAllWebsiteDayRollups(since90dDay)
|
dailyBySite, uptime30dBySite := s.storage.LoadAllWebsiteDayRollups(since30dDay)
|
||||||
|
|
||||||
statuses := make([]models.WebsiteStatus, 0, len(websites))
|
statuses := make([]models.WebsiteStatus, 0, len(websites))
|
||||||
for _, w := range websites {
|
for _, w := range websites {
|
||||||
daily := dailyBySite[w.ID]
|
daily := dailyBySite[w.ID]
|
||||||
u90 := uptime90dBySite[w.ID]
|
u30 := uptime30dBySite[w.ID]
|
||||||
st := s.buildWebsiteStatusBulk(w, since24h, since7d, latestMap, hourMap, daily, u90)
|
st := s.buildWebsiteStatusBulk(w, since24h, since7d, latestMap, hourMap, daily, u30)
|
||||||
if st != nil {
|
if st != nil {
|
||||||
statuses = append(statuses, *st)
|
statuses = append(statuses, *st)
|
||||||
}
|
}
|
||||||
@@ -439,7 +439,7 @@ func (s *MonitorService) buildWebsiteStatusBulk(
|
|||||||
latestMap map[string]models.MonitorRecord,
|
latestMap map[string]models.MonitorRecord,
|
||||||
hourMap map[string]map[string][]storage.MonitorProbeHour,
|
hourMap map[string]map[string][]storage.MonitorProbeHour,
|
||||||
daily []models.DailyStats,
|
daily []models.DailyStats,
|
||||||
uptime90d float64,
|
uptime30d float64,
|
||||||
) *models.WebsiteStatus {
|
) *models.WebsiteStatus {
|
||||||
isIntranet := len(w.URLs) > 0 && utils.IsIntranetURL(w.URLs[0].URL)
|
isIntranet := len(w.URLs) > 0 && utils.IsIntranetURL(w.URLs[0].URL)
|
||||||
status := &models.WebsiteStatus{
|
status := &models.WebsiteStatus{
|
||||||
@@ -478,7 +478,7 @@ func (s *MonitorService) buildWebsiteStatusBulk(
|
|||||||
} else {
|
} else {
|
||||||
status.DailyHistory = []models.DailyStats{}
|
status.DailyHistory = []models.DailyStats{}
|
||||||
}
|
}
|
||||||
status.Uptime90d = uptime90d
|
status.Uptime30d = uptime30d
|
||||||
for _, urlSt := range status.URLStatuses {
|
for _, urlSt := range status.URLStatuses {
|
||||||
if urlSt.CurrentState.CheckedAt.After(status.LastChecked) {
|
if urlSt.CurrentState.CheckedAt.After(status.LastChecked) {
|
||||||
status.LastChecked = urlSt.CurrentState.CheckedAt
|
status.LastChecked = urlSt.CurrentState.CheckedAt
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useState, useMemo } from 'react';
|
import { useState, useMemo } from 'react';
|
||||||
import { formatLatency, formatUptime, formatTime, getStatusColor, getUptimeColor, getLatencyColor } from '../hooks/useMonitor';
|
import { formatLatency, formatUptime, formatTime, getStatusColor, getUptimeColor, getLatencyColor } from '../hooks/useMonitor';
|
||||||
|
|
||||||
const HISTORY_DAYS = 90;
|
const HISTORY_DAYS = 30;
|
||||||
|
|
||||||
const INTRANET_FALLBACK_ICON =
|
const INTRANET_FALLBACK_ICON =
|
||||||
'https://api.iconify.design/mdi/lan-connect.svg?color=%23059669';
|
'https://api.iconify.design/mdi/lan-connect.svg?color=%23059669';
|
||||||
@@ -75,7 +75,7 @@ export default function WebsiteCard({ website, onRefresh, onEdit, onDelete, read
|
|||||||
return { text: '服务异常', color: 'text-red-500' };
|
return { text: '服务异常', color: 'text-red-500' };
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const uptime90d = website.uptime_90d;
|
const uptime90d = website.uptime_30d;
|
||||||
const hasUptimeData = uptime90d != null && uptime90d > 0;
|
const hasUptimeData = uptime90d != null && uptime90d > 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user