Merge pull request #162 from shirou/load/add_misc

[load]all: add Misc in load to get miscellaneous host info from /proc…
This commit is contained in:
shirou 2016-02-27 02:01:46 +09:00
commit 3618a777a8
7 changed files with 151 additions and 1 deletions

View File

@ -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)
}

View File

@ -3,7 +3,9 @@
package load
import (
"os/exec"
"strconv"
"strings"
"github.com/shirou/gopsutil/internal/common"
)
@ -35,3 +37,32 @@ 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 {
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
}

View File

@ -3,7 +3,9 @@
package load
import (
"os/exec"
"strconv"
"strings"
"github.com/shirou/gopsutil/internal/common"
)
@ -35,3 +37,29 @@ 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 {
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
}

View File

@ -40,3 +40,40 @@ 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)
if err != nil {
return nil, err
}
ret := &MiscStat{}
lines := strings.Split(string(out), "\n")
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.ProcsRunning = int(v)
case "procs_blocked":
ret.ProcsBlocked = int(v)
case "ctxt":
ret.Ctxt = int(v)
default:
continue
}
}
return ret, nil
}

View File

@ -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)
}
}

View File

@ -11,3 +11,9 @@ func LoadAvg() (*LoadAvgStat, error) {
return &ret, common.NotImplementedError
}
func Misc() (*MiscStat, error) {
ret := MiscStat{}
return &ret, common.NotImplementedError
}

View File

@ -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
}