feat(monitor): 自 go-hua 迁入系统资源监控

- Start 后台每秒采集(CPU/内存/磁盘/网络/进程/连接/主机), GetInfo 取快照
- 基于 gopsutil, 附测试、examples/monitor 例程与包 README
This commit is contained in:
2026-09-20 12:29:37 +08:00
parent 138c929bd4
commit 30a0889ffa
11 changed files with 963 additions and 0 deletions
+217
View File
@@ -0,0 +1,217 @@
package monitor
import (
"sort"
"github.com/shirou/gopsutil/v3/net"
)
// NetInfo 网卡信息(gopsutil net.InterfaceStat)
type NetInfo struct {
Name string `json:"name"` // interface name
BytesSent uint64 `json:"bytesSent"` // number of bytes sent
BytesRecv uint64 `json:"bytesRecv"` // number of bytes received
PacketsSent uint64 `json:"packetsSent"` // number of packets sent
PacketsRecv uint64 `json:"packetsRecv"` // number of packets received
TotalBytesSent uint64 `json:"totalBytesSent"` // number of bytes sent
TotalBytesRecv uint64 `json:"totalBytesRecv"` // number of bytes received
TotalPacketsSent uint64 `json:"totalPacketsSent"` // number of packets sent
TotalPacketsRecv uint64 `json:"totalPacketsRecv"` // number of packets received
}
// NetInfoLite 精简版网卡信息
type NetInfoLite struct {
BytesSent uint64 `json:"bytesSent"` // number of bytes sent
BytesRecv uint64 `json:"bytesRecv"` // number of bytes received
PacketsSent uint64 `json:"packetsSent"` // number of packets sent
PacketsRecv uint64 `json:"packetsRecv"` // number of packets received
TotalBytesSent uint64 `json:"totalBytesSent"` // number of bytes sent
TotalBytesRecv uint64 `json:"totalBytesRecv"` // number of bytes received
}
// Addr 网卡地址
type Addr struct {
Ip string `json:"ip"`
Port uint32 `json:"port"`
}
// ConnInfo 连接汇总:TCP/UDP 计数、监听端口列表与每进程连接计数
type ConnInfo struct {
Fd uint32 `json:"fd"`
Family uint32 `json:"family"`
Type uint32 `json:"type"`
LocalAddr Addr `json:"localAddr"`
RemoteAddr Addr `json:"remoteAddr"`
Status string `json:"status"`
Pid int32 `json:"pid"`
}
// NetListen 监听端口详情
type NetListen struct {
Addr string `json:"addr"`
Port uint32 `json:"port"`
Conn int `json:"conn"`
ConnInfo
}
// ProcConn 每进程连接计数
type ProcConn struct {
Pid int `json:"pid"`
Name string `json:"name"`
Conn int `json:"conn"`
}
// NetConnInfo 单条网络连接信息(gopsutil net.ConnectionStat)
type NetConnInfo struct {
Tcp int `json:"tcp"`
Udp int `json:"udp"`
Listen []NetListen `json:"listen"`
}
// getNetInfo 采集网卡列表
func getNetInfo() ([]NetInfo, error) {
netIo, err := net.IOCounters(true)
if err != nil {
return nil, err
}
nets := make([]NetInfo, len(netIo))
for i, v := range netIo {
nets[i].Name = netIo[i].Name
nets[i].TotalBytesSent = v.BytesSent
nets[i].TotalBytesRecv = v.BytesRecv
nets[i].TotalPacketsSent = v.PacketsSent
nets[i].TotalPacketsRecv = v.PacketsRecv
// 应该使用网卡名 未处理
if len(monInfo.Net) > i {
nets[i].BytesSent = v.BytesSent - monInfo.Net[i].TotalBytesSent
nets[i].BytesRecv = v.BytesRecv - monInfo.Net[i].TotalBytesRecv
nets[i].PacketsSent = v.PacketsSent - monInfo.Net[i].TotalPacketsSent
nets[i].PacketsRecv = v.PacketsRecv - monInfo.Net[i].TotalPacketsRecv
}
}
return nets, err
}
// getNetConnInfo 采集 TCP/UDP 连接计数与监听端口汇总
func getNetConnInfo() (NetConnInfo, error) {
// linux TcpStatus
/* {
"01": "ESTABLISHED",
"02": "SYN_SENT",
"03": "SYN_RECV",
"04": "FIN_WAIT1",
"05": "FIN_WAIT2",
"06": "TIME_WAIT",
"07": "CLOSE",
"08": "CLOSE_WAIT",
"09": "LAST_ACK",
"0A": "LISTEN",
"0B": "CLOSING",
} */
// windows TcpStatus
/* {
1: "CLOSED",
2: "LISTEN",
3: "SYN_SENT",
4: "SYN_RECEIVED",
5: "ESTABLISHED",
6: "FIN_WAIT_1",
7: "FIN_WAIT_2",
8: "CLOSE_WAIT",
9: "CLOSING",
10: "LAST_ACK",
11: "TIME_WAIT",
12: "DELETE",
} */
/* {
"all": {kindTCP4, kindTCP6, kindUDP4, kindUDP6},
"tcp": {kindTCP4, kindTCP6},
"tcp4": {kindTCP4},
"tcp6": {kindTCP6},
"udp": {kindUDP4, kindUDP6},
"udp4": {kindUDP4},
"udp6": {kindUDP6},
"inet": {kindTCP4, kindTCP6, kindUDP4, kindUDP6},
"inet4": {kindTCP4, kindUDP4},
"inet6": {kindTCP6, kindUDP6},
} */
info := NetConnInfo{}
tcp, err := net.Connections("tcp")
if err != nil {
return info, nil
}
udp, err := net.Connections("udp")
if err != nil {
return info, nil
}
//logger.Infof("net conn tcp:%d udp:%d", info.Tcp, info.Udp)
// 监听列表
listen := make([]NetListen, 0)
for _, v := range tcp {
if v.Status == "LISTEN" {
inPort := false
for _, l := range listen {
if l.Port == v.Laddr.Port {
inPort = true
break
}
}
if !inPort {
listen = append(listen, NetListen{
Addr: v.Laddr.IP,
Port: v.Laddr.Port,
Conn: 0,
ConnInfo: ConnInfo{
Fd: v.Fd,
Family: v.Family,
Type: v.Type,
LocalAddr: Addr{
Ip: v.Laddr.IP,
Port: v.Laddr.Port,
},
RemoteAddr: Addr{
Ip: v.Raddr.IP,
Port: v.Raddr.Port,
},
Status: v.Status,
Pid: v.Pid,
},
})
}
}
}
// 连接计数
count := 0
for _, v := range tcp {
if v.Status == "ESTABLISHED" {
for index, l := range listen {
if l.Port == v.Laddr.Port {
listen[index].Conn++
break
}
}
count++
}
}
//排序
sort.Slice(listen, func(i, j int) bool {
return listen[i].Conn > listen[j].Conn
})
// TCP和UDP连接数
info.Tcp = count //len(tcp)
info.Udp = len(udp)
info.Listen = listen
return info, nil
}