| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- package main
- import (
- "encoding/json"
- "fmt"
- "net/http"
- "os"
- "os/exec"
- "runtime"
- "strconv"
- "strings"
- "sync"
- )
- var lastCPU struct {
- idle, total uint64
- mu sync.Mutex
- }
- func initCPUUsage() {
- getCPUUsage()
- }
- func systemInfoHandler(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "application/json; charset=utf-8")
- memPercent, memUsed, memTotal := getMemInfo()
- diskPercent, diskUsed, diskTotal := getDiskInfo()
- json.NewEncoder(w).Encode(map[string]any{
- "cpu_usage": getCPUUsage(),
- "cpu_cores": getCPUCore(),
- "cpu_freq": getCPUFreq(),
- "mem_percent": memPercent,
- "mem_used": memUsed,
- "mem_total": memTotal,
- "disk_percent": diskPercent,
- "disk_used": diskUsed,
- "disk_total": diskTotal,
- })
- }
- func getCPUUsage() int {
- lastCPU.mu.Lock()
- defer lastCPU.mu.Unlock()
- data, err := os.ReadFile("/proc/stat")
- if err != nil {
- return 0
- }
- f := strings.Fields(strings.Split(string(data), "\n")[0])
- if len(f) < 5 {
- return 0
- }
- var idle, total uint64
- for i := 1; i < len(f); i++ {
- v, err := strconv.ParseUint(f[i], 10, 64)
- if err != nil {
- continue
- }
- total += v
- // idle + iowait
- if i == 4 || i == 5 {
- idle += v
- }
- }
- if lastCPU.total == 0 {
- lastCPU.idle = idle
- lastCPU.total = total
- return 0
- }
- dt := total - lastCPU.total
- di := idle - lastCPU.idle
- lastCPU.idle = idle
- lastCPU.total = total
- if dt == 0 {
- return 0
- }
- return int((dt - di) * 100 / dt)
- }
- func getCPUCore() int {
- return runtime.NumCPU()
- }
- func getCPUFreq() string {
- var total, count int
- for i := 0; ; i++ {
- data, err := os.ReadFile(fmt.Sprintf("/sys/devices/system/cpu/cpu%d/cpufreq/scaling_cur_freq", i))
- if err != nil {
- break
- }
- freq, err := strconv.Atoi(strings.TrimSpace(string(data)))
- if err != nil {
- continue
- }
- total += freq / 1000
- count++
- }
- if count > 0 {
- return strconv.Itoa(total / count)
- }
- data, err := os.ReadFile("/proc/cpuinfo")
- if err == nil {
- for _, line := range strings.Split(string(data), "\n") {
- if strings.HasPrefix(line, "cpu MHz") {
- f := strings.Split(line, ":")
- if len(f) == 2 {
- v, err := strconv.ParseFloat(strings.TrimSpace(f[1]), 64)
- if err == nil {
- return strconv.Itoa(int(v))
- }
- }
- }
- }
- }
- return noValue
- }
- func getMemInfo() (int, string, string) {
- data, err := os.ReadFile("/proc/meminfo")
- if err != nil {
- return 0, noValue, noValue
- }
- var total, avail uint64
- for _, line := range strings.Split(string(data), "\n") {
- f := strings.Fields(line)
- if len(f) < 2 {
- continue
- }
- switch f[0] {
- case "MemTotal:":
- total, _ = strconv.ParseUint(f[1], 10, 64)
- case "MemAvailable:":
- avail, _ = strconv.ParseUint(f[1], 10, 64)
- }
- }
- if total == 0 {
- return 0, noValue, noValue
- }
- used := total - avail
- return int(used * 100 / total),
- formatSize(used * 1024),
- formatSize(total * 1024)
- }
- func getDiskInfo() (int, string, string) {
- out, err := exec.Command("df", "-h", "/").Output()
- if err != nil {
- return 0, noValue, noValue
- }
- lines := strings.Split(string(out), "\n")
- if len(lines) < 2 {
- return 0, noValue, noValue
- }
- f := strings.Fields(lines[1])
- if len(f) < 5 {
- return 0, noValue, noValue
- }
- percent, err := strconv.Atoi(strings.TrimSuffix(f[4], "%"))
- if err != nil {
- percent = 0
- }
- return percent, f[2], f[1]
- }
- func formatSize(size uint64) string {
- const (
- KB = 1024
- MB = KB * 1024
- GB = MB * 1024
- )
- switch {
- case size >= GB:
- return fmt.Sprintf("%.1fGB", float64(size)/GB)
- case size >= MB:
- return fmt.Sprintf("%.0fMB", float64(size)/MB)
- case size >= KB:
- return fmt.Sprintf("%.0fKB", float64(size)/KB)
- default:
- return fmt.Sprintf("%dB", size)
- }
- }
|