Files
TaskPool/internal/services/monitor_service.go
T
admin e6956aa001 Initial commit: TaskPool React panel
- React frontend with route-level code splitting
- Backend rebranded from Baihu to TaskPool
- DB brand migration script and local compatibility
2026-07-26 08:43:52 +08:00

133 lines
3.3 KiB
Go

package services
import (
"math/rand"
"runtime"
"sync"
"time"
"github.com/engigu/taskpool/internal/constant"
"github.com/shirou/gopsutil/v3/cpu"
"github.com/shirou/gopsutil/v3/disk"
"github.com/shirou/gopsutil/v3/host"
"github.com/shirou/gopsutil/v3/mem"
)
type HostMetrics struct {
CPUPercent float64
VMem *mem.VirtualMemoryStat
DiskUsage *disk.UsageStat
HostInfo *host.InfoStat
}
type MonitorService struct {
hostMu sync.RWMutex
lastUpdate time.Time
metrics HostMetrics
}
var (
monitorServiceInstance *MonitorService
monitorServiceOnce sync.Once
)
// GetMonitorService 获取系统监控服务单例
func GetMonitorService() *MonitorService {
monitorServiceOnce.Do(func() {
monitorServiceInstance = &MonitorService{}
})
return monitorServiceInstance
}
// GetHostMetrics 获取并返回物理机状态(带有缓存和演示模式伪装)
func (ms *MonitorService) GetHostMetrics() HostMetrics {
ms.hostMu.Lock()
defer ms.hostMu.Unlock()
// 缓存 2 秒
if time.Since(ms.lastUpdate) < 2*time.Second && ms.metrics.VMem != nil {
return ms.metrics
}
if constant.DemoMode {
ms.updateDemoMetrics()
return ms.metrics
}
cpuPercents, _ := cpu.Percent(0, false)
if len(cpuPercents) > 0 {
ms.metrics.CPUPercent = cpuPercents[0]
}
ms.metrics.VMem, _ = mem.VirtualMemory()
ms.metrics.DiskUsage, _ = disk.Usage("/")
ms.metrics.HostInfo, _ = host.Info()
ms.lastUpdate = time.Now()
// 提供默认值防空指针
if ms.metrics.VMem == nil {
ms.metrics.VMem = &mem.VirtualMemoryStat{}
}
if ms.metrics.DiskUsage == nil {
ms.metrics.DiskUsage = &disk.UsageStat{}
}
if ms.metrics.HostInfo == nil {
ms.metrics.HostInfo = &host.InfoStat{}
}
return ms.metrics
}
type RuntimeMetrics struct {
NumGoroutine int
MemStats runtime.MemStats
}
var (
runtimeMu sync.RWMutex
lastRuntime time.Time
cachedRuntime RuntimeMetrics
)
// GetRuntimeMetrics 获取 Go 运行时指标(缓存 2 秒,防止高并发下频繁触发 STW)
func (ms *MonitorService) GetRuntimeMetrics() RuntimeMetrics {
runtimeMu.Lock()
defer runtimeMu.Unlock()
if time.Since(lastRuntime) < 2*time.Second && cachedRuntime.NumGoroutine > 0 {
return cachedRuntime
}
cachedRuntime.NumGoroutine = runtime.NumGoroutine()
runtime.ReadMemStats(&cachedRuntime.MemStats)
lastRuntime = time.Now()
return cachedRuntime
}
func (ms *MonitorService) updateDemoMetrics() {
ms.metrics.CPUPercent = 10 + rand.Float64()*40 // 10% - 50% 的随机 CPU 波动
totalMem := uint64(8 * 1024 * 1024 * 1024) // 8GB 内存
usedMem := uint64(float64(totalMem) * (0.3 + rand.Float64()*0.3)) // 30% - 60% 随机使用率
ms.metrics.VMem = &mem.VirtualMemoryStat{
Total: totalMem,
Used: usedMem,
UsedPercent: float64(usedMem) / float64(totalMem) * 100,
}
totalDisk := uint64(500 * 1024 * 1024 * 1024) // 500GB 硬盘
usedDisk := uint64(float64(totalDisk) * 0.45) // 固定 45% 使用率
ms.metrics.DiskUsage = &disk.UsageStat{
Total: totalDisk,
Used: usedDisk,
UsedPercent: float64(usedDisk) / float64(totalDisk) * 100,
}
ms.metrics.HostInfo = &host.InfoStat{
Platform: "Demo Environment",
OS: "linux",
Uptime: uint64(time.Now().Unix() - 1700000000), // 生成一个较长且持续增加的运行时间
}
ms.lastUpdate = time.Now()
}