feat:show system cpu memory disk percent

#418
This commit is contained in:
samwaf
2025-07-25 15:25:21 +08:00
parent 7bbde22488
commit 02f5fdf626
9 changed files with 256 additions and 3 deletions
+3
View File
@@ -43,6 +43,7 @@ type APIGroup struct {
WafTunnelApi
WafVpConfigApi
WafFileApi
WafSystemMonitorApi
}
var APIGroupAPP = new(APIGroup)
@@ -99,4 +100,6 @@ var (
wafPrivateGroupService = waf_service.WafPrivateGroupServiceApp
wafCacheRuleService = waf_service.WafCacheRuleServiceApp
wafTunnelService = waf_service.WafTunnelServiceApp
wafMonitorService = waf_service.WafSystemMonitorServiceApp
)
+22
View File
@@ -0,0 +1,22 @@
package api
import (
"SamWaf/model/common/response"
"SamWaf/service/waf_service"
"github.com/gin-gonic/gin"
)
type WafSystemMonitorApi struct {
}
var wafSystemMonitorService = waf_service.WafSystemMonitorServiceApp
// GetSystemMonitorApi 获取系统监控信息
func (w *WafSystemMonitorApi) GetSystemMonitorApi(c *gin.Context) {
systemInfo, err := wafSystemMonitorService.GetSystemMonitorInfo()
if err != nil {
response.FailWithMessage("获取系统监控信息失败: "+err.Error(), c)
return
}
response.OkWithDetailed(systemInfo, "获取成功", c)
}
+5 -1
View File
@@ -26,6 +26,7 @@ require (
github.com/samwafgo/go-wxsqlite3 v1.0.1
github.com/samwafgo/sqlitedriver v1.0.2
github.com/shirou/gopsutil v3.21.11+incompatible
github.com/shirou/gopsutil/v3 v3.24.5
github.com/spf13/viper v1.18.2
github.com/stretchr/testify v1.10.0
github.com/twmb/franz-go v1.18.0
@@ -86,6 +87,7 @@ require (
github.com/klauspost/compress v1.17.8 // indirect
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/magefile/mage v1.15.1-0.20231118170541-2385abb49a1f // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
@@ -101,12 +103,14 @@ require (
github.com/pierrec/lz4/v4 v4.1.21 // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/richardlehane/mscfb v1.0.4 // indirect
github.com/richardlehane/msoleps v1.0.4 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sergi/go-diff v1.1.0 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/skeema/knownhosts v1.2.1 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
@@ -129,7 +133,7 @@ require (
github.com/xanzy/ssh-agent v0.3.3 // indirect
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d // indirect
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.mongodb.org/mongo-driver v1.13.1 // indirect
go.uber.org/multierr v1.10.0 // indirect
golang.org/x/arch v0.12.0 // indirect
+14 -2
View File
@@ -144,6 +144,7 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
@@ -198,6 +199,8 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20220907060842-b2ba5d58e48d h1:E7Qr3vakQIk9KTpn6m4yhsEhOdo4g51EqE4cSMy2LCw=
github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20220907060842-b2ba5d58e48d/go.mod h1:bChUKvbKVC3zL/lLLIcu6alhQaL8uWD/DA+jRdyggdI=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/magefile/mage v1.15.1-0.20231118170541-2385abb49a1f h1:iiLWLoibjCL0XND6inF7bs2nc20lU/FYkiR//VIOLUc=
github.com/magefile/mage v1.15.1-0.20231118170541-2385abb49a1f/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
@@ -238,6 +241,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg=
github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@@ -266,6 +271,12 @@ github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
@@ -347,8 +358,8 @@ github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZ
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk=
go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
@@ -426,6 +437,7 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+37
View File
@@ -0,0 +1,37 @@
package response
// 系统监控响应结构体
type WafSystemMonitor struct {
CPU WafCPUInfo `json:"cpu"` // CPU信息
Memory WafMemoryInfo `json:"memory"` // 内存信息
Disk []WafDiskInfo `json:"disk"` // 磁盘信息
}
// CPU信息
type WafCPUInfo struct {
ModelName string `json:"model_name"` // CPU型号
Cores int32 `json:"cores"` // 核心数
UsagePercent float64 `json:"usage_percent"` // 使用率百分比
PhysicalCnt int `json:"physical_cnt"` // 物理核心数
LogicalCnt int `json:"logical_cnt"` // 逻辑核心数
}
// 内存信息
type WafMemoryInfo struct {
Total string `json:"total"` // 总内存
Available string `json:"available"` // 可用内存
Used string `json:"used"` // 已用内存
UsagePercent float64 `json:"usage_percent"` // 使用率百分比
JVMUsed string `json:"jvm_used"` // JVM使用内存(这里用Go程序内存)
JVMPercent float64 `json:"jvm_percent"` // JVM使用率
}
// 磁盘信息
type WafDiskInfo struct {
FileSystem string `json:"file_system"` // 文件系统
MountPoint string `json:"mount_point"` // 挂载点
Total string `json:"total"` // 总容量
Available string `json:"available"` // 可用容量
Used string `json:"used"` // 已用容量
UsagePercent float64 `json:"usage_percent"` // 使用率百分比
}
+1
View File
@@ -41,6 +41,7 @@ type ApiGroup struct {
WafTunnelRouter
WafVpConfigRouter
WafFileRouter
WafSystemMonitorRouter
}
type PublicApiGroup struct {
LoginRouter
+16
View File
@@ -0,0 +1,16 @@
package router
import (
"SamWaf/api"
"github.com/gin-gonic/gin"
)
type WafSystemMonitorRouter struct {
}
func (s *WafSystemMonitorRouter) InitWafSystemMonitorRouter(group *gin.RouterGroup) {
wafSystemMonitorApi := api.APIGroupAPP.WafSystemMonitorApi
router := group.Group("")
router.GET("/samwaf/monitor/system_info", wafSystemMonitorApi.GetSystemMonitorApi) // 获取系统监控信息
}
+157
View File
@@ -0,0 +1,157 @@
package waf_service
import (
"SamWaf/model/response"
"fmt"
"math"
"runtime"
"time"
"github.com/shirou/gopsutil/v3/cpu"
"github.com/shirou/gopsutil/v3/disk"
"github.com/shirou/gopsutil/v3/mem"
)
type WafSystemMonitorService struct {
}
var WafSystemMonitorServiceApp = &WafSystemMonitorService{}
// GetSystemMonitorInfo 获取系统监控信息
func (receiver *WafSystemMonitorService) GetSystemMonitorInfo() (response.WafSystemMonitor, error) {
var result response.WafSystemMonitor
// 获取CPU信息
cpuInfo, err := receiver.getCPUInfo()
if err != nil {
return result, fmt.Errorf("获取CPU信息失败: %v", err)
}
result.CPU = cpuInfo
// 获取内存信息
memInfo, err := receiver.getMemoryInfo()
if err != nil {
return result, fmt.Errorf("获取内存信息失败: %v", err)
}
result.Memory = memInfo
// 获取磁盘信息
diskInfo, err := receiver.getDiskInfo()
if err != nil {
return result, fmt.Errorf("获取磁盘信息失败: %v", err)
}
result.Disk = diskInfo
return result, nil
}
// getCPUInfo 获取CPU信息
func (receiver *WafSystemMonitorService) getCPUInfo() (response.WafCPUInfo, error) {
var cpuInfo response.WafCPUInfo
// 获取CPU基本信息
cpuInfos, err := cpu.Info()
if err != nil {
return cpuInfo, err
}
if len(cpuInfos) > 0 {
cpuInfo.ModelName = cpuInfos[0].ModelName
cpuInfo.Cores = cpuInfos[0].Cores
}
// 获取CPU使用率
cpuPercent, err := cpu.Percent(time.Second, false)
if err != nil {
return cpuInfo, err
}
if len(cpuPercent) > 0 {
cpuInfo.UsagePercent = receiver.roundToTwoDecimal(cpuPercent[0])
}
// 获取CPU核心数
physicalCnt, _ := cpu.Counts(false)
logicalCnt, _ := cpu.Counts(true)
cpuInfo.PhysicalCnt = physicalCnt
cpuInfo.LogicalCnt = logicalCnt
return cpuInfo, nil
}
// getMemoryInfo 获取内存信息
func (receiver *WafSystemMonitorService) getMemoryInfo() (response.WafMemoryInfo, error) {
var memInfo response.WafMemoryInfo
// 获取系统内存信息
vmStat, err := mem.VirtualMemory()
if err != nil {
return memInfo, err
}
memInfo.Total = receiver.formatBytes(vmStat.Total)
memInfo.Available = receiver.formatBytes(vmStat.Available)
memInfo.Used = receiver.formatBytes(vmStat.Used)
memInfo.UsagePercent = receiver.roundToTwoDecimal(vmStat.UsedPercent)
// 获取Go程序内存使用情况
var m runtime.MemStats
runtime.ReadMemStats(&m)
memInfo.JVMUsed = receiver.formatBytes(m.Alloc)
if vmStat.Total > 0 {
jvmPercent := float64(m.Alloc) / float64(vmStat.Total) * 100
memInfo.JVMPercent = receiver.roundToTwoDecimal(jvmPercent)
}
return memInfo, nil
}
// getDiskInfo 获取磁盘信息
func (receiver *WafSystemMonitorService) getDiskInfo() ([]response.WafDiskInfo, error) {
var diskInfos []response.WafDiskInfo
// 获取磁盘分区信息
partitions, err := disk.Partitions(false)
if err != nil {
return diskInfos, err
}
for _, partition := range partitions {
// 获取磁盘使用情况
usage, err := disk.Usage(partition.Mountpoint)
if err != nil {
continue // 跳过无法访问的分区
}
diskInfo := response.WafDiskInfo{
FileSystem: partition.Device,
MountPoint: partition.Mountpoint,
Total: receiver.formatBytes(usage.Total),
Available: receiver.formatBytes(usage.Free),
Used: receiver.formatBytes(usage.Used),
UsagePercent: receiver.roundToTwoDecimal(usage.UsedPercent),
}
diskInfos = append(diskInfos, diskInfo)
}
return diskInfos, nil
}
// roundToTwoDecimal 将浮点数四舍五入到两位小数
func (receiver *WafSystemMonitorService) roundToTwoDecimal(value float64) float64 {
return math.Round(value*100) / 100
}
// formatBytes 格式化字节数为可读格式
func (receiver *WafSystemMonitorService) formatBytes(bytes uint64) string {
const unit = 1024
if bytes < unit {
return fmt.Sprintf("%d B", bytes)
}
div, exp := int64(unit), 0
for n := bytes / unit; n >= unit; n /= unit {
div *= unit
exp++
}
return fmt.Sprintf("%.1f %cB", float64(bytes)/float64(div), "KMGTPE"[exp])
}
+1
View File
@@ -75,6 +75,7 @@ func (web *WafWebManager) initRouter(r *gin.Engine) {
router.ApiGroupApp.InitWafTunnelRouter(RouterGroup)
router.ApiGroupApp.InitWafVpConfigRouter(RouterGroup)
router.ApiGroupApp.InitWafFileRouter(RouterGroup)
router.ApiGroupApp.InitWafSystemMonitorRouter(RouterGroup)
}
if global.GWAF_RELEASE == "true" {