github.com/gofiber/fiber/v2@v2.47.0/internal/gopsutil/load/load_linux.go (about) 1 //go:build linux 2 // +build linux 3 4 package load 5 6 import ( 7 "context" 8 "os" 9 "strconv" 10 "strings" 11 "syscall" 12 13 "github.com/gofiber/fiber/v2/internal/gopsutil/common" 14 ) 15 16 func Avg() (*AvgStat, error) { 17 return AvgWithContext(context.Background()) 18 } 19 20 func AvgWithContext(ctx context.Context) (*AvgStat, error) { 21 stat, err := fileAvgWithContext(ctx) 22 if err != nil { 23 stat, err = sysinfoAvgWithContext(ctx) 24 } 25 return stat, err 26 } 27 28 func sysinfoAvgWithContext(ctx context.Context) (*AvgStat, error) { 29 var info syscall.Sysinfo_t 30 err := syscall.Sysinfo(&info) 31 if err != nil { 32 return nil, err 33 } 34 35 const si_load_shift = 16 36 return &AvgStat{ 37 Load1: float64(info.Loads[0]) / float64(1<<si_load_shift), 38 Load5: float64(info.Loads[1]) / float64(1<<si_load_shift), 39 Load15: float64(info.Loads[2]) / float64(1<<si_load_shift), 40 }, nil 41 } 42 43 func fileAvgWithContext(ctx context.Context) (*AvgStat, error) { 44 values, err := readLoadAvgFromFile() 45 if err != nil { 46 return nil, err 47 } 48 49 load1, err := strconv.ParseFloat(values[0], 64) 50 if err != nil { 51 return nil, err 52 } 53 load5, err := strconv.ParseFloat(values[1], 64) 54 if err != nil { 55 return nil, err 56 } 57 load15, err := strconv.ParseFloat(values[2], 64) 58 if err != nil { 59 return nil, err 60 } 61 62 ret := &AvgStat{ 63 Load1: load1, 64 Load5: load5, 65 Load15: load15, 66 } 67 68 return ret, nil 69 } 70 71 // Misc returnes miscellaneous host-wide statistics. 72 // Note: the name should be changed near future. 73 func Misc() (*MiscStat, error) { 74 return MiscWithContext(context.Background()) 75 } 76 77 func MiscWithContext(ctx context.Context) (*MiscStat, error) { 78 filename := common.HostProc("stat") 79 out, err := os.ReadFile(filename) 80 if err != nil { 81 return nil, err 82 } 83 84 ret := &MiscStat{} 85 lines := strings.Split(string(out), "\n") 86 for _, line := range lines { 87 fields := strings.Fields(line) 88 if len(fields) != 2 { 89 continue 90 } 91 v, err := strconv.ParseInt(fields[1], 10, 64) 92 if err != nil { 93 continue 94 } 95 switch fields[0] { 96 case "processes": 97 ret.ProcsCreated = v 98 case "procs_running": 99 ret.ProcsRunning = v 100 case "procs_blocked": 101 ret.ProcsBlocked = v 102 case "ctxt": 103 ret.Ctxt = v 104 default: 105 continue 106 } 107 108 } 109 110 procsTotal, err := getProcsTotal() 111 if err != nil { 112 return ret, err 113 } 114 ret.ProcsTotal = procsTotal 115 116 return ret, nil 117 } 118 119 func getProcsTotal() (int64, error) { 120 values, err := readLoadAvgFromFile() 121 if err != nil { 122 return 0, err 123 } 124 return strconv.ParseInt(strings.Split(values[3], "/")[1], 10, 64) 125 } 126 127 func readLoadAvgFromFile() ([]string, error) { 128 loadavgFilename := common.HostProc("loadavg") 129 line, err := os.ReadFile(loadavgFilename) 130 if err != nil { 131 return nil, err 132 } 133 134 values := strings.Fields(string(line)) 135 return values, nil 136 }