feat(dev): add error and update readme

This commit is contained in:
strucoder 2017-04-10 17:48:47 +08:00
parent 0ea98db742
commit 7803be576c
2 changed files with 23 additions and 12 deletions

View File

@ -3,16 +3,19 @@ Cross-platform process cpu % and memory usage of a PID for golang
Ideas from https://github.com/soyuka/pidusage but just use Golang Ideas from https://github.com/soyuka/pidusage but just use Golang
[![Go Report Card](https://goreportcard.com/badge/github.com/struCoder/pidusage)](https://goreportcard.com/report/github.com/struCoder/pidusage)
[![GoDoc](https://godoc.org/github.com/struCoder/pidusage?status.svg)](https://godoc.org/github.com/struCoder/pidusage)
## API ## API
```golang ```golang
import ( import (
"os" "os"
"github.com/struCoder/pmgo/lib/utils" "github.com/struCoder/pidusage"
) )
func printStat() { func printStat() {
sysInfo := pidusage.GetStat(os.Process.Pid) sysInfo, err := pidusage.GetStat(os.Process.Pid)
} }
``` ```
@ -21,7 +24,7 @@ func printStat() {
A check on the `runtime.GOOS` is done to determine the method to use. A check on the `runtime.GOOS` is done to determine the method to use.
### Linux ### Linux
We use `/proc/{pid}/stat` in addition to the the `PAGE_SIZE` and the `CLK_TCK` direclty from `getconf()` command. Uptime comes from `proc/uptime` file because it's more accurate than the nodejs `os.uptime()`. We use `/proc/{pid}/stat` in addition to the the `PAGE_SIZE` and the `CLK_TCK` direclty from `getconf()` command. Uptime comes from `proc/uptime`
Cpu usage is computed by following [those instructions](http://stackoverflow.com/questions/16726779/how-do-i-get-the-total-cpu-usage-of-an-application-from-proc-pid-stat/16736599#16736599). It keeps an history of the current processor time for the given pid so that the computed value gets more and more accurate. Don't forget to do `unmonitor(pid)` so that history gets cleared. Cpu usage is computed by following [those instructions](http://stackoverflow.com/questions/16726779/how-do-i-get-the-total-cpu-usage-of-an-application-from-proc-pid-stat/16736599#16736599). It keeps an history of the current processor time for the given pid so that the computed value gets more and more accurate. Don't forget to do `unmonitor(pid)` so that history gets cleared.
Cpu usage does not check the child process tree! Cpu usage does not check the child process tree!

View File

@ -1,6 +1,7 @@
package pidusage package pidusage
import ( import (
"errors"
"io/ioutil" "io/ioutil"
"math" "math"
"os/exec" "os/exec"
@ -27,15 +28,15 @@ type Stat struct {
uptime float64 uptime float64
} }
type fn func(int) *SysInfo type fn func(int) (*SysInfo, error)
var fnMap map[string]fn var fnMap map[string]fn
var platform string var platform string
var history map[int]Stat var history map[int]Stat
var eol string var eol string
func wrapper(statType string) func(pid int) *SysInfo { func wrapper(statType string) func(pid int) (*SysInfo, error) {
return func(pid int) *SysInfo { return func(pid int) (*SysInfo, error) {
return stat(pid, statType) return stat(pid, statType)
} }
} }
@ -67,7 +68,7 @@ func parseFloat(val string) float64 {
return floatVal return floatVal
} }
func stat(pid int, statType string) *SysInfo { func stat(pid int, statType string) (*SysInfo, error) {
sysInfo := &SysInfo{} sysInfo := &SysInfo{}
_history := history[pid] _history := history[pid]
if statType == "ps" { if statType == "ps" {
@ -77,6 +78,9 @@ func stat(pid int, statType string) *SysInfo {
} }
stdout, _ := exec.Command("ps", args, strconv.Itoa(pid)).Output() stdout, _ := exec.Command("ps", args, strconv.Itoa(pid)).Output()
ret := formatStdOut(stdout, 1) ret := formatStdOut(stdout, 1)
if len(ret) == 0 {
return sysInfo, errors.New("can not foud this pid: " + strconv.Itoa(pid))
}
sysInfo.CPU = parseFloat(ret[0]) sysInfo.CPU = parseFloat(ret[0])
sysInfo.Memory = parseFloat(ret[1]) * 1024 sysInfo.Memory = parseFloat(ret[1]) * 1024
} else if statType == "proc" { } else if statType == "proc" {
@ -98,7 +102,11 @@ func stat(pid int, statType string) *SysInfo {
} }
procStatFileBytes, err := ioutil.ReadFile(path.Join("/proc", strconv.Itoa(pid), "stat")) procStatFileBytes, err := ioutil.ReadFile(path.Join("/proc", strconv.Itoa(pid), "stat"))
infos := strings.Split(strings.SplitAfter(string(procStatFileBytes), ")")[1], " ") splitAfter := strings.SplitAfter(string(procStatFileBytes), ")")
if len(splitAfter) == 0 {
return sysInfo, errors.New("can not foud this pid: " + strconv.Itoa(pid))
}
infos := strings.Split(splitAfter[1], " ")
stat := &Stat{ stat := &Stat{
utime: parseFloat(infos[12]), utime: parseFloat(infos[12]),
stime: parseFloat(infos[13]), stime: parseFloat(infos[13]),
@ -135,12 +143,12 @@ func stat(pid int, statType string) *SysInfo {
sysInfo.CPU = (total / seconds) * 100 sysInfo.CPU = (total / seconds) * 100
sysInfo.Memory = stat.rss * pageSize sysInfo.Memory = stat.rss * pageSize
} }
return sysInfo return sysInfo, nil
} }
// GetStat will return current system CPU and memory data // GetStat will return current system CPU and memory data
func GetStat(pid int) *SysInfo { func GetStat(pid int) (*SysInfo, error) {
sysInfo := fnMap[platform](pid) sysInfo, err := fnMap[platform](pid)
return sysInfo return sysInfo, err
} }