更新若干功能
This commit is contained in:
127
host_metrics.go
Normal file
127
host_metrics.go
Normal file
@@ -0,0 +1,127 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/shirou/gopsutil/v4/cpu"
|
||||
"github.com/shirou/gopsutil/v4/mem"
|
||||
gnet "github.com/shirou/gopsutil/v4/net"
|
||||
"view/platform"
|
||||
)
|
||||
|
||||
// HostMetrics 本机总览快照(端口监控页轮询)。
|
||||
type HostMetrics struct {
|
||||
At string `json:"at"`
|
||||
CPUPercent float64 `json:"cpu"`
|
||||
MemUsedMB float64 `json:"memUsedMB"`
|
||||
MemTotalMB float64 `json:"memTotalMB"`
|
||||
MemPercent float64 `json:"memPercent"`
|
||||
GPUPercent float64 `json:"gpu"` // -1 表示不可用
|
||||
GPUMemUsedMB float64 `json:"gpuMemUsedMB"`
|
||||
GPUMemTotalMB float64 `json:"gpuMemTotalMB"`
|
||||
GPUName string `json:"gpuName"`
|
||||
NetRecvKBs float64 `json:"netRecvKBs"`
|
||||
NetSentKBs float64 `json:"netSentKBs"`
|
||||
}
|
||||
|
||||
var (
|
||||
hostNetMu sync.Mutex
|
||||
hostNetAt time.Time
|
||||
hostNetRecv uint64
|
||||
hostNetSent uint64
|
||||
hostNetInit bool
|
||||
)
|
||||
|
||||
// GetHostMetrics 采集 CPU / 内存 / 网卡吞吐;GPU 在有 nvidia-smi 时附带利用率。
|
||||
func (a *App) GetHostMetrics() (HostMetrics, error) {
|
||||
out := HostMetrics{At: time.Now().Format(time.RFC3339), GPUPercent: -1}
|
||||
|
||||
if percents, err := cpu.Percent(0, false); err == nil && len(percents) > 0 {
|
||||
out.CPUPercent = percents[0]
|
||||
if out.CPUPercent < 0 {
|
||||
out.CPUPercent = 0
|
||||
}
|
||||
}
|
||||
|
||||
if vm, err := mem.VirtualMemory(); err == nil && vm != nil {
|
||||
out.MemUsedMB = float64(vm.Used) / 1024 / 1024
|
||||
out.MemTotalMB = float64(vm.Total) / 1024 / 1024
|
||||
out.MemPercent = vm.UsedPercent
|
||||
}
|
||||
|
||||
recvKB, sentKB := sampleHostNet()
|
||||
out.NetRecvKBs = recvKB
|
||||
out.NetSentKBs = sentKB
|
||||
|
||||
fillGPU(&out)
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func sampleHostNet() (recvKBs, sentKBs float64) {
|
||||
counters, err := gnet.IOCounters(false)
|
||||
if err != nil || len(counters) == 0 {
|
||||
return 0, 0
|
||||
}
|
||||
c := counters[0]
|
||||
now := time.Now()
|
||||
|
||||
hostNetMu.Lock()
|
||||
defer hostNetMu.Unlock()
|
||||
if !hostNetInit {
|
||||
hostNetInit = true
|
||||
hostNetAt = now
|
||||
hostNetRecv = c.BytesRecv
|
||||
hostNetSent = c.BytesSent
|
||||
return 0, 0
|
||||
}
|
||||
wall := now.Sub(hostNetAt).Seconds()
|
||||
if wall <= 0 {
|
||||
return 0, 0
|
||||
}
|
||||
recvKBs = float64(c.BytesRecv-hostNetRecv) / 1024 / wall
|
||||
sentKBs = float64(c.BytesSent-hostNetSent) / 1024 / wall
|
||||
if recvKBs < 0 {
|
||||
recvKBs = 0
|
||||
}
|
||||
if sentKBs < 0 {
|
||||
sentKBs = 0
|
||||
}
|
||||
hostNetAt = now
|
||||
hostNetRecv = c.BytesRecv
|
||||
hostNetSent = c.BytesSent
|
||||
return recvKBs, sentKBs
|
||||
}
|
||||
|
||||
// fillGPU 优先 nvidia-smi;失败则保持 gpu=-1。无窗口执行,避免端口监控轮询闪 cmd。
|
||||
func fillGPU(out *HostMetrics) {
|
||||
cmd := exec.Command("nvidia-smi",
|
||||
"--query-gpu=name,utilization.gpu,memory.used,memory.total",
|
||||
"--format=csv,noheader,nounits")
|
||||
platform.ConfigureHidden(cmd)
|
||||
raw, err := cmd.Output()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
line := strings.TrimSpace(strings.Split(string(raw), "\n")[0])
|
||||
if line == "" {
|
||||
return
|
||||
}
|
||||
parts := strings.Split(line, ",")
|
||||
if len(parts) < 4 {
|
||||
return
|
||||
}
|
||||
out.GPUName = strings.TrimSpace(parts[0])
|
||||
if v, e := strconv.ParseFloat(strings.TrimSpace(parts[1]), 64); e == nil {
|
||||
out.GPUPercent = v
|
||||
}
|
||||
if v, e := strconv.ParseFloat(strings.TrimSpace(parts[2]), 64); e == nil {
|
||||
out.GPUMemUsedMB = v
|
||||
}
|
||||
if v, e := strconv.ParseFloat(strings.TrimSpace(parts[3]), 64); e == nil {
|
||||
out.GPUMemTotalMB = v
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user