From f9effa497ed7edd67e465842c1c2083e47585668 Mon Sep 17 00:00:00 2001 From: Shirou WAKAYAMA Date: Sat, 20 Feb 2016 22:52:16 +0900 Subject: [PATCH 1/4] [load]all: add Misc in load to get miscellaneous host info from /proc/stat --- load/load.go | 19 +++++++++++++++++++ load/load_darwin.go | 26 ++++++++++++++++++++++++++ load/load_freebsd.go | 25 +++++++++++++++++++++++++ load/load_linux.go | 38 ++++++++++++++++++++++++++++++++++++++ load/load_test.go | 24 ++++++++++++++++++++++++ load/load_windows.go | 6 ++++++ 6 files changed, 138 insertions(+) diff --git a/load/load.go b/load/load.go index 58746e7..bb996dc 100644 --- a/load/load.go +++ b/load/load.go @@ -2,8 +2,16 @@ package load import ( "encoding/json" + + "github.com/shirou/gopsutil/internal/common" ) +var invoke common.Invoker + +func init() { + invoke = common.Invoke{} +} + type LoadAvgStat struct { Load1 float64 `json:"load1"` Load5 float64 `json:"load5"` @@ -14,3 +22,14 @@ func (l LoadAvgStat) String() string { s, _ := json.Marshal(l) return string(s) } + +type MiscStat struct { + ProcsRunning int `json:"procsRunning"` + ProcsBlocked int `json:"procsBlocked"` + Ctxt int `json:"ctxt"` +} + +func (m MiscStat) String() string { + s, _ := json.Marshal(m) + return string(s) +} diff --git a/load/load_darwin.go b/load/load_darwin.go index 0d1c7ec..2b2fe7d 100644 --- a/load/load_darwin.go +++ b/load/load_darwin.go @@ -3,7 +3,9 @@ package load import ( + "os/exec" "strconv" + "strings" "github.com/shirou/gopsutil/internal/common" ) @@ -35,3 +37,27 @@ func LoadAvg() (*LoadAvgStat, error) { return ret, nil } + +func Misc() (*MiscStat, error) { + bin, err := exec.LookPath("ps") + if err != nil { + return nil, err + } + out, err := invoke.Command(bin, "axo", "state") + if err != nil { + return nil, err + } + lines := strings.Split(string(out), "\n") + + ret := MiscStat{} + for _, l := range lines { + if strings.Contains(l, "R") { + ret.ProcsRunning += 1 + } else if strings.Contains(l, "U") { + // uninterruptible sleep == blocked + ret.ProcsBlocked += 1 + } + } + + return &ret, nil +} diff --git a/load/load_freebsd.go b/load/load_freebsd.go index e97c569..814eb4a 100644 --- a/load/load_freebsd.go +++ b/load/load_freebsd.go @@ -3,7 +3,9 @@ package load import ( + "os/exec" "strconv" + "strings" "github.com/shirou/gopsutil/internal/common" ) @@ -35,3 +37,26 @@ func LoadAvg() (*LoadAvgStat, error) { return ret, nil } + +func Misc() (*MiscStat, error) { + bin, err := exec.LookPath("ps") + if err != nil { + return nil, err + } + out, err := invoke.Command(bin, "axo", "state") + if err != nil { + return nil, err + } + lines := strings.Split(string(out), "\n") + + ret := MiscStat{} + for _, l := range lines { + if strings.Contains(l, "R") { + ret.ProcsRunning += 1 + } else if strings.Contains(l, "D") { + ret.ProcsBlocked += 1 + } + } + + return &ret, nil +} diff --git a/load/load_linux.go b/load/load_linux.go index 80621c9..33b3e17 100644 --- a/load/load_linux.go +++ b/load/load_linux.go @@ -40,3 +40,41 @@ func LoadAvg() (*LoadAvgStat, error) { return ret, nil } + +func Misc() (*MiscStat, error) { + filename := common.HostProc("stat") + lines, err := ioutil.ReadFile(filename) + if err != nil { + return nil, err + } + + ret := &Misc{ + ProcsRunning: pr, + ProcsBlocked: pb, + Ctxt: ctxt, + } + + for _, line := range lines { + fields := strings.Fields(line) + if len(fields) != 2 { + continue + } + v, err := strconv.ParseInt(fields[1], 10, 64) + if err != nil { + continue + } + switch fields[0] { + case "procs_running": + ret.ProcessRunning = v + case "procs_blocked": + ret.ProcessBlocked = v + case "ctxt": + ret.Ctxt = v + default: + continue + } + + } + + return ret, nil +} diff --git a/load/load_test.go b/load/load_test.go index 39cee39..d2fa873 100644 --- a/load/load_test.go +++ b/load/load_test.go @@ -28,3 +28,27 @@ func TestLoadAvgStat_String(t *testing.T) { t.Errorf("LoadAvgStat string is invalid: %v", v) } } + +func TestMisc(t *testing.T) { + v, err := Misc() + if err != nil { + t.Errorf("error %v", err) + } + + empty := &MiscStat{} + if v == empty { + t.Errorf("error load: %v", v) + } +} + +func TestMiscStatString(t *testing.T) { + v := MiscStat{ + ProcsRunning: 1, + ProcsBlocked: 2, + Ctxt: 3, + } + e := `{"procsRunning":1,"procsBlocked":2,"ctxt":3}` + if e != fmt.Sprintf("%v", v) { + t.Errorf("TestMiscString string is invalid: %v", v) + } +} diff --git a/load/load_windows.go b/load/load_windows.go index 65a6ba7..691d20a 100644 --- a/load/load_windows.go +++ b/load/load_windows.go @@ -11,3 +11,9 @@ func LoadAvg() (*LoadAvgStat, error) { return &ret, common.NotImplementedError } + +func Misc() (*MiscStat, error) { + ret := MiscStat{} + + return &ret, common.NotImplementedError +} From c973fdbc4616132ae86dede99001e5a7e2515588 Mon Sep 17 00:00:00 2001 From: Shirou WAKAYAMA Date: Sat, 20 Feb 2016 23:03:32 +0900 Subject: [PATCH 2/4] [load]linux: fix compile problems. --- load/load_linux.go | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/load/load_linux.go b/load/load_linux.go index 33b3e17..4d437a8 100644 --- a/load/load_linux.go +++ b/load/load_linux.go @@ -43,17 +43,13 @@ func LoadAvg() (*LoadAvgStat, error) { func Misc() (*MiscStat, error) { filename := common.HostProc("stat") - lines, err := ioutil.ReadFile(filename) + out, err := ioutil.ReadFile(filename) if err != nil { return nil, err } - ret := &Misc{ - ProcsRunning: pr, - ProcsBlocked: pb, - Ctxt: ctxt, - } - + ret := &MiscStat{} + lines := strings.Split(string(out), "\n") for _, line := range lines { fields := strings.Fields(line) if len(fields) != 2 { @@ -65,11 +61,11 @@ func Misc() (*MiscStat, error) { } switch fields[0] { case "procs_running": - ret.ProcessRunning = v + ret.ProcsRunning = int(v) case "procs_blocked": - ret.ProcessBlocked = v + ret.ProcsBlocked = int(v) case "ctxt": - ret.Ctxt = v + ret.Ctxt = int(v) default: continue } From 821a0141b11ecf0a98be74c5836873f6deb8ba96 Mon Sep 17 00:00:00 2001 From: Shirou WAKAYAMA Date: Sat, 20 Feb 2016 23:17:20 +0900 Subject: [PATCH 3/4] [load]: add comments. --- load/load_darwin.go | 5 +++++ load/load_freebsd.go | 3 +++ load/load_linux.go | 3 +++ 3 files changed, 11 insertions(+) diff --git a/load/load_darwin.go b/load/load_darwin.go index 2b2fe7d..a603750 100644 --- a/load/load_darwin.go +++ b/load/load_darwin.go @@ -38,6 +38,11 @@ func LoadAvg() (*LoadAvgStat, error) { return ret, nil } + +// Misc returnes miscellaneous host-wide statistics. +// darwin use ps command to get process running/blocked count. +// Almost same as FreeBSD implementation, but state is different. +// U means 'Uninterruptible Sleep'. func Misc() (*MiscStat, error) { bin, err := exec.LookPath("ps") if err != nil { diff --git a/load/load_freebsd.go b/load/load_freebsd.go index 814eb4a..cd85085 100644 --- a/load/load_freebsd.go +++ b/load/load_freebsd.go @@ -38,6 +38,9 @@ func LoadAvg() (*LoadAvgStat, error) { return ret, nil } +// Misc returnes miscellaneous host-wide statistics. +// darwin use ps command to get process running/blocked count. +// Almost same as Darwin implementation, but state is different. func Misc() (*MiscStat, error) { bin, err := exec.LookPath("ps") if err != nil { diff --git a/load/load_linux.go b/load/load_linux.go index 4d437a8..e2b8c56 100644 --- a/load/load_linux.go +++ b/load/load_linux.go @@ -41,6 +41,9 @@ func LoadAvg() (*LoadAvgStat, error) { return ret, nil } + +// Misc returnes miscellaneous host-wide statistics. +// Note: the name should be changed near future. func Misc() (*MiscStat, error) { filename := common.HostProc("stat") out, err := ioutil.ReadFile(filename) From 97bcc355a68071cd95d1a72a7a5a3914d59a53b1 Mon Sep 17 00:00:00 2001 From: Shirou WAKAYAMA Date: Tue, 23 Feb 2016 15:13:24 +0900 Subject: [PATCH 4/4] [process]linux: change to use exec.LookPath to invoke lsof. --- process/process_linux.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/process/process_linux.go b/process/process_linux.go index 05a75c9..1783d2f 100644 --- a/process/process_linux.go +++ b/process/process_linux.go @@ -8,6 +8,7 @@ import ( "fmt" "io/ioutil" "os" + "os/exec" "path/filepath" "strconv" "strings" @@ -673,7 +674,11 @@ func callLsof(arg string, pid int32) ([]string, error) { } else { cmd = []string{"-a", "-F" + arg, "-p", strconv.Itoa(int(pid))} } - out, err := invoke.Command("/usr/bin/lsof", cmd...) + lsof, err := exec.LookPath("lsof") + if err != nil { + return []string{}, err + } + out, err := invoke.Command(lsof, cmd...) if err != nil { return []string{}, err }