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