diff --git a/README.rst b/README.rst index 4776b38..c1e018f 100644 --- a/README.rst +++ b/README.rst @@ -88,6 +88,7 @@ Current Status - io_counters (linux) - nice (linux) - num_fds (linux) + - num_ctx_switches (linux) - num_threads (linux, freebsd, windows) - cpu_times (linux) - memory_info (linux, freebsd) @@ -110,7 +111,6 @@ Current Status - username - ionice - rlimit - - num_ctx_switches - num_handlers - threads - cpu_percent diff --git a/process.go b/process.go index 64a1627..5d64721 100644 --- a/process.go +++ b/process.go @@ -31,6 +31,11 @@ type IOCountersStat struct { WriteBytes int32 `json:"write_bytes"` } +type NumCtxSwitchesStat struct { + Voluntary int32 `json:"voluntary"` + Involuntary int32 `json:"involuntary"` +} + func (p Process) String() string { s, _ := json.Marshal(p) return string(s) @@ -56,6 +61,11 @@ func (i IOCountersStat) String() string { 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 { diff --git a/process_freebsd.go b/process_freebsd.go index 8ac876d..83448ae 100644 --- a/process_freebsd.go +++ b/process_freebsd.go @@ -124,8 +124,8 @@ func (p *Process) Rlimit() ([]RlimitStat, error) { func (p *Process) IOCounters() (*IOCountersStat, error) { return nil, errors.New("not implemented yet") } -func (p *Process) NumCtxSwitches() (int32, error) { - return 0, errors.New("not implemented yet") +func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) { + return nil, errors.New("not implemented yet") } func (p *Process) NumFDs() (int32, error) { return 0, errors.New("not implemented yet") diff --git a/process_linux.go b/process_linux.go index 943d142..764ace2 100644 --- a/process_linux.go +++ b/process_linux.go @@ -3,6 +3,7 @@ package gopsutil import ( + "encoding/json" "errors" "io/ioutil" "os" @@ -10,7 +11,6 @@ import ( "strconv" "strings" "syscall" - "encoding/json" ) const ( @@ -27,6 +27,7 @@ type MemoryInfoExStat struct { Data uint64 `json:"data"` // bytes Dirty uint64 `json:"dirty"` // bytes } + func (m MemoryInfoExStat) String() string { s, _ := json.Marshal(m) return string(s) @@ -51,8 +52,6 @@ func (m MemoryMapsStat) String() string { return string(s) } - - // Create new Process instance // This only stores Pid func NewProcess(pid int32) (*Process, error) { @@ -70,7 +69,7 @@ func (p *Process) Ppid() (int32, error) { return ppid, nil } func (p *Process) Name() (string, error) { - name, _, _, _, _, err := p.fillFromStatus() + name, _, _, _, _, _, err := p.fillFromStatus() if err != nil { return "", err } @@ -97,7 +96,7 @@ func (p *Process) Parent() (*Process, error) { return nil, errors.New("not implemented yet") } func (p *Process) Status() (string, error) { - _, status, _, _, _, err := p.fillFromStatus() + _, status, _, _, _, _, err := p.fillFromStatus() if err != nil { return "", err } @@ -107,14 +106,14 @@ func (p *Process) Username() (string, error) { return "", nil } func (p *Process) Uids() ([]int32, error) { - _, _, uids, _, _, err := p.fillFromStatus() + _, _, uids, _, _, _, err := p.fillFromStatus() if err != nil { return nil, err } return uids, nil } func (p *Process) Gids() ([]int32, error) { - _, _, _, gids, _, err := p.fillFromStatus() + _, _, _, gids, _, _, err := p.fillFromStatus() if err != nil { return nil, err } @@ -143,14 +142,18 @@ func (p *Process) Rlimit() ([]RlimitStat, error) { func (p *Process) IOCounters() (*IOCountersStat, error) { return p.fillFromIO() } -func (p *Process) NumCtxSwitches() (int32, error) { - return 0, errors.New("not implemented yet") +func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) { + _, _, _, _, _, numCtxSwitches, err := p.fillFromStatus() + if err != nil { + return nil, err + } + return numCtxSwitches, nil } func (p *Process) NumFDs() (int32, error) { return 0, errors.New("not implemented yet") } func (p *Process) NumThreads() (int32, error) { - _, _, _, _, numThreads, err := p.fillFromStatus() + _, _, _, _, numThreads, _, err := p.fillFromStatus() if err != nil { return 0, err } @@ -407,18 +410,20 @@ func (p *Process) fillFromStatm() (*MemoryInfoStat, *MemoryInfoExStat, error) { } // Get various status from /proc/(pid)/status -func (p *Process) fillFromStatus() (string, string, []int32, []int32, int32, error) { +func (p *Process) fillFromStatus() (string, string, []int32, []int32, int32, *NumCtxSwitchesStat, error) { pid := p.Pid statPath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "status") contents, err := ioutil.ReadFile(statPath) if err != nil { - return "", "", nil, nil, 0, err + return "", "", nil, nil, 0, nil, err } lines := strings.Split(string(contents), "\n") name := "" status := "" var numThreads int32 + var vol int32 + var unvol int32 var uids []int32 var gids []int32 for _, line := range lines { @@ -446,10 +451,18 @@ func (p *Process) fillFromStatus() (string, string, []int32, []int32, int32, err } case "Threads": numThreads = parseInt32(field[1]) + case "voluntary_ctxt_switches": + vol = parseInt32(field[1]) + case "nonvoluntary_ctxt_switches": + unvol = parseInt32(field[1]) } } - return name, status, uids, gids, numThreads, nil + numctx := &NumCtxSwitchesStat{ + Voluntary: vol, + Involuntary: unvol, + } + return name, status, uids, gids, numThreads, numctx, nil } func (p *Process) fillFromStat() (string, int32, *CPUTimesStat, int64, int32, error) { diff --git a/process_test.go b/process_test.go index a59f20a..dd26c21 100644 --- a/process_test.go +++ b/process_test.go @@ -101,3 +101,13 @@ func Test_Process_IOCounters(t *testing.T) { fmt.Println(v) } + +func Test_Process_NumCtx(t *testing.T) { + p := test_getProcess() + + _, err := p.NumCtxSwitches() + if err != nil { + t.Errorf("geting numctx error %v", err) + return + } +} diff --git a/process_windows.go b/process_windows.go index f55fd77..e676b34 100644 --- a/process_windows.go +++ b/process_windows.go @@ -111,8 +111,8 @@ func (p *Process) Rlimit() ([]RlimitStat, error) { func (p *Process) IOCounters() (*IOCountersStat, error) { return nil, errors.New("not implemented yet") } -func (p *Process) NumCtxSwitches() (int32, error) { - return 0, errors.New("not implemented yet") +func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) { + return nil, errors.New("not implemented yet") } func (p *Process) NumFDs() (int32, error) { return 0, errors.New("not implemented yet")