| package process |
| |
| import ( |
| "encoding/json" |
| "runtime" |
| "time" |
| |
| "github.com/shirou/gopsutil/cpu" |
| "github.com/shirou/gopsutil/internal/common" |
| "github.com/shirou/gopsutil/mem" |
| ) |
| |
| var invoke common.Invoker |
| |
| func init() { |
| invoke = common.Invoke{} |
| } |
| |
| type Process struct { |
| Pid int32 `json:"pid"` |
| name string |
| status string |
| parent int32 |
| numCtxSwitches *NumCtxSwitchesStat |
| uids []int32 |
| gids []int32 |
| numThreads int32 |
| memInfo *MemoryInfoStat |
| |
| lastCPUTimes *cpu.TimesStat |
| lastCPUTime time.Time |
| } |
| |
| type OpenFilesStat struct { |
| Path string `json:"path"` |
| Fd uint64 `json:"fd"` |
| } |
| |
| type MemoryInfoStat struct { |
| RSS uint64 `json:"rss"` // bytes |
| VMS uint64 `json:"vms"` // bytes |
| Swap uint64 `json:"swap"` // bytes |
| } |
| |
| type RlimitStat struct { |
| Resource int32 `json:"resource"` |
| Soft int32 `json:"soft"` |
| Hard int32 `json:"hard"` |
| } |
| |
| type IOCountersStat struct { |
| ReadCount uint64 `json:"readCount"` |
| WriteCount uint64 `json:"writeCount"` |
| ReadBytes uint64 `json:"readBytes"` |
| WriteBytes uint64 `json:"writeBytes"` |
| } |
| |
| type NumCtxSwitchesStat struct { |
| Voluntary int64 `json:"voluntary"` |
| Involuntary int64 `json:"involuntary"` |
| } |
| |
| func (p Process) String() string { |
| s, _ := json.Marshal(p) |
| return string(s) |
| } |
| |
| func (o OpenFilesStat) String() string { |
| s, _ := json.Marshal(o) |
| return string(s) |
| } |
| |
| func (m MemoryInfoStat) String() string { |
| s, _ := json.Marshal(m) |
| return string(s) |
| } |
| |
| func (r RlimitStat) String() string { |
| s, _ := json.Marshal(r) |
| return string(s) |
| } |
| |
| func (i IOCountersStat) String() string { |
| s, _ := json.Marshal(i) |
| return string(s) |
| } |
| |
| func (p NumCtxSwitchesStat) String() string { |
| s, _ := json.Marshal(p) |
| return string(s) |
| } |
| |
| func PidExists(pid int32) (bool, error) { |
| pids, err := Pids() |
| if err != nil { |
| return false, err |
| } |
| |
| for _, i := range pids { |
| if i == pid { |
| return true, err |
| } |
| } |
| |
| return false, err |
| } |
| |
| // If interval is 0, return difference from last call(non-blocking). |
| // If interval > 0, wait interval sec and return diffrence between start and end. |
| func (p *Process) Percent(interval time.Duration) (float64, error) { |
| cpuTimes, err := p.Times() |
| if err != nil { |
| return 0, err |
| } |
| now := time.Now() |
| |
| if interval > 0 { |
| p.lastCPUTimes = cpuTimes |
| p.lastCPUTime = now |
| time.Sleep(interval) |
| cpuTimes, err = p.Times() |
| now = time.Now() |
| if err != nil { |
| return 0, err |
| } |
| } else { |
| if p.lastCPUTimes == nil { |
| // invoked first time |
| p.lastCPUTimes = cpuTimes |
| p.lastCPUTime = now |
| return 0, nil |
| } |
| } |
| |
| numcpu := runtime.NumCPU() |
| delta := (now.Sub(p.lastCPUTime).Seconds()) * float64(numcpu) |
| ret := calculatePercent(p.lastCPUTimes, cpuTimes, delta, numcpu) |
| p.lastCPUTimes = cpuTimes |
| p.lastCPUTime = now |
| return ret, nil |
| } |
| |
| func calculatePercent(t1, t2 *cpu.TimesStat, delta float64, numcpu int) float64 { |
| if delta == 0 { |
| return 0 |
| } |
| delta_proc := t2.Total() - t1.Total() |
| overall_percent := ((delta_proc / delta) * 100) * float64(numcpu) |
| return overall_percent |
| } |
| |
| // MemoryPercent returns how many percent of the total RAM this process uses |
| func (p *Process) MemoryPercent() (float32, error) { |
| machineMemory, err := mem.VirtualMemory() |
| if err != nil { |
| return 0, err |
| } |
| total := machineMemory.Total |
| |
| processMemory, err := p.MemoryInfo() |
| if err != nil { |
| return 0, err |
| } |
| used := processMemory.RSS |
| |
| return (100 * float32(used) / float32(total)), nil |
| } |