From a2d4c5dcb8fa55c99d64671e636f91ba9044cadd Mon Sep 17 00:00:00 2001 From: WAKAYAMA Shirou Date: Fri, 19 Sep 2014 22:41:29 +0900 Subject: [PATCH 1/8] error handling in linux is now unsuppressed. However, so many err check is introduced. Some refactoring is needed. --- cpu_darwin.go | 45 +++++++++++++++---- cpu_linux.go | 30 ++++++++++--- disk.go | 2 +- disk_linux.go | 52 +++++++++++++++------- mem_linux.go | 36 +++++++++++++--- net_linux.go | 51 ++++++++++++++++++---- process.go | 12 +++--- process_linux.go | 128 ++++++++++++++++++++++++++++++++++++++++--------------- process_posix.go | 2 +- 9 files changed, 275 insertions(+), 83 deletions(-) diff --git a/cpu_darwin.go b/cpu_darwin.go index 8a61de0..81705fd 100644 --- a/cpu_darwin.go +++ b/cpu_darwin.go @@ -32,11 +32,26 @@ func CPUTimes(percpu bool) ([]CPUTimesStat, error) { return ret, err } - user, _ := strconv.ParseFloat(cpuTime[CPUser], 32) - nice, _ := strconv.ParseFloat(cpuTime[CPNice], 32) - sys, _ := strconv.ParseFloat(cpuTime[CPSys], 32) - idle, _ := strconv.ParseFloat(cpuTime[CPIdle], 32) - intr, _ := strconv.ParseFloat(cpuTime[CPIntr], 32) + user, err := strconv.ParseFloat(cpuTime[CPUser], 32) + if err != nil { + return ret, err + } + nice, err := strconv.ParseFloat(cpuTime[CPNice], 32) + if err != nil { + return ret, err + } + sys, err := strconv.ParseFloat(cpuTime[CPSys], 32) + if err != nil { + return ret, err + } + idle, err := strconv.ParseFloat(cpuTime[CPIdle], 32) + if err != nil { + return ret, err + } + intr, err := strconv.ParseFloat(cpuTime[CPIntr], 32) + if err != nil { + return ret, err + } c := CPUTimesStat{ User: float32(user / ClocksPerSec), @@ -71,7 +86,12 @@ func CPUInfo() ([]CPUInfoStat, error) { } else if strings.HasPrefix(line, "machdep.cpu.model") { c.Model = values[1] } else if strings.HasPrefix(line, "machdep.cpu.stepping") { - c.Stepping = mustParseInt32(values[1]) + t, err := strconv.ParseInt(values[1], 10, 32) + if err != nil { + return ret, err + } + c.Stepping = int32(t) + } else if strings.HasPrefix(line, "machdep.cpu.features") { for _, v := range values[1:] { c.Flags = append(c.Flags, strings.ToLower(v)) @@ -85,9 +105,18 @@ func CPUInfo() ([]CPUInfoStat, error) { c.Flags = append(c.Flags, strings.ToLower(v)) } } else if strings.HasPrefix(line, "machdep.cpu.core_count") { - c.Cores = mustParseInt32(values[1]) + t, err := strconv.ParseInt(values[1], 10, 32) + if err != nil { + return ret, err + } + c.Cores = t } else if strings.HasPrefix(line, "machdep.cpu.cache.size") { - c.CacheSize = mustParseInt32(values[1]) + t, err := strconv.ParseInt(values[1], 10, 32) + if err != nil { + return ret, err + } + + c.CacheSize = t } else if strings.HasPrefix(line, "machdep.cpu.vendor") { c.VendorID = values[1] } diff --git a/cpu_linux.go b/cpu_linux.go index 5ec5f88..ada85e6 100644 --- a/cpu_linux.go +++ b/cpu_linux.go @@ -46,7 +46,11 @@ func CPUInfo() ([]CPUInfoStat, error) { switch key { case "processor": c = CPUInfoStat{} - c.CPU = mustParseInt32(value) + t, err := strconv.ParseInt(value, 10, 32) + if err != nil { + return ret, err + } + c.CPU = int32(t) case "vendor_id": c.VendorID = value case "cpu family": @@ -56,17 +60,33 @@ func CPUInfo() ([]CPUInfoStat, error) { case "model name": c.ModelName = value case "stepping": - c.Stepping = mustParseInt32(value) + t, err := strconv.ParseInt(value, 10, 32) + if err != nil { + return ret, err + } + c.Stepping = int32(t) case "cpu MHz": - c.Mhz = mustParseFloat64(value) + t, err := strconv.ParseFloat(value, 64) + if err != nil { + return ret, err + } + c.Mhz = t case "cache size": - c.CacheSize = mustParseInt32(strings.Replace(value, " KB", "", 1)) + t, err := strconv.ParseInt(strings.Replace(value, " KB", "", 1), 10, 32) + if err != nil { + return ret, err + } + c.CacheSize = int32(t) case "physical id": c.PhysicalID = value case "core id": c.CoreID = value case "cpu cores": - c.Cores = mustParseInt32(value) + t, err := strconv.ParseInt(value, 10, 32) + if err != nil { + return ret, err + } + c.Cores = int32(t) case "flags": c.Flags = strings.Split(value, ",") } diff --git a/disk.go b/disk.go index ae54a0b..a76771e 100644 --- a/disk.go +++ b/disk.go @@ -31,7 +31,7 @@ type DiskIOCountersStat struct { ReadTime uint64 `json:"readTime"` WriteTime uint64 `json:"writeTime"` Name string `json:"name"` - IoTime uint64 `json:"ioTime"` + IoTime uint64 `json:"ioTime"` } func (d DiskUsageStat) String() string { diff --git a/disk_linux.go b/disk_linux.go index 1e33c5f..81e4811 100644 --- a/disk_linux.go +++ b/disk_linux.go @@ -3,6 +3,7 @@ package gopsutil import ( + "strconv" "strings" ) @@ -25,7 +26,7 @@ func DiskPartitions(all bool) ([]DiskPartitionStat, error) { for _, line := range lines { fields := strings.Fields(line) d := DiskPartitionStat{ - Device: fields[0], + Device: fields[0], Mountpoint: fields[1], Fstype: fields[2], Opts: fields[3], @@ -48,21 +49,42 @@ func DiskIOCounters() (map[string]DiskIOCountersStat, error) { for _, line := range lines { fields := strings.Fields(line) name := fields[2] - reads := mustParseUint64(fields[3]) - rbytes := mustParseUint64(fields[5]) - rtime := mustParseUint64(fields[6]) - writes := mustParseUint64(fields[7]) - wbytes := mustParseUint64(fields[9]) - wtime := mustParseUint64(fields[10]) - iotime := mustParseUint64(fields[12]) + reads, err := strconv.ParseUint((fields[3]), 10, 64) + if err != nil { + return ret, err + } + rbytes, err := strconv.ParseUint((fields[5]), 10, 64) + if err != nil { + return ret, err + } + rtime, err := strconv.ParseUint((fields[6]), 10, 64) + if err != nil { + return ret, err + } + writes, err := strconv.ParseUint((fields[7]), 10, 64) + if err != nil { + return ret, err + } + wbytes, err := strconv.ParseUint((fields[9]), 10, 64) + if err != nil { + return ret, err + } + wtime, err := strconv.ParseUint((fields[10]), 10, 64) + if err != nil { + return ret, err + } + iotime, err := strconv.ParseUint((fields[12]), 10, 64) + if err != nil { + return ret, err + } d := DiskIOCountersStat{ - ReadBytes: rbytes * SectorSize, - WriteBytes: wbytes * SectorSize, - ReadCount: reads, - WriteCount: writes, - ReadTime: rtime, - WriteTime: wtime, - IoTime: iotime, + ReadBytes: uint64(rbytes) * SectorSize, + WriteBytes: uint64(wbytes) * SectorSize, + ReadCount: uint64(reads), + WriteCount: uint64(writes), + ReadTime: uint64(rtime), + WriteTime: uint64(wtime), + IoTime: uint64(iotime), } if d == empty { continue diff --git a/mem_linux.go b/mem_linux.go index 9163a01..e2fa8fb 100644 --- a/mem_linux.go +++ b/mem_linux.go @@ -3,6 +3,7 @@ package gopsutil import ( + "strconv" "strings" "syscall" ) @@ -24,17 +25,42 @@ func VirtualMemory() (*VirtualMemoryStat, error) { switch key { case "MemTotal": ret.Total = mustParseUint64(value) * 1000 + t, err := strconv.ParseInt(value, 10, 64) + if err != nil { + return ret, err + } + ret.Total = uint64(t) * 1000 case "MemFree": ret.Free = mustParseUint64(value) * 1000 + t, err := strconv.ParseInt(value, 10, 64) + if err != nil { + return ret, err + } + ret.Free = uint64(t) * 1000 case "Buffers": - ret.Buffers = mustParseUint64(value) * 1000 + t, err := strconv.ParseInt(value, 10, 64) + if err != nil { + return ret, err + } + ret.Buffers = uint64(t) * 1000 case "Cached": - ret.Cached = mustParseUint64(value) * 1000 + t, err := strconv.ParseInt(value, 10, 64) + if err != nil { + return ret, err + } + ret.Cached = uint64(t) * 1000 case "Active": - ret.Active = mustParseUint64(value) * 1000 + t, err := strconv.ParseInt(value, 10, 64) + if err != nil { + return ret, err + } + ret.Active = uint64(t) * 1000 case "Inactive": - ret.Inactive = mustParseUint64(value) * 1000 - + t, err := strconv.ParseInt(value, 10, 64) + if err != nil { + return ret, err + } + ret.Inactive = uint64(t) * 1000 } } ret.Available = ret.Free + ret.Buffers + ret.Cached diff --git a/net_linux.go b/net_linux.go index 9790337..9cc38ae 100644 --- a/net_linux.go +++ b/net_linux.go @@ -3,6 +3,7 @@ package gopsutil import ( + "strconv" "strings" ) @@ -22,16 +23,50 @@ func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) { if fields[0] == "" { continue } + + bytesRecv, err := strconv.ParseUint(fields[1], 10, 64) + if err != nil { + return ret, err + } + packetsRecv, err := strconv.ParseUint(fields[2], 10, 64) + if err != nil { + return ret, err + } + errIn, err := strconv.ParseUint(fields[3], 10, 64) + if err != nil { + return ret, err + } + dropIn, err := strconv.ParseUint(fields[4], 10, 64) + if err != nil { + return ret, err + } + bytesSent, err := strconv.ParseUint(fields[9], 10, 64) + if err != nil { + return ret, err + } + packetsSent, err := strconv.ParseUint(fields[10], 10, 64) + if err != nil { + return ret, err + } + errOut, err := strconv.ParseUint(fields[11], 10, 64) + if err != nil { + return ret, err + } + dropOut, err := strconv.ParseUint(fields[14], 10, 64) + if err != nil { + return ret, err + } + nic := NetIOCountersStat{ Name: strings.Trim(fields[0], ":"), - BytesRecv: mustParseUint64(fields[1]), - PacketsRecv: mustParseUint64(fields[2]), - Errin: mustParseUint64(fields[3]), - Dropin: mustParseUint64(fields[4]), - BytesSent: mustParseUint64(fields[9]), - PacketsSent: mustParseUint64(fields[10]), - Errout: mustParseUint64(fields[11]), - Dropout: mustParseUint64(fields[12]), + BytesRecv: bytesRecv, + PacketsRecv: packetsRecv, + Errin: errIn, + Dropin: dropIn, + BytesSent: bytesSent, + PacketsSent: packetsSent, + Errout: errOut, + Dropout: dropOut, } ret = append(ret, nic) } diff --git a/process.go b/process.go index 8ad2071..aaade8b 100644 --- a/process.go +++ b/process.go @@ -5,13 +5,13 @@ import ( ) type Process struct { - Pid int32 `json:"pid"` - name string - status string + Pid int32 `json:"pid"` + name string + status string numCtxSwitches *NumCtxSwitchesStat - uids []int32 - gids []int32 - numThreads int32 + uids []int32 + gids []int32 + numThreads int32 } type OpenFilesStat struct { diff --git a/process_linux.go b/process_linux.go index 8e60793..ad088bf 100644 --- a/process_linux.go +++ b/process_linux.go @@ -195,7 +195,7 @@ func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) { lines := strings.Split(string(contents), "\n") // function of parsing a block - getBlock := func(first_line []string, block []string) MemoryMapsStat { + getBlock := func(first_line []string, block []string) (MemoryMapsStat, error) { m := MemoryMapsStat{} m.Path = first_line[len(first_line)-1] @@ -205,30 +205,35 @@ func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) { continue } v := strings.Trim(field[1], " kB") // remove last "kB" + t, err := strconv.ParseUint(v, 10, 64) + if err != nil { + return m, err + } + switch field[0] { case "Size": - m.Size = mustParseUint64(v) + m.Size = t case "Rss": - m.Rss = mustParseUint64(v) + m.Rss = t case "Pss": - m.Pss = mustParseUint64(v) + m.Pss = t case "Shared_Clean": - m.SharedClean = mustParseUint64(v) + m.SharedClean = t case "Shared_Dirty": - m.SharedDirty = mustParseUint64(v) + m.SharedDirty = t case "Private_Clean": - m.PrivateClean = mustParseUint64(v) + m.PrivateClean = t case "Private_Dirty": - m.PrivateDirty = mustParseUint64(v) + m.PrivateDirty = t case "Referenced": - m.Referenced = mustParseUint64(v) + m.Referenced = t case "Anonymous": - m.Anonymous = mustParseUint64(v) + m.Anonymous = t case "Swap": - m.Swap = mustParseUint64(v) + m.Swap = t } } - return m + return m, nil } blocks := make([]string, 16) @@ -237,7 +242,11 @@ func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) { if strings.HasSuffix(field[0], ":") == false { // new block section if len(blocks) > 0 { - ret = append(ret, getBlock(field, blocks)) + g, err := getBlock(field, blocks) + if err != nil { + return &ret, err + } + ret = append(ret, g) } // starts new block blocks = make([]string, 16) @@ -272,9 +281,13 @@ func (p *Process) fillFromfd() (int32, []*OpenFilesStat, error) { if err != nil { continue } + t, err := strconv.ParseUint(fd, 10, 64) + if err != nil { + return numFDs, openfiles, err + } o := &OpenFilesStat{ Path: filepath, - Fd: mustParseUint64(fd), + Fd: t, } openfiles = append(openfiles, o) } @@ -338,15 +351,20 @@ func (p *Process) fillFromIO() (*IOCountersStat, error) { if len(field) < 2 { continue } + t, err := strconv.ParseInt(strings.Trim(field[1], " \t"), 10, 32) + if err != nil { + return nil, err + } + switch field[0] { case "rchar": - ret.ReadCount = mustParseInt32(strings.Trim(field[1], " \t")) + ret.ReadCount = int32(t) case "wchar": - ret.WriteCount = mustParseInt32(strings.Trim(field[1], " \t")) + ret.WriteCount = int32(t) case "read_bytes": - ret.ReadBytes = mustParseInt32(strings.Trim(field[1], " \t")) + ret.ReadBytes = int32(t) case "write_bytes": - ret.WriteBytes = mustParseInt32(strings.Trim(field[1], " \t")) + ret.WriteBytes = int32(t) } } @@ -363,19 +381,43 @@ func (p *Process) fillFromStatm() (*MemoryInfoStat, *MemoryInfoExStat, error) { } fields := strings.Split(string(contents), " ") - vms := mustParseUint64(fields[0]) * PageSize - rss := mustParseUint64(fields[1]) * PageSize + vms, err := strconv.ParseUint(fields[0], 10, 64) + if err != nil { + return nil, nil, err + } + rss, err := strconv.ParseUint(fields[1], 10, 64) + if err != nil { + return nil, nil, err + } memInfo := &MemoryInfoStat{ - RSS: rss, - VMS: vms, + RSS: rss * PageSize, + VMS: vms * PageSize, + } + + shared, err := strconv.ParseUint(fields[2], 10, 64) + if err != nil { + return nil, nil, err + } + text, err := strconv.ParseUint(fields[3], 10, 64) + if err != nil { + return nil, nil, err } + lib, err := strconv.ParseUint(fields[4], 10, 64) + if err != nil { + return nil, nil, err + } + dirty, err := strconv.ParseUint(fields[5], 10, 64) + if err != nil { + return nil, nil, err + } + memInfoEx := &MemoryInfoExStat{ - RSS: rss, - VMS: vms, - Shared: mustParseUint64(fields[2]) * PageSize, - Text: mustParseUint64(fields[3]) * PageSize, - Lib: mustParseUint64(fields[4]) * PageSize, - Dirty: mustParseUint64(fields[5]) * PageSize, + RSS: rss * PageSize, + VMS: vms * PageSize, + Shared: shared * PageSize, + Text: text * PageSize, + Lib: lib * PageSize, + Dirty: dirty * PageSize, } return memInfo, memInfoEx, nil @@ -458,12 +500,25 @@ func (p *Process) fillFromStat() (string, int32, *CPUTimesStat, int64, int32, er termmap, err := getTerminalMap() terminal := "" if err == nil { - terminal = termmap[mustParseUint64(fields[6])] + t, err := strconv.ParseUint(fields[6], 10, 64) + if err != nil { + return "", 0, nil, 0, 0, err + } + terminal = termmap[t] } - ppid := mustParseInt32(fields[3]) - utime, _ := strconv.ParseFloat(fields[13], 64) - stime, _ := strconv.ParseFloat(fields[14], 64) + ppid, err := strconv.ParseInt(fields[3], 10, 32) + if err != nil { + return "", 0, nil, 0, 0, err + } + utime, err := strconv.ParseFloat(fields[13], 64) + if err != nil { + return "", 0, nil, 0, 0, err + } + stime, err := strconv.ParseFloat(fields[14], 64) + if err != nil { + return "", 0, nil, 0, 0, err + } cpuTimes := &CPUTimesStat{ CPU: "cpu", @@ -472,7 +527,12 @@ func (p *Process) fillFromStat() (string, int32, *CPUTimesStat, int64, int32, er } bootTime, _ := BootTime() - ctime := ((mustParseUint64(fields[21]) / uint64(ClockTicks)) + uint64(bootTime)) * 1000 + t, err := strconv.ParseUint(fields[21], 10, 64) + if err != nil { + return "", 0, nil, 0, 0, err + } + + ctime := ((t / uint64(ClockTicks)) + uint64(bootTime)) * 1000 createTime := int64(ctime) // p.Nice = mustParseInt32(fields[18]) @@ -480,7 +540,7 @@ func (p *Process) fillFromStat() (string, int32, *CPUTimesStat, int64, int32, er snice, _ := syscall.Getpriority(PrioProcess, int(pid)) nice := int32(snice) // FIXME: is this true? - return terminal, ppid, cpuTimes, createTime, nice, nil + return terminal, int32(ppid), cpuTimes, createTime, nice, nil } func Pids() ([]int32, error) { diff --git a/process_posix.go b/process_posix.go index 1514dc7..4e2625a 100644 --- a/process_posix.go +++ b/process_posix.go @@ -4,8 +4,8 @@ package gopsutil import ( "os" - "os/user" "os/exec" + "os/user" "strconv" "strings" "syscall" From 90b8a2160be1d59f89061c5cf8536af9782ca589 Mon Sep 17 00:00:00 2001 From: WAKAYAMA shirou Date: Sat, 20 Sep 2014 00:15:35 +0900 Subject: [PATCH 2/8] remove mustParse on frebsd. --- cpu_freebsd.go | 18 ++++++++-- host_freebsd.go | 6 +++- mem_freebsd.go | 101 +++++++++++++++++++++++++++++++++++++++++++++----------- mem_test.go | 1 - net_freebsd.go | 41 ++++++++++++++++++----- 5 files changed, 134 insertions(+), 33 deletions(-) diff --git a/cpu_freebsd.go b/cpu_freebsd.go index c576852..4657702 100644 --- a/cpu_freebsd.go +++ b/cpu_freebsd.go @@ -62,12 +62,20 @@ func CPUInfo() ([]CPUInfoStat, error) { for _, line := range lines { if matches := regexp.MustCompile(`CPU:\s+(.+) \(([\d.]+).+\)`).FindStringSubmatch(line); matches != nil { c.ModelName = matches[1] - c.Mhz = mustParseFloat64(matches[2]) + t, err := strconv.ParseFloat(matches[2], 64) + if err != nil { + return ret, nil + } + c.Mhz = t } else if matches := regexp.MustCompile(`Origin = "(.+)" Id = (.+) Family = (.+) Model = (.+) Stepping = (.+)`).FindStringSubmatch(line); matches != nil { c.VendorID = matches[1] c.Family = matches[3] c.Model = matches[4] - c.Stepping = mustParseInt32(matches[5]) + t, err := strconv.ParseInt(matches[5], 10, 32) + if err != nil { + return ret, nil + } + c.Stepping = int32(t) } else if matches := regexp.MustCompile(`Features=.+<(.+)>`).FindStringSubmatch(line); matches != nil { for _, v := range strings.Split(matches[1], ",") { c.Flags = append(c.Flags, strings.ToLower(v)) @@ -78,7 +86,11 @@ func CPUInfo() ([]CPUInfoStat, error) { } } else if matches := regexp.MustCompile(`Logical CPUs per core: (\d+)`).FindStringSubmatch(line); matches != nil { // FIXME: no this line? - c.Cores = mustParseInt32(matches[1]) + t, err := strconv.ParseInt(matches[1], 10, 32) + if err != nil { + return ret, nil + } + c.Cores = int32(t) } } diff --git a/host_freebsd.go b/host_freebsd.go index bb8bdb7..71f2d5f 100644 --- a/host_freebsd.go +++ b/host_freebsd.go @@ -42,7 +42,11 @@ func HostInfo() (*HostInfoStat, error) { if err == nil { // ex: { sec = 1392261637, usec = 627534 } Thu Feb 13 12:20:37 2014 v := strings.Replace(values[2], ",", "", 1) - ret.Uptime = mustParseUint64(v) + t, err := strconv.ParseUint(v, 10, 64) + if err != nil { + return ret, err + } + ret.Uptime = t } return ret, nil diff --git a/mem_freebsd.go b/mem_freebsd.go index f3851c1..4f70ec4 100644 --- a/mem_freebsd.go +++ b/mem_freebsd.go @@ -4,30 +4,75 @@ package gopsutil import ( "os/exec" + "strconv" "strings" ) func VirtualMemory() (*VirtualMemoryStat, error) { + pageSize, err := doSysctrl("vm.stats.vm.v_page_size") + if err != nil { + return nil, err + } + p, err := strconv.ParseUint(pageSize[0], 10, 64) + if err != nil { + return nil, err + } - pageSize, _ := doSysctrl("vm.stats.vm.v_page_size") - p := mustParseUint64(pageSize[0]) + pageCount, err := doSysctrl("vm.stats.vm.v_page_count") + if err != nil { + return nil, err + } + free, err := doSysctrl("vm.stats.vm.v_free_count") + if err != nil { + return nil, err + } + active, err := doSysctrl("vm.stats.vm.v_active_count") + if err != nil { + return nil, err + } + inactive, err := doSysctrl("vm.stats.vm.v_inactive_count") + if err != nil { + return nil, err + } + cache, err := doSysctrl("vm.stats.vm.v_cache_count") + if err != nil { + return nil, err + } + buffer, err := doSysctrl("vfs.bufspace") + if err != nil { + return nil, err + } + wired, err := doSysctrl("vm.stats.vm.v_wire_count") + if err != nil { + return nil, err + } - pageCount, _ := doSysctrl("vm.stats.vm.v_page_count") - free, _ := doSysctrl("vm.stats.vm.v_free_count") - active, _ := doSysctrl("vm.stats.vm.v_active_count") - inactive, _ := doSysctrl("vm.stats.vm.v_inactive_count") - cache, _ := doSysctrl("vm.stats.vm.v_cache_count") - buffer, _ := doSysctrl("vfs.bufspace") - wired, _ := doSysctrl("vm.stats.vm.v_wire_count") + parsed := make([]uint64, 0, 7) + vv := []string{ + pageCount[0], + free[0], + active[0], + inactive[0], + cache[0], + buffer[0], + wired[0], + } + for _, target := range vv { + t, err := strconv.ParseUint(target, 10, 64) + if err != nil { + return nil, err + } + parsed = append(parsed, t) + } ret := &VirtualMemoryStat{ - Total: mustParseUint64(pageCount[0]) * p, - Free: mustParseUint64(free[0]) * p, - Active: mustParseUint64(active[0]) * p, - Inactive: mustParseUint64(inactive[0]) * p, - Cached: mustParseUint64(cache[0]) * p, - Buffers: mustParseUint64(buffer[0]), - Wired: mustParseUint64(wired[0]) * p, + Total: parsed[0] * p, + Free: parsed[1] * p, + Active: parsed[2] * p, + Inactive: parsed[3] * p, + Cached: parsed[4] * p, + Buffers: parsed[5], + Wired: parsed[6] * p, } // TODO: platform independent (worked freebsd?) @@ -55,12 +100,28 @@ func SwapMemory() (*SwapMemoryStat, error) { } u := strings.Replace(values[4], "%", "", 1) + total_v, err := strconv.ParseUint(values[1], 10, 64) + if err != nil { + return nil, err + } + used_v, err := strconv.ParseUint(values[2], 10, 64) + if err != nil { + return nil, err + } + free_v, err := strconv.ParseUint(values[3], 10, 64) + if err != nil { + return nil, err + } + up_v, err := strconv.ParseFloat(u, 64) + if err != nil { + return nil, err + } ret = &SwapMemoryStat{ - Total: mustParseUint64(values[1]), - Used: mustParseUint64(values[2]), - Free: mustParseUint64(values[3]), - UsedPercent: mustParseFloat64(u), + Total: total_v, + Used: used_v, + Free: free_v, + UsedPercent: up_v, } } diff --git a/mem_test.go b/mem_test.go index 7d66550..5631bdf 100644 --- a/mem_test.go +++ b/mem_test.go @@ -10,7 +10,6 @@ func TestVirtual_memory(t *testing.T) { if err != nil { t.Errorf("error %v", err) } - empty := &VirtualMemoryStat{} if v == empty { t.Errorf("error %v", v) diff --git a/net_freebsd.go b/net_freebsd.go index 27257c9..bb1bd53 100644 --- a/net_freebsd.go +++ b/net_freebsd.go @@ -4,6 +4,7 @@ package gopsutil import ( "os/exec" + "strconv" "strings" ) @@ -27,16 +28,40 @@ func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) { base = 0 } + parsed := make([]uint64, 0, 8) + vv := []string{ + values[base+3], // PacketsRecv + values[base+4], // Errin + values[base+5], // Dropin + values[base+6], // BytesRecvn + values[base+7], // PacketSent + values[base+8], // Errout + values[base+9], // BytesSent + values[base+11], // Dropout + } + for _, target := range vv { + if target == "-" { + parsed = append(parsed, 0) + continue + } + + t, err := strconv.ParseUint(target, 10, 64) + if err != nil { + return nil, err + } + parsed = append(parsed, t) + } + n := NetIOCountersStat{ Name: values[0], - PacketsRecv: mustParseUint64(values[base+3]), - Errin: mustParseUint64(values[base+4]), - Dropin: mustParseUint64(values[base+5]), - BytesRecv: mustParseUint64(values[base+6]), - PacketsSent: mustParseUint64(values[base+7]), - Errout: mustParseUint64(values[base+8]), - BytesSent: mustParseUint64(values[base+9]), - Dropout: mustParseUint64(values[base+11]), + PacketsRecv: parsed[0], + Errin: parsed[1], + Dropin: parsed[2], + BytesRecv: parsed[3], + PacketsSent: parsed[4], + Errout: parsed[5], + BytesSent: parsed[6], + Dropout: parsed[7], } ret = append(ret, n) } From b2dc5698851f2162a927daea4b3523e5e08c253a Mon Sep 17 00:00:00 2001 From: WAKAYAMA Shirou Date: Sat, 20 Sep 2014 00:21:26 +0900 Subject: [PATCH 3/8] refactoring. --- disk_linux.go | 14 +++++++------- mem_linux.go | 42 ++++++++++-------------------------------- 2 files changed, 17 insertions(+), 39 deletions(-) diff --git a/disk_linux.go b/disk_linux.go index 81e4811..bfcc9f1 100644 --- a/disk_linux.go +++ b/disk_linux.go @@ -78,13 +78,13 @@ func DiskIOCounters() (map[string]DiskIOCountersStat, error) { return ret, err } d := DiskIOCountersStat{ - ReadBytes: uint64(rbytes) * SectorSize, - WriteBytes: uint64(wbytes) * SectorSize, - ReadCount: uint64(reads), - WriteCount: uint64(writes), - ReadTime: uint64(rtime), - WriteTime: uint64(wtime), - IoTime: uint64(iotime), + ReadBytes: rbytes * SectorSize, + WriteBytes: wbytes * SectorSize, + ReadCount: reads, + WriteCount: writes, + ReadTime: rtime, + WriteTime: wtime, + IoTime: iotime, } if d == empty { continue diff --git a/mem_linux.go b/mem_linux.go index e2fa8fb..2cb8911 100644 --- a/mem_linux.go +++ b/mem_linux.go @@ -22,45 +22,23 @@ func VirtualMemory() (*VirtualMemoryStat, error) { value := strings.TrimSpace(fields[1]) value = strings.Replace(value, " kB", "", -1) + t, err := strconv.ParseUint(value, 10, 64) + if err != nil { + return ret, err + } switch key { case "MemTotal": - ret.Total = mustParseUint64(value) * 1000 - t, err := strconv.ParseInt(value, 10, 64) - if err != nil { - return ret, err - } - ret.Total = uint64(t) * 1000 + ret.Total = t * 1000 case "MemFree": - ret.Free = mustParseUint64(value) * 1000 - t, err := strconv.ParseInt(value, 10, 64) - if err != nil { - return ret, err - } - ret.Free = uint64(t) * 1000 + ret.Free = t * 1000 case "Buffers": - t, err := strconv.ParseInt(value, 10, 64) - if err != nil { - return ret, err - } - ret.Buffers = uint64(t) * 1000 + ret.Buffers = t * 1000 case "Cached": - t, err := strconv.ParseInt(value, 10, 64) - if err != nil { - return ret, err - } - ret.Cached = uint64(t) * 1000 + ret.Cached = t * 1000 case "Active": - t, err := strconv.ParseInt(value, 10, 64) - if err != nil { - return ret, err - } - ret.Active = uint64(t) * 1000 + ret.Active = t * 1000 case "Inactive": - t, err := strconv.ParseInt(value, 10, 64) - if err != nil { - return ret, err - } - ret.Inactive = uint64(t) * 1000 + ret.Inactive = t * 1000 } } ret.Available = ret.Free + ret.Buffers + ret.Cached From f53c6828234d88c3ae0797c7646a7b07a94dd10f Mon Sep 17 00:00:00 2001 From: Shirou WAKAYAMA Date: Sat, 20 Sep 2014 09:30:14 +0900 Subject: [PATCH 4/8] fix darwin mem_swap parse error. --- mem_darwin.go | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/mem_darwin.go b/mem_darwin.go index eb5f7ec..bd59ed1 100644 --- a/mem_darwin.go +++ b/mem_darwin.go @@ -4,6 +4,7 @@ package gopsutil import ( "os/exec" + "strconv" "strings" ) @@ -53,21 +54,38 @@ func VirtualMemory() (*VirtualMemoryStat, error) { // SwapMemory returns swapinfo. func SwapMemory() (*SwapMemoryStat, error) { - swapUsage, _ := doSysctrl("vm.swapusage") - var ret *SwapMemoryStat - total := strings.Replace(swapUsage[3], "M", "", 1) - used := strings.Replace(swapUsage[6], "M", "", 1) - free := strings.Replace(swapUsage[9], "M", "", 1) + swapUsage, err := doSysctrl("vm.swapusage") + if err != nil { + return ret, err + } + + total := strings.Replace(swapUsage[2], "M", "", 1) + used := strings.Replace(swapUsage[5], "M", "", 1) + free := strings.Replace(swapUsage[8], "M", "", 1) + + total_v, err := strconv.ParseFloat(total, 64) + if err != nil { + return nil, err + } + used_v, err := strconv.ParseFloat(used, 64) + if err != nil { + return nil, err + } + free_v, err := strconv.ParseFloat(free, 64) + if err != nil { + return nil, err + } - u := "0" + u := ((total_v - free_v) / total_v) * 100.0 + // vm.swapusage shows "M", multiply 1000 ret = &SwapMemoryStat{ - Total: mustParseUint64(total), - Used: mustParseUint64(used), - Free: mustParseUint64(free), - UsedPercent: mustParseFloat64(u), + Total: uint64(total_v * 1000), + Used: uint64(used_v * 1000), + Free: uint64(free_v * 1000), + UsedPercent: u, } return ret, nil From b9702ac2660056b5f33998978619008fc9deaaa9 Mon Sep 17 00:00:00 2001 From: Shirou WAKAYAMA Date: Sat, 20 Sep 2014 09:37:02 +0900 Subject: [PATCH 5/8] fix getPagesize parse error. --- mem_darwin.go | 54 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/mem_darwin.go b/mem_darwin.go index bd59ed1..afeea81 100644 --- a/mem_darwin.go +++ b/mem_darwin.go @@ -13,34 +13,46 @@ func getPageSize() (uint64, error) { if err != nil { return 0, err } - p := mustParseUint64(string(out)) + o := strings.TrimSpace(string(out)) + p, err := strconv.ParseUint(o, 10, 64) + if err != nil { + return 0, err + } + return p, nil } // VirtualMemory returns VirtualmemoryStat. func VirtualMemory() (*VirtualMemoryStat, error) { - p, _ := getPageSize() - - total, _ := doSysctrl("hw.memsize") - free, _ := doSysctrl("vm.page_free_count") - /* - active, _ := doSysctrl("vm.stats.vm.v_active_count") - inactive, _ := doSysctrl("vm.pageout_inactive_used") - cache, _ := doSysctrl("vm.stats.vm.v_cache_count") - buffer, _ := doSysctrl("vfs.bufspace") - wired, _ := doSysctrl("vm.stats.vm.v_wire_count") - */ + p, err := getPageSize() + if err != nil { + return nil, err + } + + total, err := doSysctrl("hw.memsize") + if err != nil { + return nil, err + } + free, err := doSysctrl("vm.page_free_count") + if err != nil { + return nil, err + } + parsed := make([]uint64, 0, 7) + vv := []string{ + total[0], + free[0], + } + for _, target := range vv { + t, err := strconv.ParseUint(target, 10, 64) + if err != nil { + return nil, err + } + parsed = append(parsed, t) + } ret := &VirtualMemoryStat{ - Total: mustParseUint64(total[0]) * p, - Free: mustParseUint64(free[0]) * p, - /* - Active: mustParseUint64(active[0]) * p, - Inactive: mustParseUint64(inactive[0]) * p, - Cached: mustParseUint64(cache[0]) * p, - Buffers: mustParseUint64(buffer[0]), - Wired: mustParseUint64(wired[0]) * p, - */ + Total: parsed[0] * p, + Free: parsed[1] * p, } // TODO: platform independent (worked freebsd?) From 2cc43216361358a560331e9212538475cb322ba7 Mon Sep 17 00:00:00 2001 From: Shirou WAKAYAMA Date: Sat, 20 Sep 2014 10:16:30 +0900 Subject: [PATCH 6/8] fix darwin netstat format parsing error. --- net_darwin.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net_darwin.go b/net_darwin.go index 66657b8..e24c6ad 100644 --- a/net_darwin.go +++ b/net_darwin.go @@ -23,7 +23,7 @@ func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) { } base := 1 // sometimes Address is ommitted - if len(values) < 13 { + if len(values) < 11 { base = 0 } From a7a157d0f7660b80b91e2f02a8d47110a9745c63 Mon Sep 17 00:00:00 2001 From: Shirou WAKAYAMA Date: Sat, 20 Sep 2014 10:17:00 +0900 Subject: [PATCH 7/8] remove "mustParse" function on darwin. --- cpu_darwin.go | 22 ++++++---------------- host_darwin.go | 6 +++++- net_darwin.go | 34 ++++++++++++++++++++++++---------- 3 files changed, 35 insertions(+), 27 deletions(-) diff --git a/cpu_darwin.go b/cpu_darwin.go index 81705fd..abc8dc9 100644 --- a/cpu_darwin.go +++ b/cpu_darwin.go @@ -79,6 +79,10 @@ func CPUInfo() ([]CPUInfoStat, error) { for _, line := range strings.Split(string(out), "\n") { values := strings.Fields(line) + t, err := strconv.ParseInt(values[1], 10, 32) + if err != nil { + return ret, err + } if strings.HasPrefix(line, "machdep.cpu.brand_string") { c.ModelName = strings.Join(values[1:], " ") } else if strings.HasPrefix(line, "machdep.cpu.family") { @@ -86,12 +90,7 @@ func CPUInfo() ([]CPUInfoStat, error) { } else if strings.HasPrefix(line, "machdep.cpu.model") { c.Model = values[1] } else if strings.HasPrefix(line, "machdep.cpu.stepping") { - t, err := strconv.ParseInt(values[1], 10, 32) - if err != nil { - return ret, err - } c.Stepping = int32(t) - } else if strings.HasPrefix(line, "machdep.cpu.features") { for _, v := range values[1:] { c.Flags = append(c.Flags, strings.ToLower(v)) @@ -105,18 +104,9 @@ func CPUInfo() ([]CPUInfoStat, error) { c.Flags = append(c.Flags, strings.ToLower(v)) } } else if strings.HasPrefix(line, "machdep.cpu.core_count") { - t, err := strconv.ParseInt(values[1], 10, 32) - if err != nil { - return ret, err - } - c.Cores = t + c.Cores = int32(t) } else if strings.HasPrefix(line, "machdep.cpu.cache.size") { - t, err := strconv.ParseInt(values[1], 10, 32) - if err != nil { - return ret, err - } - - c.CacheSize = t + c.CacheSize = int32(t) } else if strings.HasPrefix(line, "machdep.cpu.vendor") { c.VendorID = values[1] } diff --git a/host_darwin.go b/host_darwin.go index db09f8c..c666dea 100644 --- a/host_darwin.go +++ b/host_darwin.go @@ -60,7 +60,11 @@ func HostInfo() (*HostInfoStat, error) { if err == nil { // ex: { sec = 1392261637, usec = 627534 } Thu Feb 13 12:20:37 2014 v := strings.Replace(values[2], ",", "", 1) - ret.Uptime = mustParseUint64(v) + t, err := strconv.ParseUint(v, 10, 64) + if err != nil { + return ret, err + } + ret.Uptime = t } return ret, nil diff --git a/net_darwin.go b/net_darwin.go index e24c6ad..d65e116 100644 --- a/net_darwin.go +++ b/net_darwin.go @@ -4,6 +4,7 @@ package gopsutil import ( "os/exec" + "strconv" "strings" ) @@ -19,6 +20,7 @@ func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) { for _, line := range lines { values := strings.Fields(line) if len(values) < 1 || values[0] == "Name" { + // skip first line continue } base := 1 @@ -27,18 +29,30 @@ func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) { base = 0 } + parsed := make([]uint64, 0, 3) + vv := []string{ + values[base+3], // PacketsRecv + values[base+4], // Errin + values[base+5], // Dropin + } + for _, target := range vv { + if target == "-" { + parsed = append(parsed, 0) + continue + } + + t, err := strconv.ParseUint(target, 10, 64) + if err != nil { + return nil, err + } + parsed = append(parsed, t) + } + n := NetIOCountersStat{ Name: values[0], - PacketsRecv: mustParseUint64(values[base+3]), - Errin: mustParseUint64(values[base+4]), - Dropin: mustParseUint64(values[base+5]), - /* - BytesRecv: mustParseUint64(values[base+6]), - PacketsSent: mustParseUint64(values[base+7]), - Errout: mustParseUint64(values[base+8]), - BytesSent: mustParseUint64(values[base+9]), - Dropout: mustParseUint64(values[base+11]), - */ + PacketsRecv: parsed[0], + Errin: parsed[1], + Dropin: parsed[2], } ret = append(ret, n) } From 9beacb51c5f26abad48a6627946343f00bafb04d Mon Sep 17 00:00:00 2001 From: WAKAYAMA shirou Date: Sat, 20 Sep 2014 10:22:41 +0900 Subject: [PATCH 8/8] fix error handling. --- cpu_freebsd.go | 25 ++++++++++++++++++++----- cpu_linux.go | 55 ++++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 64 insertions(+), 16 deletions(-) diff --git a/cpu_freebsd.go b/cpu_freebsd.go index 4657702..ecf9304 100644 --- a/cpu_freebsd.go +++ b/cpu_freebsd.go @@ -32,11 +32,26 @@ func CPUTimes(percpu bool) ([]CPUTimesStat, error) { return ret, err } - user, _ := strconv.ParseFloat(cpuTime[CPUser], 32) - nice, _ := strconv.ParseFloat(cpuTime[CPNice], 32) - sys, _ := strconv.ParseFloat(cpuTime[CPSys], 32) - idle, _ := strconv.ParseFloat(cpuTime[CPIdle], 32) - intr, _ := strconv.ParseFloat(cpuTime[CPIntr], 32) + user, err := strconv.ParseFloat(cpuTime[CPUser], 32) + if err != nil { + return ret, err + } + nice, err := strconv.ParseFloat(cpuTime[CPNice], 32) + if err != nil { + return ret, err + } + sys, err := strconv.ParseFloat(cpuTime[CPSys], 32) + if err != nil { + return ret, err + } + idle, err := strconv.ParseFloat(cpuTime[CPIdle], 32) + if err != nil { + return ret, err + } + intr, err := strconv.ParseFloat(cpuTime[CPIntr], 32) + if err != nil { + return ret, err + } c := CPUTimesStat{ User: float32(user / ClocksPerSec), diff --git a/cpu_linux.go b/cpu_linux.go index ada85e6..36c4490 100644 --- a/cpu_linux.go +++ b/cpu_linux.go @@ -106,14 +106,38 @@ func parseStatLine(line string) (*CPUTimesStat, error) { if cpu == "cpu" { cpu = "cpu-total" } - user, _ := strconv.ParseFloat(fields[1], 32) - nice, _ := strconv.ParseFloat(fields[2], 32) - system, _ := strconv.ParseFloat(fields[3], 32) - idle, _ := strconv.ParseFloat(fields[4], 32) - iowait, _ := strconv.ParseFloat(fields[5], 32) - irq, _ := strconv.ParseFloat(fields[6], 32) - softirq, _ := strconv.ParseFloat(fields[7], 32) - stolen, _ := strconv.ParseFloat(fields[8], 32) + user, err := strconv.ParseFloat(fields[1], 32) + if err != nil { + return nil, err + } + nice, err := strconv.ParseFloat(fields[2], 32) + if err != nil { + return nil, err + } + system, err := strconv.ParseFloat(fields[3], 32) + if err != nil { + return nil, err + } + idle, err := strconv.ParseFloat(fields[4], 32) + if err != nil { + return nil, err + } + iowait, err := strconv.ParseFloat(fields[5], 32) + if err != nil { + return nil, err + } + irq, err := strconv.ParseFloat(fields[6], 32) + if err != nil { + return nil, err + } + softirq, err := strconv.ParseFloat(fields[7], 32) + if err != nil { + return nil, err + } + stolen, err := strconv.ParseFloat(fields[8], 32) + if err != nil { + return nil, err + } ct := &CPUTimesStat{ CPU: cpu, User: float32(user), @@ -126,15 +150,24 @@ func parseStatLine(line string) (*CPUTimesStat, error) { Stolen: float32(stolen), } if len(fields) > 9 { // Linux >= 2.6.11 - steal, _ := strconv.ParseFloat(fields[9], 32) + steal, err := strconv.ParseFloat(fields[9], 32) + if err != nil { + return nil, err + } ct.Steal = float32(steal) } if len(fields) > 10 { // Linux >= 2.6.24 - guest, _ := strconv.ParseFloat(fields[10], 32) + guest, err := strconv.ParseFloat(fields[10], 32) + if err != nil { + return nil, err + } ct.Guest = float32(guest) } if len(fields) > 11 { // Linux >= 3.2.0 - guestNice, _ := strconv.ParseFloat(fields[11], 32) + guestNice, err := strconv.ParseFloat(fields[11], 32) + if err != nil { + return nil, err + } ct.GuestNice = float32(guestNice) }