e6956aa001
- React frontend with route-level code splitting - Backend rebranded from Baihu to TaskPool - DB brand migration script and local compatibility
133 lines
3.3 KiB
Go
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()
|
|
}
|