feat(agent): agent 0.10.0 新增资源/日志/配置回读端点,前端接入 VPS 资源与公网 Nginx 日志(v1.2.4)

agent 0.10.0:新增 GET /api/v1/metrics(资源采集,复用 internal/sysinfo;CPU 两次采样差值 + 1 秒内复用上次结果)、GET /api/v1/logs/nginx(日志尾部,路径白名单来自 nginx -T / 环境变量 / 默认目录,32KB 块倒读、单行 4KB 截断、上限 2000 行)、GET /api/v1/frps/config(frps.toml 回读,256KB 上限)

internal/sysinfo:补 LoadAvg 与 UptimeSeconds(Linux /proc/loadavg 与 /proc/uptime、Windows GetTickCount64、其它平台空值)

应用侧:AgentClient 三个只读方法;request 错误改为带状态码的 statusError,新增 ErrAgentEndpointMissing,把 404/405 统一转成「agent 版本过低需 ≥ 0.10.0」提示;补 service/handler/router

前端:公网 Agent 页「VPS 资源」横排带(占满环境与依赖整行);日志中心「公网 Nginx」页签;frps 同源配置弹窗「比对 VPS 实际文件」

二进制:内嵌 fonu-agent-linux-amd64 / arm64 用新代码重编;VERSION → 1.2.4
This commit is contained in:
2026-09-24 10:15:11 +08:00
parent f75e672a45
commit 2f59f5adc4
19 changed files with 953 additions and 7 deletions
+40
View File
@@ -4,6 +4,8 @@ package sysinfo
import (
"os"
"strconv"
"strings"
"syscall"
)
@@ -22,6 +24,44 @@ func readPlatform() (Stats, CPUSample) {
return stats, sample
}
// LoadAvg 返回 1 / 5 / 15 分钟平均负载;读取失败返回 nil
func LoadAvg() []float64 {
raw, err := os.ReadFile("/proc/loadavg")
if err != nil {
return nil
}
fields := strings.Fields(string(raw))
if len(fields) < 3 {
return nil
}
values := make([]float64, 0, 3)
for _, field := range fields[:3] {
value, err := strconv.ParseFloat(field, 64)
if err != nil {
return nil
}
values = append(values, value)
}
return values
}
// UptimeSeconds 返回系统运行秒数(/proc/uptime)
func UptimeSeconds() uint64 {
raw, err := os.ReadFile("/proc/uptime")
if err != nil {
return 0
}
fields := strings.Fields(string(raw))
if len(fields) == 0 {
return 0
}
seconds, err := strconv.ParseFloat(fields[0], 64)
if err != nil || seconds < 0 {
return 0
}
return uint64(seconds)
}
func diskUsage(path string) (total, used uint64) {
var stat syscall.Statfs_t
if err := syscall.Statfs(path, &stat); err != nil {
+10
View File
@@ -6,3 +6,13 @@ package sysinfo
func readPlatform() (Stats, CPUSample) {
return Stats{}, CPUSample{}
}
// LoadAvg 未适配的平台没有平均负载概念
func LoadAvg() []float64 {
return nil
}
// UptimeSeconds 未适配的平台不采集运行时长
func UptimeSeconds() uint64 {
return 0
}
+12
View File
@@ -13,6 +13,7 @@ var (
procGetSystemTimes = kernel32.NewProc("GetSystemTimes")
procGlobalMemoryStatusEx = kernel32.NewProc("GlobalMemoryStatusEx")
procGetDiskFreeSpaceExW = kernel32.NewProc("GetDiskFreeSpaceExW")
procGetTickCount64 = kernel32.NewProc("GetTickCount64")
)
type memoryStatusEx struct {
@@ -87,6 +88,17 @@ func diskUsage(root string) (total, used uint64) {
return totalBytes, totalBytes - totalFree
}
// LoadAvg Windows 没有平均负载概念,固定返回 nil
func LoadAvg() []float64 {
return nil
}
// UptimeSeconds 用 GetTickCount64 取系统运行秒数
func UptimeSeconds() uint64 {
ret, _, _ := procGetTickCount64.Call()
return uint64(ret) / 1000
}
// filetimeTicks 把 FILETIME(100ns 单位)折算为 10ms 刻度,避免累加时溢出
func filetimeTicks(ft syscall.Filetime) uint64 {
return (uint64(ft.HighDateTime)<<32 | uint64(ft.LowDateTime)) / 10000