3x-ui/web/job/check_cpu_usage.go

41 lines
1.1 KiB
Go
Raw Normal View History

2023-03-17 16:07:49 +00:00
package job
import (
2023-05-20 23:00:26 +00:00
"strconv"
2023-03-17 16:07:49 +00:00
"time"
2025-09-19 08:05:43 +00:00
"github.com/mhsanaei/3x-ui/v2/web/service"
2023-03-17 16:07:49 +00:00
2024-06-17 19:48:49 +00:00
"github.com/shirou/gopsutil/v4/cpu"
2023-03-17 16:07:49 +00:00
)
2025-09-20 07:35:50 +00:00
// CheckCpuJob monitors CPU usage and sends Telegram notifications when usage exceeds the configured threshold.
2023-03-17 16:07:49 +00:00
type CheckCpuJob struct {
tgbotService service.Tgbot
settingService service.SettingService
}
2025-09-20 07:35:50 +00:00
// NewCheckCpuJob creates a new CPU monitoring job instance.
2023-03-17 16:07:49 +00:00
func NewCheckCpuJob() *CheckCpuJob {
return new(CheckCpuJob)
}
2025-09-20 07:35:50 +00:00
// Run checks CPU usage over the last minute and sends a Telegram alert if it exceeds the threshold.
2023-03-17 16:07:49 +00:00
func (j *CheckCpuJob) Run() {
threshold, err := j.settingService.GetTgCpu()
if err != nil || threshold <= 0 {
// If threshold cannot be retrieved or is not set, skip sending notifications
return
}
2023-03-17 16:07:49 +00:00
// get latest status of server
percent, err := cpu.Percent(1*time.Minute, false)
fix: comprehensive bug fixes across the codebase ## Critical Fixes ### 1. DATA LOSS: 5 functions discard all other clients when updating one Functions affected: - SetClientTelegramUserID - ToggleClientEnableByEmail - ResetClientIpLimitByEmail - ResetClientExpiryTimeByEmail - ResetClientTrafficLimitByEmail All five built a `newClients` slice by only appending the client matching the target email, then replaced the entire client list. Every other client in the inbound was silently deleted. Fix: update client in-place with break instead of building new slice. ### 2. DATA LOSS: ResetSettings never deletes user credentials ResetSettings() called `.Where("1 = 1").Error` instead of `.Delete(model.User{}).Error`. The reset command did nothing to users. ### 3. SECURITY: WebSocket CheckOrigin allows cross-origin hijacking The fallback `(originHost == "" || requestHost == "")` accepted any origin with a missing host component. Removed the fallback and added proper host normalization for IPv6/ports. ### 4. GRACEFUL SHUTDOWN: Server.Stop() uses cancelled context s.cancel() was called before s.httpServer.Shutdown(s.ctx), making the context already-done. Shutdown returned immediately (forced kill) instead of waiting 10 seconds. Moved s.cancel() to end and used context.WithTimeout(10s) for shutdown. Same fix applied to sub.go. ## Medium Fixes ### 5. Wrong success messages on error paths (~11 endpoints) When validation failed, endpoints returned messages like "inboundUpdateSuccess" alongside the error. Fixed to use "somethingWentWrong" for all error paths. ### 6. resetAllTraffics/resetAllClientTraffics trigger restart on error SetToNeedRestart() was called in else branch that ran even on failure. Restructured to only call after confirming success. ### 7. disableInvalidClients has duplicate unreachable error check Same "User %s not found" string check was nested twice. Removed the inner duplicate. ### 8. DelInbound logs uninitialized tag variable The else branch logged empty tag variable instead of actual inbound id. ### 9. check_cpu_usage.go index-out-of-range panic cpu.Percent() can return empty slice. Added len(percent) > 0 guard. ### 10. Dead code: cron.Remove(entry) on never-added entry var entry cron.EntryID defaults to 0; cron.Remove(0) is a no-op. ### 11. checkEmailExistForInbound duplicates checkEmailsExistForClients Refactored to delegate to existing function instead of reimplementing.
2026-03-28 06:12:49 +00:00
if err == nil && len(percent) > 0 && percent[0] > float64(threshold) {
2023-05-20 23:00:26 +00:00
msg := j.tgbotService.I18nBot("tgbot.messages.cpuThreshold",
"Percent=="+strconv.FormatFloat(percent[0], 'f', 2, 64),
"Threshold=="+strconv.Itoa(threshold))
2023-03-17 16:07:49 +00:00
j.tgbotService.SendMsgToTgbotAdmins(msg)
}
}