From 354718bdd87e0a8edbb9e21093598b3e6dbeee4d Mon Sep 17 00:00:00 2001 From: Chad Harp Date: Sat, 1 Jun 2019 15:05:46 -0500 Subject: [PATCH 1/3] Add support for Solaris CPU times --- cpu/cpu_solaris.go | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 86 insertions(+), 3 deletions(-) diff --git a/cpu/cpu_solaris.go b/cpu/cpu_solaris.go index 947ac97..ab22c87 100644 --- a/cpu/cpu_solaris.go +++ b/cpu/cpu_solaris.go @@ -1,6 +1,7 @@ package cpu import ( + "bytes" "context" "errors" "fmt" @@ -10,8 +11,6 @@ import ( "sort" "strconv" "strings" - - "github.com/shirou/gopsutil/internal/common" ) var ClocksPerSec = float64(128) @@ -31,12 +30,96 @@ func init() { } } +//sum all values in a float64 map with float64 keys +func msum(x map[float64]float64) float64 { + total := 0.0 + for _, y := range x { + total += y + } + return total +} + func Times(percpu bool) ([]TimesStat, error) { return TimesWithContext(context.Background(), percpu) } func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) { - return []TimesStat{}, common.ErrNotImplementedError + kstatSys, err := exec.LookPath("kstat") + if err != nil { + return nil, fmt.Errorf("cannot find kstat: %s", err) + } + cpu := make(map[float64]float64) + idle := make(map[float64]float64) + user := make(map[float64]float64) + kern := make(map[float64]float64) + iowt := make(map[float64]float64) + //swap := make(map[float64]float64) + kstatSysOut, err := invoke.CommandWithContext(ctx, kstatSys, "-C", "cpu_stat:*:*:/^idle$|^user$|^kernel$|^iowait$|^swap$/") + if err != nil { + return nil, fmt.Errorf("cannot execute kstat: %s", err) + } + for _, line := range strings.Split(bytes.NewBuffer(kstatSysOut).String(), "\n") { + fields := strings.Split(line, ":") + if fields[0] != "cpu_stat" { + continue + } + cpuNumber, err := strconv.ParseFloat(fields[1], 64) + if err != nil { + return nil, fmt.Errorf("cannot parse cpu number: %s", err) + } + cpu[cpuNumber] = cpuNumber + switch fields[3] { + case "idle": + idle[cpuNumber], err = strconv.ParseFloat(fields[4], 64) + if err != nil { + return nil, fmt.Errorf("cannot parse idle: %s", err) + } + case "user": + user[cpuNumber], err = strconv.ParseFloat(fields[4], 64) + if err != nil { + return nil, fmt.Errorf("cannot parse user: %s", err) + } + case "kernel": + kern[cpuNumber], err = strconv.ParseFloat(fields[4], 64) + if err != nil { + return nil, fmt.Errorf("cannot parse kernel: %s", err) + } + case "iowait": + iowt[cpuNumber], err = strconv.ParseFloat(fields[4], 64) + if err != nil { + return nil, fmt.Errorf("cannot parse iowait: %s", err) + } + //not sure how this translates, don't report, add to kernel, something else? + /*case "swap": + swap[cpuNumber], err = strconv.ParseFloat(fields[4], 64) + if err != nil { + return nil, fmt.Errorf("cannot parse swap: %s", err) + } */ + } + } + ret := make([]TimesStat, 0, len(cpu)) + if percpu { + for _, c := range cpu { + ct := &TimesStat{ + CPU: fmt.Sprintf("cpu%d", int(cpu[c])), + Idle: idle[c] / ClocksPerSec, + User: user[c] / ClocksPerSec, + System: kern[c] / ClocksPerSec, + Iowait: iowt[c] / ClocksPerSec, + } + ret = append(ret, *ct) + } + } else { + ct := &TimesStat{ + CPU: "cpu-total", + Idle: msum(idle) / ClocksPerSec, + User: msum(user) / ClocksPerSec, + System: msum(kern) / ClocksPerSec, + Iowait: msum(iowt) / ClocksPerSec, + } + ret = append(ret, *ct) + } + return ret, nil } func Info() ([]InfoStat, error) { From 16b37cc9c27f53362af380bbdb0e862ddfdae614 Mon Sep 17 00:00:00 2001 From: Chad Harp Date: Sun, 2 Jun 2019 09:58:35 -0500 Subject: [PATCH 2/3] Modify cpu_solaris to support Sorlais 10 --- cpu/cpu_solaris.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cpu/cpu_solaris.go b/cpu/cpu_solaris.go index ab22c87..07c3106 100644 --- a/cpu/cpu_solaris.go +++ b/cpu/cpu_solaris.go @@ -54,12 +54,13 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) { kern := make(map[float64]float64) iowt := make(map[float64]float64) //swap := make(map[float64]float64) - kstatSysOut, err := invoke.CommandWithContext(ctx, kstatSys, "-C", "cpu_stat:*:*:/^idle$|^user$|^kernel$|^iowait$|^swap$/") + kstatSysOut, err := invoke.CommandWithContext(ctx, kstatSys, "-p", "cpu_stat:*:*:/^idle$|^user$|^kernel$|^iowait$|^swap$/") if err != nil { return nil, fmt.Errorf("cannot execute kstat: %s", err) } + re := regexp.MustCompile(`[:\s]+`) for _, line := range strings.Split(bytes.NewBuffer(kstatSysOut).String(), "\n") { - fields := strings.Split(line, ":") + fields := re.Split(line, -1) if fields[0] != "cpu_stat" { continue } From 8c6072d1112e1047484e6caafbd471cca394634e Mon Sep 17 00:00:00 2001 From: Chad Harp Date: Fri, 7 Jun 2019 07:39:57 -0500 Subject: [PATCH 3/3] Cast bytes to string --- cpu/cpu_solaris.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cpu/cpu_solaris.go b/cpu/cpu_solaris.go index 07c3106..3de0984 100644 --- a/cpu/cpu_solaris.go +++ b/cpu/cpu_solaris.go @@ -1,7 +1,6 @@ package cpu import ( - "bytes" "context" "errors" "fmt" @@ -59,7 +58,7 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) { return nil, fmt.Errorf("cannot execute kstat: %s", err) } re := regexp.MustCompile(`[:\s]+`) - for _, line := range strings.Split(bytes.NewBuffer(kstatSysOut).String(), "\n") { + for _, line := range strings.Split(string(kstatSysOut), "\n") { fields := re.Split(line, -1) if fields[0] != "cpu_stat" { continue