feat: 新增机器状态查看&机器状态等

This commit is contained in:
meilin.huang
2022-04-27 10:59:02 +08:00
parent 6fe892ca9f
commit ce78b2caee
41 changed files with 1240 additions and 2470 deletions

View File

@@ -3,8 +3,6 @@ package machine
import (
"bufio"
"fmt"
"io"
"sort"
"strconv"
"strings"
"time"
@@ -23,19 +21,6 @@ type NetIntfInfo struct {
Tx uint64
}
type cpuRaw struct {
User uint64 // time spent in user mode
Nice uint64 // time spent in user mode with low priority (nice)
System uint64 // time spent in system mode
Idle uint64 // time spent in the idle task
Iowait uint64 // time spent waiting for I/O to complete (since Linux 2.5.41)
Irq uint64 // time spent servicing interrupts (since 2.6.0-test4)
SoftIrq uint64 // time spent servicing softirqs (since 2.6.0-test4)
Steal uint64 // time spent in other OSes when running in a virtualized environment
Guest uint64 // time spent running a virtual CPU for guest operating systems under the control of the Linux kernel.
Total uint64 // total of all time fields
}
type CPUInfo struct {
User float32
Nice float32
@@ -49,7 +34,7 @@ type CPUInfo struct {
}
type Stats struct {
Uptime time.Duration
Uptime string
Hostname string
Load1 string
Load5 string
@@ -59,6 +44,7 @@ type Stats struct {
MemTotal uint64
MemFree uint64
MemBuffers uint64
MemAvailable uint64
MemCached uint64
SwapTotal uint64
SwapFree uint64
@@ -90,12 +76,32 @@ func getUptime(uptime string, stats *Stats) (err error) {
if err != nil {
return
}
stats.Uptime = time.Duration(upsecs * 1e9)
stats.Uptime = fmtUptime(time.Duration(upsecs * 1e9))
}
return
}
func fmtUptime(dur time.Duration) string {
dur = dur - (dur % time.Second)
var days int
for dur.Hours() > 24.0 {
days++
dur -= 24 * time.Hour
}
s1 := dur.String()
s2 := ""
if days > 0 {
s2 = fmt.Sprintf("%dd ", days)
}
for _, ch := range s1 {
s2 += string(ch)
if ch == 'h' || ch == 'm' {
s2 += " "
}
}
return s2
}
func getHostname(hostname string, stats *Stats) (err error) {
stats.Hostname = strings.TrimSpace(hostname)
return
@@ -143,6 +149,8 @@ func getMemInfo(memInfo string, stats *Stats) (err error) {
stats.SwapTotal = val
case "SwapFree:":
stats.SwapFree = val
case "MemAvailable:":
stats.MemAvailable = val
}
}
}
@@ -248,190 +256,22 @@ func getInterfaceInfo(iInfo string, stats *Stats) (err error) {
return
}
func parseCPUFields(fields []string, stat *cpuRaw) {
numFields := len(fields)
for i := 1; i < numFields; i++ {
val, err := strconv.ParseUint(fields[i], 10, 64)
if err != nil {
continue
}
stat.Total += val
switch i {
case 1:
stat.User = val
case 2:
stat.Nice = val
case 3:
stat.System = val
case 4:
stat.Idle = val
case 5:
stat.Iowait = val
case 6:
stat.Irq = val
case 7:
stat.SoftIrq = val
case 8:
stat.Steal = val
case 9:
stat.Guest = val
}
}
}
// the CPU stats that were fetched last time round
var preCPU cpuRaw
func getCPU(cpuInfo string, stats *Stats) (err error) {
var (
nowCPU cpuRaw
total float32
)
// %Cpu(s): 6.1 us, 3.0 sy, 0.0 ni, 90.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
value := strings.Split(cpuInfo, ":")[1]
values := strings.Split(value, ",")
scanner := bufio.NewScanner(strings.NewReader(cpuInfo))
for scanner.Scan() {
line := scanner.Text()
fields := strings.Fields(line)
if len(fields) > 0 && fields[0] == "cpu" { // changing here if want to get every cpu-core's stats
parseCPUFields(fields, &nowCPU)
break
}
}
if preCPU.Total == 0 { // having no pre raw cpu data
goto END
}
us, _ := strconv.ParseFloat(strings.Split(strings.TrimSpace(values[0]), " ")[0], 32)
stats.CPU.User = float32(us)
total = float32(nowCPU.Total - preCPU.Total)
stats.CPU.User = float32(nowCPU.User-preCPU.User) / total * 100
stats.CPU.Nice = float32(nowCPU.Nice-preCPU.Nice) / total * 100
stats.CPU.System = float32(nowCPU.System-preCPU.System) / total * 100
stats.CPU.Idle = float32(nowCPU.Idle-preCPU.Idle) / total * 100
stats.CPU.Iowait = float32(nowCPU.Iowait-preCPU.Iowait) / total * 100
stats.CPU.Irq = float32(nowCPU.Irq-preCPU.Irq) / total * 100
stats.CPU.SoftIrq = float32(nowCPU.SoftIrq-preCPU.SoftIrq) / total * 100
stats.CPU.Guest = float32(nowCPU.Guest-preCPU.Guest) / total * 100
END:
preCPU = nowCPU
return
sy, _ := strconv.ParseFloat(strings.Split(strings.TrimSpace(values[1]), " ")[0], 32)
stats.CPU.System = float32(sy)
id, _ := strconv.ParseFloat(strings.Split(strings.TrimSpace(values[3]), " ")[0], 32)
stats.CPU.Idle = float32(id)
wa, _ := strconv.ParseFloat(strings.Split(strings.TrimSpace(values[4]), " ")[0], 32)
stats.CPU.Iowait = float32(wa)
return nil
}
func fmtUptime(stats *Stats) string {
dur := stats.Uptime
dur = dur - (dur % time.Second)
var days int
for dur.Hours() > 24.0 {
days++
dur -= 24 * time.Hour
}
s1 := dur.String()
s2 := ""
if days > 0 {
s2 = fmt.Sprintf("%dd ", days)
}
for _, ch := range s1 {
s2 += string(ch)
if ch == 'h' || ch == 'm' {
s2 += " "
}
}
return s2
}
func fmtBytes(val uint64) string {
if val < 1024 {
return fmt.Sprintf("%d bytes", val)
} else if val < 1024*1024 {
return fmt.Sprintf("%6.2f KiB", float64(val)/1024.0)
} else if val < 1024*1024*1024 {
return fmt.Sprintf("%6.2f MiB", float64(val)/1024.0/1024.0)
} else {
return fmt.Sprintf("%6.2f GiB", float64(val)/1024.0/1024.0/1024.0)
}
}
func ShowStats(output io.Writer, stats *Stats) {
used := stats.MemTotal - stats.MemFree - stats.MemBuffers - stats.MemCached
fmt.Fprintf(output,
`%s%s%s%s up %s%s%s
Load:
%s%s %s %s%s
CPU:
%s%.2f%s%% user, %s%.2f%s%% sys, %s%.2f%s%% nice, %s%.2f%s%% idle, %s%.2f%s%% iowait, %s%.2f%s%% hardirq, %s%.2f%s%% softirq, %s%.2f%s%% guest
Processes:
%s%s%s running of %s%s%s total
Memory:
free = %s%s%s
used = %s%s%s
buffers = %s%s%s
cached = %s%s%s
swap = %s%s%s free of %s%s%s
`,
escClear,
escBrightWhite, stats.Hostname, escReset,
escBrightWhite, fmtUptime(stats), escReset,
escBrightWhite, stats.Load1, stats.Load5, stats.Load10, escReset,
escBrightWhite, stats.CPU.User, escReset,
escBrightWhite, stats.CPU.System, escReset,
escBrightWhite, stats.CPU.Nice, escReset,
escBrightWhite, stats.CPU.Idle, escReset,
escBrightWhite, stats.CPU.Iowait, escReset,
escBrightWhite, stats.CPU.Irq, escReset,
escBrightWhite, stats.CPU.SoftIrq, escReset,
escBrightWhite, stats.CPU.Guest, escReset,
escBrightWhite, stats.RunningProcs, escReset,
escBrightWhite, stats.TotalProcs, escReset,
escBrightWhite, fmtBytes(stats.MemFree), escReset,
escBrightWhite, fmtBytes(used), escReset,
escBrightWhite, fmtBytes(stats.MemBuffers), escReset,
escBrightWhite, fmtBytes(stats.MemCached), escReset,
escBrightWhite, fmtBytes(stats.SwapFree), escReset,
escBrightWhite, fmtBytes(stats.SwapTotal), escReset,
)
if len(stats.FSInfos) > 0 {
fmt.Println("Filesystems:")
for _, fs := range stats.FSInfos {
fmt.Fprintf(output, " %s%8s%s: %s%s%s free of %s%s%s\n",
escBrightWhite, fs.MountPoint, escReset,
escBrightWhite, fmtBytes(fs.Free), escReset,
escBrightWhite, fmtBytes(fs.Used+fs.Free), escReset,
)
}
fmt.Println()
}
if len(stats.NetIntf) > 0 {
fmt.Println("Network Interfaces:")
keys := make([]string, 0, len(stats.NetIntf))
for intf := range stats.NetIntf {
keys = append(keys, intf)
}
sort.Strings(keys)
for _, intf := range keys {
info := stats.NetIntf[intf]
fmt.Fprintf(output, " %s%s%s - %s%s%s",
escBrightWhite, intf, escReset,
escBrightWhite, info.IPv4, escReset,
)
if len(info.IPv6) > 0 {
fmt.Fprintf(output, ", %s%s%s\n",
escBrightWhite, info.IPv6, escReset,
)
} else {
fmt.Fprintf(output, "\n")
}
fmt.Fprintf(output, " rx = %s%s%s, tx = %s%s%s\n",
escBrightWhite, fmtBytes(info.Rx), escReset,
escBrightWhite, fmtBytes(info.Tx), escReset,
)
fmt.Println()
}
fmt.Println()
}
}
const (
escClear = ""
escRed = ""
escReset = ""
escBrightWhite = ""
)