139 lines
3.1 KiB
Go
139 lines
3.1 KiB
Go
|
// Copyright (c) 2012 VMware, Inc.
|
||
|
|
||
|
package gosigar
|
||
|
|
||
|
import (
|
||
|
"io/ioutil"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
"syscall"
|
||
|
)
|
||
|
|
||
|
func init() {
|
||
|
system.ticks = 100 // C.sysconf(C._SC_CLK_TCK)
|
||
|
|
||
|
Procd = "/proc"
|
||
|
|
||
|
getLinuxBootTime()
|
||
|
}
|
||
|
|
||
|
func getMountTableFileName() string {
|
||
|
return "/etc/mtab"
|
||
|
}
|
||
|
|
||
|
// Get returns uptime data
|
||
|
func (self *Uptime) Get() error {
|
||
|
sysinfo := syscall.Sysinfo_t{}
|
||
|
|
||
|
if err := syscall.Sysinfo(&sysinfo); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
self.Length = float64(sysinfo.Uptime)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Get returns FD usage data
|
||
|
func (self *FDUsage) Get() error {
|
||
|
return readFile(Procd+"/sys/fs/file-nr", func(line string) bool {
|
||
|
fields := strings.Fields(line)
|
||
|
if len(fields) == 3 {
|
||
|
self.Open, _ = strconv.ParseUint(fields[0], 10, 64)
|
||
|
self.Unused, _ = strconv.ParseUint(fields[1], 10, 64)
|
||
|
self.Max, _ = strconv.ParseUint(fields[2], 10, 64)
|
||
|
}
|
||
|
return false
|
||
|
})
|
||
|
}
|
||
|
|
||
|
// Get returns hugepages data
|
||
|
func (self *HugeTLBPages) Get() error {
|
||
|
table, err := parseMeminfo()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
self.Total, _ = table["HugePages_Total"]
|
||
|
self.Free, _ = table["HugePages_Free"]
|
||
|
self.Reserved, _ = table["HugePages_Rsvd"]
|
||
|
self.Surplus, _ = table["HugePages_Surp"]
|
||
|
self.DefaultSize, _ = table["Hugepagesize"]
|
||
|
|
||
|
if totalSize, found := table["Hugetlb"]; found {
|
||
|
self.TotalAllocatedSize = totalSize
|
||
|
} else {
|
||
|
// If Hugetlb is not present, or huge pages of different sizes
|
||
|
// are used, this figure can be unaccurate.
|
||
|
// TODO (jsoriano): Extract information from /sys/kernel/mm/hugepages too
|
||
|
self.TotalAllocatedSize = (self.Total - self.Free + self.Reserved) * self.DefaultSize
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Get returns process FD usage
|
||
|
func (self *ProcFDUsage) Get(pid int) error {
|
||
|
err := readFile(procFileName(pid, "limits"), func(line string) bool {
|
||
|
if strings.HasPrefix(line, "Max open files") {
|
||
|
fields := strings.Fields(line)
|
||
|
if len(fields) == 6 {
|
||
|
self.SoftLimit, _ = strconv.ParseUint(fields[3], 10, 64)
|
||
|
self.HardLimit, _ = strconv.ParseUint(fields[4], 10, 64)
|
||
|
}
|
||
|
return false
|
||
|
}
|
||
|
return true
|
||
|
})
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
fds, err := ioutil.ReadDir(procFileName(pid, "fd"))
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
self.Open = uint64(len(fds))
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func parseCpuStat(self *Cpu, line string) error {
|
||
|
fields := strings.Fields(line)
|
||
|
|
||
|
self.User, _ = strtoull(fields[1])
|
||
|
self.Nice, _ = strtoull(fields[2])
|
||
|
self.Sys, _ = strtoull(fields[3])
|
||
|
self.Idle, _ = strtoull(fields[4])
|
||
|
self.Wait, _ = strtoull(fields[5])
|
||
|
self.Irq, _ = strtoull(fields[6])
|
||
|
self.SoftIrq, _ = strtoull(fields[7])
|
||
|
self.Stolen, _ = strtoull(fields[8])
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Get returns memory data
|
||
|
func (self *Mem) Get() error {
|
||
|
|
||
|
table, err := parseMeminfo()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
self.Total, _ = table["MemTotal"]
|
||
|
self.Free, _ = table["MemFree"]
|
||
|
buffers, _ := table["Buffers"]
|
||
|
self.Cached, _ = table["Cached"]
|
||
|
|
||
|
if available, ok := table["MemAvailable"]; ok {
|
||
|
// MemAvailable is in /proc/meminfo (kernel 3.14+)
|
||
|
self.ActualFree = available
|
||
|
} else {
|
||
|
self.ActualFree = self.Free + buffers + self.Cached
|
||
|
}
|
||
|
|
||
|
self.Used = self.Total - self.Free
|
||
|
self.ActualUsed = self.Total - self.ActualFree
|
||
|
|
||
|
return nil
|
||
|
}
|