nezha/cmd/agent/monitor/monitor.go
2021-03-20 23:50:16 +08:00

145 lines
3.6 KiB
Go

package monitor
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"sync/atomic"
"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"
"github.com/naiba/nezha/model"
"github.com/naiba/nezha/service/dao"
)
type ipDotSbGeoIP struct {
CountryCode string `json:"country_code,omitempty"`
IP string `json:"ip,omitempty"`
}
var netInSpeed, netOutSpeed, netInTransfer, netOutTransfer, lastUpdate uint64
var cachedIP, cachedCountry string
func UpdateIP() {
var ip ipDotSbGeoIP
for {
var tempIP string
var tempCountry string
resp, err := http.Get("https://api-ipv4.ip.sb/geoip")
if err == nil {
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
json.Unmarshal(body, &ip)
tempIP = ip.IP
tempCountry = ip.CountryCode
} else {
cachedIP = ""
}
time.Sleep(time.Second * 10)
resp, err = http.Get("https://api-ipv6.ip.sb/geoip")
if err == nil {
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
json.Unmarshal(body, &ip)
if tempIP == "" {
tempIP = ip.IP
} else {
tempIP = fmt.Sprintf("ip(v4: %s, v6: %s)", tempIP, ip.IP)
}
tempCountry = ip.CountryCode
}
cachedIP = tempIP
cachedCountry = tempCountry
time.Sleep(time.Minute * 10)
}
}
func GetHost() *model.Host {
hi, _ := host.Info()
var cpuType string
if hi.VirtualizationSystem != "" {
cpuType = "Virtual"
} else {
cpuType = "Physical"
}
cpuModelCount := make(map[string]int)
ci, _ := cpu.Info()
for i := 0; i < len(ci); i++ {
cpuModelCount[ci[i].ModelName]++
}
var cpus []string
for model, count := range cpuModelCount {
cpus = append(cpus, fmt.Sprintf("%s %d %s Core", model, count, cpuType))
}
mv, _ := mem.VirtualMemory()
ms, _ := mem.SwapMemory()
u, _ := disk.Usage("/")
return &model.Host{
Platform: hi.OS,
PlatformVersion: hi.PlatformVersion,
CPU: cpus,
MemTotal: mv.Total,
DiskTotal: u.Total,
SwapTotal: ms.Total,
Arch: hi.KernelArch,
Virtualization: hi.VirtualizationSystem,
BootTime: hi.BootTime,
IP: cachedIP,
CountryCode: strings.ToLower(cachedCountry),
Version: dao.Version,
}
}
func GetState(delay int64) *model.HostState {
hi, _ := host.Info()
// Memory
mv, _ := mem.VirtualMemory()
ms, _ := mem.SwapMemory()
// CPU
var cpuPercent float64
cp, err := cpu.Percent(time.Second*time.Duration(delay), false)
if err == nil {
cpuPercent = cp[0]
}
// Disk
u, _ := disk.Usage("/")
return &model.HostState{
CPU: cpuPercent,
MemUsed: mv.Used,
SwapUsed: ms.Used,
DiskUsed: u.Used,
NetInTransfer: atomic.LoadUint64(&netInTransfer),
NetOutTransfer: atomic.LoadUint64(&netOutTransfer),
NetInSpeed: atomic.LoadUint64(&netInSpeed),
NetOutSpeed: atomic.LoadUint64(&netOutSpeed),
Uptime: hi.Uptime,
}
}
func TrackNetworkSpeed() {
var innerNetInTransfer, innerNetOutTransfer uint64
nc, err := net.IOCounters(false)
if err == nil {
innerNetInTransfer += nc[0].BytesRecv
innerNetOutTransfer += nc[0].BytesSent
now := uint64(time.Now().Unix())
diff := now - atomic.LoadUint64(&lastUpdate)
if diff > 0 {
atomic.StoreUint64(&netInSpeed, (innerNetInTransfer-atomic.LoadUint64(&netInTransfer))/diff)
atomic.StoreUint64(&netOutSpeed, (innerNetOutTransfer-atomic.LoadUint64(&netOutTransfer))/diff)
}
atomic.StoreUint64(&netInTransfer, innerNetInTransfer)
atomic.StoreUint64(&netOutTransfer, innerNetOutTransfer)
atomic.StoreUint64(&lastUpdate, now)
}
}