|
|
|
@ -60,6 +60,13 @@ type MemoryMapsStat struct {
|
|
|
|
|
Swap uint64 `json:"swap"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type PageFaultsStat struct {
|
|
|
|
|
MinorFaults uint64 `json:"minorFaults"`
|
|
|
|
|
MajorFaults uint64 `json:"majorFaults"`
|
|
|
|
|
ChildMinorFaults uint64 `json:"childMinorFaults"`
|
|
|
|
|
ChildMajorFaults uint64 `json:"childMajorFaults"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// String returns JSON value of the process.
|
|
|
|
|
func (m MemoryMapsStat) String() string {
|
|
|
|
|
s, _ := json.Marshal(m)
|
|
|
|
@ -85,7 +92,7 @@ func (p *Process) Ppid() (int32, error) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Process) PpidWithContext(ctx context.Context) (int32, error) {
|
|
|
|
|
_, ppid, _, _, _, _, err := p.fillFromStat()
|
|
|
|
|
_, ppid, _, _, _, _, _, err := p.fillFromStat()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return -1, err
|
|
|
|
|
}
|
|
|
|
@ -151,7 +158,7 @@ func (p *Process) CreateTime() (int64, error) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Process) CreateTimeWithContext(ctx context.Context) (int64, error) {
|
|
|
|
|
_, _, _, createTime, _, _, err := p.fillFromStat()
|
|
|
|
|
_, _, _, createTime, _, _, _, err := p.fillFromStat()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
@ -254,7 +261,7 @@ func (p *Process) Terminal() (string, error) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Process) TerminalWithContext(ctx context.Context) (string, error) {
|
|
|
|
|
t, _, _, _, _, _, err := p.fillFromStat()
|
|
|
|
|
t, _, _, _, _, _, _, err := p.fillFromStat()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
@ -273,7 +280,7 @@ func (p *Process) Nice() (int32, error) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
|
|
|
|
|
_, _, _, _, _, nice, err := p.fillFromStat()
|
|
|
|
|
_, _, _, _, _, nice, _, err := p.fillFromStat()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
@ -311,7 +318,7 @@ func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) (
|
|
|
|
|
return rlimits, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_, _, _, _, rtprio, nice, err := p.fillFromStat()
|
|
|
|
|
_, _, _, _, rtprio, nice, _, err := p.fillFromStat()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
@ -419,7 +426,7 @@ func (p *Process) ThreadsWithContext(ctx context.Context) (map[int32]*cpu.TimesS
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, tid := range tids {
|
|
|
|
|
_, _, cpuTimes, _, _, _, err := p.fillFromTIDStat(tid)
|
|
|
|
|
_, _, cpuTimes, _, _, _, _, err := p.fillFromTIDStat(tid)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
@ -435,7 +442,7 @@ func (p *Process) Times() (*cpu.TimesStat, error) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error) {
|
|
|
|
|
_, _, cpuTimes, _, _, _, err := p.fillFromStat()
|
|
|
|
|
_, _, cpuTimes, _, _, _, _, err := p.fillFromStat()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
@ -479,6 +486,20 @@ func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExSta
|
|
|
|
|
return memInfoEx, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// PageFaultsInfo returns the process's page fault counters
|
|
|
|
|
func (p *Process) PageFaults() (*PageFaultsStat, error) {
|
|
|
|
|
return p.PageFaultsWithContext(context.Background())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, error) {
|
|
|
|
|
_, _, _, _, _, _, pageFaults, err := p.fillFromStat()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return pageFaults, nil
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Children returns a slice of Process of the process.
|
|
|
|
|
func (p *Process) Children() ([]*Process, error) {
|
|
|
|
|
return p.ChildrenWithContext(context.Background())
|
|
|
|
@ -1148,11 +1169,11 @@ func (p *Process) fillFromStatusWithContext(ctx context.Context) error {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Process) fillFromTIDStat(tid int32) (uint64, int32, *cpu.TimesStat, int64, uint32, int32, error) {
|
|
|
|
|
func (p *Process) fillFromTIDStat(tid int32) (uint64, int32, *cpu.TimesStat, int64, uint32, int32, *PageFaultsStat, error) {
|
|
|
|
|
return p.fillFromTIDStatWithContext(context.Background(), tid)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (uint64, int32, *cpu.TimesStat, int64, uint32, int32, error) {
|
|
|
|
|
func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (uint64, int32, *cpu.TimesStat, int64, uint32, int32, *PageFaultsStat, error) {
|
|
|
|
|
pid := p.Pid
|
|
|
|
|
var statPath string
|
|
|
|
|
|
|
|
|
@ -1164,7 +1185,7 @@ func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (ui
|
|
|
|
|
|
|
|
|
|
contents, err := ioutil.ReadFile(statPath)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, 0, nil, 0, 0, 0, err
|
|
|
|
|
return 0, 0, nil, 0, 0, 0, nil, err
|
|
|
|
|
}
|
|
|
|
|
fields := strings.Fields(string(contents))
|
|
|
|
|
|
|
|
|
@ -1175,21 +1196,21 @@ func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (ui
|
|
|
|
|
|
|
|
|
|
terminal, err := strconv.ParseUint(fields[i+5], 10, 64)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, 0, nil, 0, 0, 0, err
|
|
|
|
|
return 0, 0, nil, 0, 0, 0, nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ppid, err := strconv.ParseInt(fields[i+2], 10, 32)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, 0, nil, 0, 0, 0, err
|
|
|
|
|
return 0, 0, nil, 0, 0, 0, nil, err
|
|
|
|
|
}
|
|
|
|
|
utime, err := strconv.ParseFloat(fields[i+12], 64)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, 0, nil, 0, 0, 0, err
|
|
|
|
|
return 0, 0, nil, 0, 0, 0, nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stime, err := strconv.ParseFloat(fields[i+13], 64)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, 0, nil, 0, 0, 0, err
|
|
|
|
|
return 0, 0, nil, 0, 0, 0, nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cpuTimes := &cpu.TimesStat{
|
|
|
|
@ -1201,14 +1222,14 @@ func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (ui
|
|
|
|
|
bootTime, _ := host.BootTime()
|
|
|
|
|
t, err := strconv.ParseUint(fields[i+20], 10, 64)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, 0, nil, 0, 0, 0, err
|
|
|
|
|
return 0, 0, nil, 0, 0, 0, nil, err
|
|
|
|
|
}
|
|
|
|
|
ctime := (t / uint64(ClockTicks)) + uint64(bootTime)
|
|
|
|
|
createTime := int64(ctime * 1000)
|
|
|
|
|
|
|
|
|
|
rtpriority, err := strconv.ParseInt(fields[i+16], 10, 32)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, 0, nil, 0, 0, 0, err
|
|
|
|
|
return 0, 0, nil, 0, 0, 0, nil, err
|
|
|
|
|
}
|
|
|
|
|
if rtpriority < 0 {
|
|
|
|
|
rtpriority = rtpriority*-1 - 1
|
|
|
|
@ -1221,14 +1242,38 @@ func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (ui
|
|
|
|
|
snice, _ := unix.Getpriority(PrioProcess, int(pid))
|
|
|
|
|
nice := int32(snice) // FIXME: is this true?
|
|
|
|
|
|
|
|
|
|
return terminal, int32(ppid), cpuTimes, createTime, uint32(rtpriority), nice, nil
|
|
|
|
|
minFault, err := strconv.ParseUint(fields[i+8], 10, 64)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, 0, nil, 0, 0, 0, nil, err
|
|
|
|
|
}
|
|
|
|
|
cMinFault, err := strconv.ParseUint(fields[i+9], 10, 64)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, 0, nil, 0, 0, 0, nil, err
|
|
|
|
|
}
|
|
|
|
|
majFault, err := strconv.ParseUint(fields[i+10], 10, 64)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, 0, nil, 0, 0, 0, nil, err
|
|
|
|
|
}
|
|
|
|
|
cMajFault, err := strconv.ParseUint(fields[i+11], 10, 64)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, 0, nil, 0, 0, 0, nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
faults := &PageFaultsStat{
|
|
|
|
|
MinorFaults: minFault,
|
|
|
|
|
MajorFaults: majFault,
|
|
|
|
|
ChildMinorFaults: cMinFault,
|
|
|
|
|
ChildMajorFaults: cMajFault,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return terminal, int32(ppid), cpuTimes, createTime, uint32(rtpriority), nice, faults, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Process) fillFromStat() (uint64, int32, *cpu.TimesStat, int64, uint32, int32, error) {
|
|
|
|
|
func (p *Process) fillFromStat() (uint64, int32, *cpu.TimesStat, int64, uint32, int32, *PageFaultsStat, error) {
|
|
|
|
|
return p.fillFromStatWithContext(context.Background())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Process) fillFromStatWithContext(ctx context.Context) (uint64, int32, *cpu.TimesStat, int64, uint32, int32, error) {
|
|
|
|
|
func (p *Process) fillFromStatWithContext(ctx context.Context) (uint64, int32, *cpu.TimesStat, int64, uint32, int32, *PageFaultsStat, error) {
|
|
|
|
|
return p.fillFromTIDStat(-1)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|