feat: add monitoring retention controls

This commit is contained in:
sagitchu
2026-04-28 11:41:07 +08:00
parent e8d5687419
commit 023be27287
15 changed files with 430 additions and 13 deletions
@@ -22,6 +22,7 @@ import (
"go-backend/internal/http/response"
"go-backend/internal/license"
"go-backend/internal/metrics"
"go-backend/internal/monitoring"
"go-backend/internal/security"
"go-backend/internal/store/repo"
"go-backend/internal/ws"
@@ -152,6 +153,7 @@ func (h *Handler) Register(mux *http.ServeMux) {
mux.HandleFunc("/api/v1/config/list", h.getConfigs)
mux.HandleFunc("/api/v1/config/update", h.updateConfigs)
mux.HandleFunc("/api/v1/config/update-single", h.updateSingleConfig)
mux.HandleFunc("/api/v1/system/storage", h.storageSummary)
mux.HandleFunc("/api/v1/license/activate", h.licenseActivate)
mux.HandleFunc("/api/v1/backup/export", h.backupExport)
mux.HandleFunc("/api/v1/backup/import", h.backupImport)
@@ -1036,6 +1038,8 @@ func normalizeAndValidateConfigValue(key, value string) (string, error) {
default:
return "", fmt.Errorf("隧道质量检测开关配置值无效")
}
case monitoring.ConfigMonitorRetentionDays:
return monitoring.NormalizeMonitoringRetentionDays(value)
default:
return value, nil
}
@@ -0,0 +1,25 @@
package handler
import (
"net/http"
"go-backend/internal/http/response"
)
func (h *Handler) storageSummary(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet && r.Method != http.MethodPost {
response.WriteJSON(w, response.ErrDefault("请求失败"))
return
}
if h == nil || h.repo == nil {
response.WriteJSON(w, response.Err(-2, "repository not initialized"))
return
}
summary, err := h.repo.DatabaseStorageSummary()
if err != nil {
response.WriteJSON(w, response.Err(-2, err.Error()))
return
}
response.WriteJSON(w, response.OK(summary))
}
@@ -8,6 +8,7 @@ import (
"sync/atomic"
"time"
"go-backend/internal/monitoring"
"go-backend/internal/store/model"
)
@@ -15,7 +16,6 @@ const (
tunnelQualityProbeInterval = 1 * time.Second
tunnelQualityProbeTimeout = 8 * time.Second
tunnelQualityPingTimeoutMs = 5000
tunnelQualityRetention = 24 * time.Hour // keep 24h of history
tunnelQualityPruneInterval = 10 * time.Minute
tunnelQualityReportInterval = 30 * time.Second // DB save interval
)
@@ -128,12 +128,19 @@ func (p *tunnelQualityProber) isEnabled() bool {
return p.handler.isTunnelQualityMonitoringEnabled()
}
func (p *tunnelQualityProber) retentionDays() int {
if p == nil || p.handler == nil || p.handler.repo == nil {
return monitoring.DefaultMonitorRetentionDays
}
cfg, err := p.handler.repo.GetConfigsByNames([]string{monitoring.ConfigMonitorRetentionDays})
if err != nil {
return monitoring.DefaultMonitorRetentionDays
}
return monitoring.MonitoringRetentionDaysFromConfigMap(cfg)
}
// maybePrune deletes old quality rows periodically (mirrors PruneServiceMonitorResults).
func (p *tunnelQualityProber) maybePrune() {
if !p.isEnabled() {
return
}
now := time.Now().UnixMilli()
if p.lastPrune > 0 && now-p.lastPrune < int64(tunnelQualityPruneInterval/time.Millisecond) {
return
@@ -145,7 +152,7 @@ func (p *tunnelQualityProber) maybePrune() {
return
}
cutoff := now - int64(tunnelQualityRetention/time.Millisecond)
cutoff := now - int64(time.Duration(p.retentionDays())*24*time.Hour/time.Millisecond)
if err := h.repo.PruneTunnelQualityResults(cutoff); err != nil {
log.Printf("tunnel_quality_prober: prune err=%v", err)
}
@@ -287,7 +294,7 @@ func (p *tunnelQualityProber) probeTunnel(tunnelID int64) {
hops = append(hops, hop)
break
}
fromNode, _ := h.getNodeRecord(source.NodeID)
targetIP, targetPort, resolveErr := resolveChainProbeTarget(fromNode, targetNode, target.Port, ipPreference, target.ConnectIP)
if resolveErr != nil {