nezha/cmd/agent/monitor/monitor.go

164 lines
4.4 KiB
Go
Raw Normal View History

2019-12-07 05:14:40 -05:00
package monitor
import (
"fmt"
2021-04-26 07:13:02 -04:00
"regexp"
2021-08-07 22:06:44 -04:00
"runtime"
2019-12-09 03:02:49 -05:00
"strings"
2019-12-13 01:51:51 -05:00
"sync/atomic"
2019-12-07 05:14:40 -05:00
"time"
"github.com/shirou/gopsutil/v3/cpu"
"github.com/shirou/gopsutil/v3/disk"
"github.com/shirou/gopsutil/v3/host"
"github.com/shirou/gopsutil/v3/mem"
"github.com/shirou/gopsutil/v3/net"
2019-12-07 05:14:40 -05:00
2020-11-10 21:07:45 -05:00
"github.com/naiba/nezha/model"
2019-12-07 05:14:40 -05:00
)
2021-07-08 12:01:58 -04:00
var Version string = "debug"
2019-12-09 10:45:23 -05:00
var netInSpeed, netOutSpeed, netInTransfer, netOutTransfer, lastUpdate uint64
2021-04-26 07:13:02 -04:00
var expectDiskFsTypes = []string{
2021-05-03 22:22:38 -04:00
"apfs", "ext4", "ext3", "ext2", "f2fs", "reiserfs", "jfs", "btrfs", "fuseblk", "zfs", "simfs", "ntfs", "fat32", "exfat", "xfs",
2021-04-26 07:13:02 -04:00
}
var excludeNetInterfaces = []string{
"lo", "tun", "docker", "veth", "br-", "vmbr", "vnet", "kube",
}
var getMacDiskNo = regexp.MustCompile(`\/dev\/disk(\d)s.*`)
2021-03-19 22:05:16 -04:00
2019-12-07 05:14:40 -05:00
func GetHost() *model.Host {
hi, _ := host.Info()
2021-02-27 06:24:19 -05:00
var cpuType string
if hi.VirtualizationSystem != "" {
cpuType = "Vrtual"
2021-02-27 06:24:19 -05:00
} else {
cpuType = "Physical"
}
cpuModelCount := make(map[string]int)
2019-12-07 05:14:40 -05:00
ci, _ := cpu.Info()
for i := 0; i < len(ci); i++ {
2021-02-27 06:24:19 -05:00
cpuModelCount[ci[i].ModelName]++
}
var cpus []string
for model, count := range cpuModelCount {
cpus = append(cpus, fmt.Sprintf("%s %d %s Core", model, count, cpuType))
2019-12-07 05:14:40 -05:00
}
2019-12-11 08:50:49 -05:00
mv, _ := mem.VirtualMemory()
diskTotal, _ := getDiskTotalAndUsed()
2021-03-19 22:05:16 -04:00
2021-08-07 22:06:44 -04:00
var swapMemTotal uint64
if runtime.GOOS == "windows" {
ms, _ := mem.SwapMemory()
swapMemTotal = ms.Total
} else {
swapMemTotal = mv.SwapTotal
}
2019-12-07 05:14:40 -05:00
return &model.Host{
Platform: hi.OS,
PlatformVersion: hi.PlatformVersion,
CPU: cpus,
2019-12-11 08:50:49 -05:00
MemTotal: mv.Total,
2021-08-07 22:06:44 -04:00
SwapTotal: swapMemTotal,
DiskTotal: diskTotal,
2019-12-07 05:14:40 -05:00
Arch: hi.KernelArch,
Virtualization: hi.VirtualizationSystem,
2019-12-09 10:45:23 -05:00
BootTime: hi.BootTime,
2021-03-19 22:05:16 -04:00
IP: cachedIP,
2021-03-20 11:50:16 -04:00
CountryCode: strings.ToLower(cachedCountry),
2021-07-08 12:01:58 -04:00
Version: Version,
2019-12-07 05:14:40 -05:00
}
}
func GetState() *model.HostState {
2019-12-09 10:45:23 -05:00
hi, _ := host.Info()
2019-12-07 05:14:40 -05:00
mv, _ := mem.VirtualMemory()
2021-08-07 22:06:44 -04:00
var swapMemUsed uint64
if runtime.GOOS == "windows" {
ms, _ := mem.SwapMemory()
swapMemUsed = ms.Used
} else {
swapMemUsed = mv.SwapTotal - mv.SwapFree
}
2019-12-09 10:45:23 -05:00
var cpuPercent float64
cp, err := cpu.Percent(0, false)
2019-12-09 10:45:23 -05:00
if err == nil {
cpuPercent = cp[0]
}
_, diskUsed := getDiskTotalAndUsed()
return &model.HostState{
2019-12-09 10:45:23 -05:00
CPU: cpuPercent,
MemUsed: mv.Total - mv.Available,
2021-08-07 22:06:44 -04:00
SwapUsed: swapMemUsed,
DiskUsed: diskUsed,
2019-12-13 01:51:51 -05:00
NetInTransfer: atomic.LoadUint64(&netInTransfer),
NetOutTransfer: atomic.LoadUint64(&netOutTransfer),
NetInSpeed: atomic.LoadUint64(&netInSpeed),
NetOutSpeed: atomic.LoadUint64(&netOutSpeed),
2019-12-09 10:45:23 -05:00
Uptime: hi.Uptime,
2019-12-07 05:14:40 -05:00
}
2019-12-09 10:45:23 -05:00
}
func TrackNetworkSpeed() {
var innerNetInTransfer, innerNetOutTransfer uint64
nc, err := net.IOCounters(true)
2019-12-07 05:14:40 -05:00
if err == nil {
for _, v := range nc {
2021-04-26 07:13:02 -04:00
if isListContainsStr(excludeNetInterfaces, v.Name) {
continue
}
innerNetInTransfer += v.BytesRecv
innerNetOutTransfer += v.BytesSent
}
2019-12-13 01:51:51 -05:00
now := uint64(time.Now().Unix())
diff := now - atomic.LoadUint64(&lastUpdate)
2019-12-09 10:45:23 -05:00
if diff > 0 {
2019-12-13 01:51:51 -05:00
atomic.StoreUint64(&netInSpeed, (innerNetInTransfer-atomic.LoadUint64(&netInTransfer))/diff)
atomic.StoreUint64(&netOutSpeed, (innerNetOutTransfer-atomic.LoadUint64(&netOutTransfer))/diff)
2019-12-09 10:45:23 -05:00
}
2019-12-13 01:51:51 -05:00
atomic.StoreUint64(&netInTransfer, innerNetInTransfer)
atomic.StoreUint64(&netOutTransfer, innerNetOutTransfer)
atomic.StoreUint64(&lastUpdate, now)
2019-12-07 05:14:40 -05:00
}
}
func getDiskTotalAndUsed() (total uint64, used uint64) {
diskList, _ := disk.Partitions(false)
2021-04-26 07:13:02 -04:00
devices := make(map[string]string)
countedDiskForMac := make(map[string]struct{})
for _, d := range diskList {
fsType := strings.ToLower(d.Fstype)
2021-04-26 07:13:02 -04:00
// 不统计 K8s 的虚拟挂载点https://github.com/shirou/gopsutil/issues/1007
if devices[d.Device] == "" && isListContainsStr(expectDiskFsTypes, fsType) && !strings.Contains(d.Mountpoint, "/var/lib/kubelet") {
devices[d.Device] = d.Mountpoint
}
}
for device, mountPath := range devices {
diskUsageOf, _ := disk.Usage(mountPath)
// 这里是针对 Mac 机器的处理https://github.com/giampaolo/psutil/issues/1509
matches := getMacDiskNo.FindStringSubmatch(device)
if len(matches) == 2 {
if _, has := countedDiskForMac[matches[1]]; !has {
countedDiskForMac[matches[1]] = struct{}{}
total += diskUsageOf.Total
}
2021-04-26 07:13:02 -04:00
} else {
total += diskUsageOf.Total
}
2021-04-26 07:13:02 -04:00
used += diskUsageOf.Used
}
return
}
2021-04-26 07:13:02 -04:00
func isListContainsStr(list []string, str string) bool {
for i := 0; i < len(list); i++ {
2021-07-16 02:49:15 -04:00
if strings.Contains(str, list[i]) {
2021-04-26 07:13:02 -04:00
return true
}
}
return false
}