2014-12-30 22:09:05 +09:00
|
|
|
package process
|
2014-04-23 12:26:21 +09:00
|
|
|
|
2014-05-01 18:43:11 +09:00
|
|
|
import (
|
|
|
|
"encoding/json"
|
2015-03-04 00:02:09 +09:00
|
|
|
"runtime"
|
|
|
|
"time"
|
|
|
|
|
2015-09-16 11:58:02 +09:00
|
|
|
"github.com/shirou/gopsutil/cpu"
|
2015-10-18 20:40:01 -07:00
|
|
|
"github.com/shirou/gopsutil/internal/common"
|
2016-02-16 19:15:41 +01:00
|
|
|
"github.com/shirou/gopsutil/mem"
|
2014-05-01 18:43:11 +09:00
|
|
|
)
|
|
|
|
|
2015-09-16 11:58:02 +09:00
|
|
|
var invoke common.Invoker
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
invoke = common.Invoke{}
|
|
|
|
}
|
|
|
|
|
2014-04-23 12:26:21 +09:00
|
|
|
type Process struct {
|
2014-09-19 22:41:29 +09:00
|
|
|
Pid int32 `json:"pid"`
|
|
|
|
name string
|
|
|
|
status string
|
2014-08-31 14:46:23 +04:00
|
|
|
numCtxSwitches *NumCtxSwitchesStat
|
2014-09-19 22:41:29 +09:00
|
|
|
uids []int32
|
|
|
|
gids []int32
|
|
|
|
numThreads int32
|
2014-10-22 19:58:39 +04:00
|
|
|
memInfo *MemoryInfoStat
|
2015-03-04 00:02:09 +09:00
|
|
|
|
|
|
|
lastCPUTimes *cpu.CPUTimesStat
|
|
|
|
lastCPUTime time.Time
|
2014-04-23 12:26:21 +09:00
|
|
|
}
|
|
|
|
|
2014-04-30 15:32:05 +09:00
|
|
|
type OpenFilesStat struct {
|
2014-04-24 00:38:19 +09:00
|
|
|
Path string `json:"path"`
|
2014-04-25 15:09:38 +09:00
|
|
|
Fd uint64 `json:"fd"`
|
2014-04-23 12:26:21 +09:00
|
|
|
}
|
|
|
|
|
2014-04-30 15:32:05 +09:00
|
|
|
type MemoryInfoStat struct {
|
2014-10-22 19:58:39 +04:00
|
|
|
RSS uint64 `json:"rss"` // bytes
|
|
|
|
VMS uint64 `json:"vms"` // bytes
|
|
|
|
Swap uint64 `json:"swap"` // bytes
|
2014-04-23 12:26:21 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
type RlimitStat struct {
|
2014-04-24 00:38:19 +09:00
|
|
|
Resource int32 `json:"resource"`
|
|
|
|
Soft int32 `json:"soft"`
|
|
|
|
Hard int32 `json:"hard"`
|
2014-04-23 12:26:21 +09:00
|
|
|
}
|
|
|
|
|
2014-04-30 16:16:07 +09:00
|
|
|
type IOCountersStat struct {
|
2014-11-02 11:33:51 +03:00
|
|
|
ReadCount uint64 `json:"read_count"`
|
|
|
|
WriteCount uint64 `json:"write_count"`
|
|
|
|
ReadBytes uint64 `json:"read_bytes"`
|
|
|
|
WriteBytes uint64 `json:"write_bytes"`
|
2014-04-23 12:26:21 +09:00
|
|
|
}
|
2014-04-23 13:24:07 +09:00
|
|
|
|
2014-05-01 19:10:15 +09:00
|
|
|
type NumCtxSwitchesStat struct {
|
2014-09-13 00:29:54 +04:00
|
|
|
Voluntary int64 `json:"voluntary"`
|
|
|
|
Involuntary int64 `json:"involuntary"`
|
2014-05-01 19:10:15 +09:00
|
|
|
}
|
|
|
|
|
2014-05-01 18:43:11 +09:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2014-05-01 19:10:15 +09:00
|
|
|
func (p NumCtxSwitchesStat) String() string {
|
|
|
|
s, _ := json.Marshal(p)
|
|
|
|
return string(s)
|
|
|
|
}
|
|
|
|
|
2014-04-30 15:32:05 +09:00
|
|
|
func PidExists(pid int32) (bool, error) {
|
2014-04-23 13:24:07 +09:00
|
|
|
pids, err := Pids()
|
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, i := range pids {
|
|
|
|
if i == pid {
|
|
|
|
return true, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false, err
|
|
|
|
}
|
2015-03-04 00:02:09 +09:00
|
|
|
|
|
|
|
// 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) CPUPercent(interval time.Duration) (float64, error) {
|
|
|
|
cpuTimes, err := p.CPUTimes()
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
2016-01-19 21:36:45 -07:00
|
|
|
now := time.Now()
|
2015-03-04 00:02:09 +09:00
|
|
|
|
|
|
|
if interval > 0 {
|
|
|
|
p.lastCPUTimes = cpuTimes
|
2016-01-19 21:36:45 -07:00
|
|
|
p.lastCPUTime = now
|
2015-03-04 00:02:09 +09:00
|
|
|
time.Sleep(interval)
|
|
|
|
cpuTimes, err = p.CPUTimes()
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if p.lastCPUTimes == nil {
|
|
|
|
// invoked first time
|
2016-01-19 21:36:45 -07:00
|
|
|
p.lastCPUTimes = cpuTimes
|
|
|
|
p.lastCPUTime = now
|
2015-03-04 00:02:09 +09:00
|
|
|
return 0, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-19 21:36:45 -07:00
|
|
|
numcpu := runtime.NumCPU()
|
|
|
|
delta := (now.Sub(p.lastCPUTime).Seconds()) * float64(numcpu)
|
|
|
|
ret := calculatePercent(p.lastCPUTimes, cpuTimes, delta, numcpu)
|
2015-03-04 00:02:09 +09:00
|
|
|
p.lastCPUTimes = cpuTimes
|
2016-01-19 21:36:45 -07:00
|
|
|
p.lastCPUTime = now
|
2015-03-04 00:02:09 +09:00
|
|
|
return ret, nil
|
|
|
|
}
|
2016-01-19 21:36:45 -07:00
|
|
|
|
|
|
|
func calculatePercent(t1, t2 *cpu.CPUTimesStat, delta float64, numcpu int) float64 {
|
|
|
|
if delta == 0 {
|
|
|
|
return 0
|
|
|
|
}
|
2016-02-10 17:48:43 +01:00
|
|
|
delta_proc := t2.Total() - t1.Total()
|
2016-01-19 21:36:45 -07:00
|
|
|
overall_percent := ((delta_proc / delta) * 100) * float64(numcpu)
|
|
|
|
return overall_percent
|
|
|
|
}
|
2016-02-16 19:15:41 +01:00
|
|
|
|
|
|
|
// 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
|
|
|
|
}
|