Add persistent thresholds and seven-day metrics history
This commit is contained in:
34
alerts.go
34
alerts.go
@@ -15,37 +15,37 @@ type Alert struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func evaluateAlerts(metrics dashboardMetrics) []Alert {
|
||||
func evaluateAlerts(metrics dashboardMetrics, thresholds AlertThresholds) []Alert {
|
||||
var alerts []Alert
|
||||
add := func(id, severity, source, title, message string) {
|
||||
alerts = append(alerts, Alert{ID: id, Severity: severity, Source: source, Title: title, Message: message})
|
||||
}
|
||||
|
||||
if metrics.CPU.UsagePercent >= 95 {
|
||||
if metrics.CPU.UsagePercent >= thresholds.CPUCritical {
|
||||
add("cpu-usage", "critical", "CPU", "Очень высокая загрузка CPU", fmt.Sprintf("Текущая загрузка %.1f%%.", metrics.CPU.UsagePercent))
|
||||
} else if metrics.CPU.UsagePercent >= 85 {
|
||||
} else if metrics.CPU.UsagePercent >= thresholds.CPUWarning {
|
||||
add("cpu-usage", "warning", "CPU", "Высокая загрузка CPU", fmt.Sprintf("Текущая загрузка %.1f%%.", metrics.CPU.UsagePercent))
|
||||
}
|
||||
for _, temperature := range metrics.CPU.Temperatures {
|
||||
if temperature.Celsius >= 90 {
|
||||
if temperature.Celsius >= thresholds.CPUTempCritical {
|
||||
add("cpu-temp-"+temperature.Label, "critical", "CPU", "Критическая температура CPU", fmt.Sprintf("%s: %.1f °C.", temperature.Label, temperature.Celsius))
|
||||
} else if temperature.Celsius >= 80 {
|
||||
} else if temperature.Celsius >= thresholds.CPUTempWarning {
|
||||
add("cpu-temp-"+temperature.Label, "warning", "CPU", "Высокая температура CPU", fmt.Sprintf("%s: %.1f °C.", temperature.Label, temperature.Celsius))
|
||||
}
|
||||
}
|
||||
|
||||
if metrics.Memory.UsagePercent >= 95 {
|
||||
if metrics.Memory.UsagePercent >= thresholds.MemoryCritical {
|
||||
add("memory", "critical", "Память", "Почти закончилась оперативная память", fmt.Sprintf("Используется %.1f%% RAM.", metrics.Memory.UsagePercent))
|
||||
} else if metrics.Memory.UsagePercent >= 85 {
|
||||
} else if metrics.Memory.UsagePercent >= thresholds.MemoryWarning {
|
||||
add("memory", "warning", "Память", "Высокое использование памяти", fmt.Sprintf("Используется %.1f%% RAM.", metrics.Memory.UsagePercent))
|
||||
}
|
||||
if metrics.Memory.SwapTotalBytes > 0 && metrics.Memory.SwapPercent >= 50 {
|
||||
if metrics.Memory.SwapTotalBytes > 0 && metrics.Memory.SwapPercent >= thresholds.SwapWarning {
|
||||
add("swap", "warning", "Память", "Активно используется swap", fmt.Sprintf("Занято %.1f%% swap.", metrics.Memory.SwapPercent))
|
||||
}
|
||||
|
||||
if metrics.Storage.UsagePercent >= 95 {
|
||||
if metrics.Storage.UsagePercent >= thresholds.StorageCritical {
|
||||
add("root-storage", "critical", "Storage", "Системный раздел почти заполнен", fmt.Sprintf("Раздел / заполнен на %.1f%%.", metrics.Storage.UsagePercent))
|
||||
} else if metrics.Storage.UsagePercent >= 85 {
|
||||
} else if metrics.Storage.UsagePercent >= thresholds.StorageWarning {
|
||||
add("root-storage", "warning", "Storage", "Мало места на системном разделе", fmt.Sprintf("Раздел / заполнен на %.1f%%.", metrics.Storage.UsagePercent))
|
||||
}
|
||||
for _, disk := range metrics.Disks {
|
||||
@@ -55,9 +55,9 @@ func evaluateAlerts(metrics dashboardMetrics) []Alert {
|
||||
add("disk-smart-"+disk.Name, "warning", "Диски", disk.Model+": SMART требует внимания", joinReasons(disk.AttentionReasons, "Проверьте SMART-показатели диска."))
|
||||
}
|
||||
if disk.Temperature != nil {
|
||||
limit := 60.0
|
||||
limit := thresholds.DiskTempWarning
|
||||
if strings.Contains(disk.Type, "NVMe") {
|
||||
limit = 75
|
||||
limit = thresholds.NVMeTempWarning
|
||||
}
|
||||
if *disk.Temperature >= limit {
|
||||
add("disk-temp-"+disk.Name, "warning", "Диски", disk.Model+": высокая температура", fmt.Sprintf("Температура %.1f °C.", *disk.Temperature))
|
||||
@@ -69,9 +69,9 @@ func evaluateAlerts(metrics dashboardMetrics) []Alert {
|
||||
if pool.Health != "ONLINE" {
|
||||
add("zfs-health-"+pool.Name, "critical", "ZFS", pool.Name+": пул не ONLINE", joinReasons(pool.AttentionReasons, "Текущее состояние: "+pool.Health+"."))
|
||||
}
|
||||
if pool.CapacityPercent >= 90 {
|
||||
if pool.CapacityPercent >= thresholds.ZFSCritical {
|
||||
add("zfs-capacity-"+pool.Name, "critical", "ZFS", pool.Name+": пул почти заполнен", fmt.Sprintf("Заполнение %.1f%%.", pool.CapacityPercent))
|
||||
} else if pool.CapacityPercent >= 80 {
|
||||
} else if pool.CapacityPercent >= thresholds.ZFSWarning {
|
||||
add("zfs-capacity-"+pool.Name, "warning", "ZFS", pool.Name+": мало свободного места", fmt.Sprintf("Заполнение %.1f%%.", pool.CapacityPercent))
|
||||
}
|
||||
if strings.Contains(strings.ToLower(pool.Scan), "in progress") {
|
||||
@@ -86,7 +86,7 @@ func evaluateAlerts(metrics dashboardMetrics) []Alert {
|
||||
} else if strings.Contains(status, "OB") || status == "ONBATT" {
|
||||
add("ups-battery", "warning", "UPS", "Сервер работает от UPS", "Основное питание отсутствует, используется батарея.")
|
||||
}
|
||||
if metrics.UPS.ChargePercent != nil && *metrics.UPS.ChargePercent < 30 {
|
||||
if metrics.UPS.ChargePercent != nil && *metrics.UPS.ChargePercent < thresholds.UPSChargeCritical {
|
||||
add("ups-charge", "critical", "UPS", "Низкий заряд батареи", fmt.Sprintf("Осталось %.1f%%.", *metrics.UPS.ChargePercent))
|
||||
}
|
||||
}
|
||||
@@ -111,8 +111,8 @@ func evaluateAlerts(metrics dashboardMetrics) []Alert {
|
||||
continue
|
||||
}
|
||||
age := now.Sub(time.Unix(backup.CreatedAt, 0))
|
||||
if age > 48*time.Hour {
|
||||
add(fmt.Sprintf("backup-old-%d", guest.VMID), "warning", "Backups", name+": копия старше 48 часов", fmt.Sprintf("Последняя копия создана %.0f часов назад на %s.", age.Hours(), backup.Storage))
|
||||
if age > time.Duration(thresholds.BackupMaxAgeHours*float64(time.Hour)) {
|
||||
add(fmt.Sprintf("backup-old-%d", guest.VMID), "warning", "Backups", fmt.Sprintf("%s: копия старше %.0f часов", name, thresholds.BackupMaxAgeHours), fmt.Sprintf("Последняя копия создана %.0f часов назад на %s.", age.Hours(), backup.Storage))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user