From b3ab1561bcc346586b6b7e884a56c99cab3f5542 Mon Sep 17 00:00:00 2001 From: xca1075 Date: Fri, 17 Jun 2022 14:53:16 +0200 Subject: [PATCH 1/2] more aix nocgo implementations --- cpu/cpu_aix_nocgo.go | 86 +++++++++++++++++++++++++++++++++++------- load/load_aix_nocgo.go | 50 +++++++++++++++++++++++- mem/mem_aix_nocgo.go | 67 +++++++++++++++++++++++++++++++- 3 files changed, 186 insertions(+), 17 deletions(-) diff --git a/cpu/cpu_aix_nocgo.go b/cpu/cpu_aix_nocgo.go index d40c40936..43dd08e29 100644 --- a/cpu/cpu_aix_nocgo.go +++ b/cpu/cpu_aix_nocgo.go @@ -5,33 +5,91 @@ package cpu import ( "context" - "fmt" + "regexp" "strings" "strconv" "github.com/shirou/gopsutil/v3/internal/common" ) +var whiteSpaces = regexp.MustCompile(`\s+`) + func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) { - return []TimesStat{}, common.ErrNotImplementedError -} + if percpu { + return []TimesStat{}, common.ErrNotImplementedError + } else { + out, err := invoke.CommandWithContext(ctx, "sar", "-u", "10", "1") + if err != nil { + return nil, err + } + lines := strings.Split(string(out), "\n") + if len(lines) < 5 { + return []TimesStat{}, common.ErrNotImplementedError + } -func InfoWithContext(ctx context.Context) ([]InfoStat, error) { - return []InfoStat{}, common.ErrNotImplementedError + ret := TimesStat{CPU: "cpu-total"} + h := whiteSpaces.Split(lines[len(lines)-3], -1) // headers + v := whiteSpaces.Split(lines[len(lines)-2], -1) // values + for i, header := range h { + if t, err := strconv.ParseUint(v[i], 10, 64); err == nil { + switch header { + case `%usr`: + ret.User = float64(t) + case `%sys`: + ret.System = float64(t) + case `%wio`: + ret.Iowait = float64(t) + case `%idle`: + ret.Idle = float64(t) + } + } + } + + return []TimesStat{ret}, nil + } } -func CountsWithContext(ctx context.Context, logical bool) (int, error) { - prtConfOut, err := invoke.CommandWithContext(ctx, "prtconf") +func InfoWithContext(ctx context.Context) ([]InfoStat, error) { + out, err := invoke.CommandWithContext(ctx, "prtconf") if err != nil { - return 0, fmt.Errorf("cannot execute prtconf: %s", err) + return nil, err } - for _, line := range strings.Split(string(prtConfOut), "\n") { - parts := strings.Split(line, ": ") - if len(parts) > 1 && parts[0] == "Number Of Processors" { - if ncpu, err := strconv.Atoi(parts[1]); err == nil { - return ncpu, nil + + ret := InfoStat{} + for _, line := range strings.Split(string(out), "\n") { + if strings.HasPrefix(line, "Number Of Processors:") { + p := whiteSpaces.Split(line, 4) + if len(p) > 3 { + if t, err := strconv.ParseUint(p[3], 10, 64); err == nil { + ret.Cores = int32(t) + } + } + } else if strings.HasPrefix(line, "Processor Clock Speed:") { + p := whiteSpaces.Split(line, 5) + if len(p) > 4 { + if t, err := strconv.ParseUint(p[3], 10, 64); err == nil { + switch strings.ToUpper(p[4]) { + case "MHZ": + ret.Mhz = float64(t) + case "GHZ": + ret.Mhz = float64(t) * 1000.0 + case "KHZ": + ret.Mhz = float64(t) / 1000.0 + default: + ret.Mhz = float64(t) + } + } } + break } } - return 0, fmt.Errorf("number of processors not found") + return []InfoStat{ret}, nil +} + +func CountsWithContext(ctx context.Context, logical bool) (int, error) { + info, err := InfoWithContext(ctx) + if err == nil { + return int(info[0].Cores), nil + } + return 0, err } diff --git a/load/load_aix_nocgo.go b/load/load_aix_nocgo.go index 7cbf8b438..bfc4850f7 100644 --- a/load/load_aix_nocgo.go +++ b/load/load_aix_nocgo.go @@ -5,14 +5,62 @@ package load import ( "context" + "regexp" + "strconv" + "strings" "github.com/shirou/gopsutil/v3/internal/common" ) +var separator = regexp.MustCompile(`,?\s+`) + func AvgWithContext(ctx context.Context) (*AvgStat, error) { + line, err := invoke.CommandWithContext(ctx, "uptime") + if err != nil { + return nil, err + } + + idx := strings.Index(string(line), "load average:") + if idx < 0 { + return nil, common.ErrNotImplementedError + } + ret := &AvgStat{} + + p := separator.Split(string(line[idx:len(line)]), 5) + if 4 < len(p) && p[0] == "load" && p[1] == "average:" { + if t, err := strconv.ParseFloat(p[2], 64); err == nil { + ret.Load1 = t + } + if t, err := strconv.ParseFloat(p[3], 64); err == nil { + ret.Load5 = t + } + if t, err := strconv.ParseFloat(p[4], 64); err == nil { + ret.Load15 = t + } + return ret, nil + } + return nil, common.ErrNotImplementedError } func MiscWithContext(ctx context.Context) (*MiscStat, error) { - return nil, common.ErrNotImplementedError + out, err := invoke.CommandWithContext(ctx, "ps", "-Ao", "state") + if err != nil { + return nil, err + } + + ret := &MiscStat{} + for _, line := range strings.Split(string(out), "\n") { + ret.ProcsTotal++ + switch line { + case "R": + case "A": + ret.ProcsRunning++ + case "T": + ret.ProcsBlocked++ + default: + continue + } + } + return ret, nil } diff --git a/mem/mem_aix_nocgo.go b/mem/mem_aix_nocgo.go index b13b635e5..09ffd8ed1 100644 --- a/mem/mem_aix_nocgo.go +++ b/mem/mem_aix_nocgo.go @@ -5,14 +5,77 @@ package mem import ( "context" + "regexp" + "strconv" + "strings" "github.com/shirou/gopsutil/v3/internal/common" ) +var whiteSpaces = regexp.MustCompile(`\s+`) + func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) { - return nil, common.ErrNotImplementedError + vmem, swap, err := callSVMon(ctx) + if err != nil { + return nil, err + } + if vmem.Total == 0 { + return nil, common.ErrNotImplementedError + } + vmem.SwapTotal = swap.Total + vmem.SwapFree = swap.Free + return vmem, nil } func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) { - return nil, common.ErrNotImplementedError + _, swap, err := callSVMon(ctx) + if err != nil { + return nil, err + } + if swap.Total == 0 { + return nil, common.ErrNotImplementedError + } + return swap, nil +} + +func callSVMon(ctx context.Context) (*VirtualMemoryStat, *SwapMemoryStat, error) { + out, err := invoke.CommandWithContext(ctx, "svmon", "-G") + if err != nil { + return nil, nil, err + } + + pagesize := uint64(4096) + vmem := &VirtualMemoryStat{} + swap := &SwapMemoryStat{} + for _, line := range strings.Split(string(out), "\n") { + if strings.HasPrefix(line, "memory") { + p := whiteSpaces.Split(line, 7) + if len(p) > 2 { + if t, err := strconv.ParseUint(p[1], 10, 64); err == nil { + vmem.Total = t * pagesize + } + if t, err := strconv.ParseUint(p[2], 10, 64); err == nil { + vmem.Used = t * pagesize + if vmem.Total > 0 { + vmem.UsedPercent = 100 * float64(vmem.Used) / float64(vmem.Total) + } + } + if t, err := strconv.ParseUint(p[3], 10, 64); err == nil { + vmem.Free = t * pagesize + } + } + } else if strings.HasPrefix(line, "pg space") { + p := whiteSpaces.Split(line, 4) + if len(p) > 3 { + if t, err := strconv.ParseUint(p[2], 10, 64); err == nil { + swap.Total = t * pagesize + } + if t, err := strconv.ParseUint(p[3], 10, 64); err == nil { + swap.Free = swap.Total - t * pagesize + } + } + break + } + } + return vmem, swap, nil } From 3d643b9b73d5b986ca1bd83637d717e1d455711e Mon Sep 17 00:00:00 2001 From: xca1075 Date: Fri, 17 Jun 2022 15:10:37 +0200 Subject: [PATCH 2/2] parse cpu values as float --- cpu/cpu_aix_nocgo.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/cpu/cpu_aix_nocgo.go b/cpu/cpu_aix_nocgo.go index 43dd08e29..d158000ea 100644 --- a/cpu/cpu_aix_nocgo.go +++ b/cpu/cpu_aix_nocgo.go @@ -31,16 +31,16 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) { h := whiteSpaces.Split(lines[len(lines)-3], -1) // headers v := whiteSpaces.Split(lines[len(lines)-2], -1) // values for i, header := range h { - if t, err := strconv.ParseUint(v[i], 10, 64); err == nil { + if t, err := strconv.ParseFloat(v[i], 64); err == nil { switch header { case `%usr`: - ret.User = float64(t) + ret.User = t case `%sys`: - ret.System = float64(t) + ret.System = t case `%wio`: - ret.Iowait = float64(t) + ret.Iowait = t case `%idle`: - ret.Idle = float64(t) + ret.Idle = t } } } @@ -67,16 +67,16 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) { } else if strings.HasPrefix(line, "Processor Clock Speed:") { p := whiteSpaces.Split(line, 5) if len(p) > 4 { - if t, err := strconv.ParseUint(p[3], 10, 64); err == nil { + if t, err := strconv.ParseFloat(p[3], 64); err == nil { switch strings.ToUpper(p[4]) { case "MHZ": - ret.Mhz = float64(t) + ret.Mhz = t case "GHZ": - ret.Mhz = float64(t) * 1000.0 + ret.Mhz = t * 1000.0 case "KHZ": - ret.Mhz = float64(t) / 1000.0 + ret.Mhz = t / 1000.0 default: - ret.Mhz = float64(t) + ret.Mhz = t } } }