github.com/elastic/gosigar@v0.14.3/sigar_linux.go (about) 1 // Copyright (c) 2012 VMware, Inc. 2 3 package gosigar 4 5 import ( 6 "io/ioutil" 7 "strconv" 8 "strings" 9 "syscall" 10 ) 11 12 func init() { 13 system.ticks = 100 // C.sysconf(C._SC_CLK_TCK) 14 15 Procd = "/proc" 16 17 getLinuxBootTime() 18 } 19 20 func getMountTableFileName() string { 21 return "/etc/mtab" 22 } 23 24 // Get returns uptime data 25 func (self *Uptime) Get() error { 26 sysinfo := syscall.Sysinfo_t{} 27 28 if err := syscall.Sysinfo(&sysinfo); err != nil { 29 return err 30 } 31 32 self.Length = float64(sysinfo.Uptime) 33 34 return nil 35 } 36 37 // Get returns FD usage data 38 func (self *FDUsage) Get() error { 39 return readFile(Procd+"/sys/fs/file-nr", func(line string) bool { 40 fields := strings.Fields(line) 41 if len(fields) == 3 { 42 self.Open, _ = strconv.ParseUint(fields[0], 10, 64) 43 self.Unused, _ = strconv.ParseUint(fields[1], 10, 64) 44 self.Max, _ = strconv.ParseUint(fields[2], 10, 64) 45 } 46 return false 47 }) 48 } 49 50 // Get returns hugepages data 51 func (self *HugeTLBPages) Get() error { 52 table, err := parseMeminfo() 53 if err != nil { 54 return err 55 } 56 57 self.Total, _ = table["HugePages_Total"] 58 self.Free, _ = table["HugePages_Free"] 59 self.Reserved, _ = table["HugePages_Rsvd"] 60 self.Surplus, _ = table["HugePages_Surp"] 61 self.DefaultSize, _ = table["Hugepagesize"] 62 63 if totalSize, found := table["Hugetlb"]; found { 64 self.TotalAllocatedSize = totalSize 65 } else { 66 // If Hugetlb is not present, or huge pages of different sizes 67 // are used, this figure can be unaccurate. 68 // TODO (jsoriano): Extract information from /sys/kernel/mm/hugepages too 69 self.TotalAllocatedSize = (self.Total - self.Free + self.Reserved) * self.DefaultSize 70 } 71 72 return nil 73 } 74 75 // Get returns process FD usage 76 func (self *ProcFDUsage) Get(pid int) error { 77 err := readFile(procFileName(pid, "limits"), func(line string) bool { 78 if strings.HasPrefix(line, "Max open files") { 79 fields := strings.Fields(line) 80 if len(fields) == 6 { 81 self.SoftLimit, _ = strconv.ParseUint(fields[3], 10, 64) 82 self.HardLimit, _ = strconv.ParseUint(fields[4], 10, 64) 83 } 84 return false 85 } 86 return true 87 }) 88 if err != nil { 89 return err 90 } 91 fds, err := ioutil.ReadDir(procFileName(pid, "fd")) 92 if err != nil { 93 return err 94 } 95 self.Open = uint64(len(fds)) 96 return nil 97 } 98 99 func parseCpuStat(self *Cpu, line string) error { 100 fields := strings.Fields(line) 101 102 self.User, _ = strtoull(fields[1]) 103 self.Nice, _ = strtoull(fields[2]) 104 self.Sys, _ = strtoull(fields[3]) 105 self.Idle, _ = strtoull(fields[4]) 106 self.Wait, _ = strtoull(fields[5]) 107 self.Irq, _ = strtoull(fields[6]) 108 self.SoftIrq, _ = strtoull(fields[7]) 109 self.Stolen, _ = strtoull(fields[8]) 110 111 return nil 112 } 113 114 // Get returns memory data 115 func (self *Mem) Get() error { 116 117 table, err := parseMeminfo() 118 if err != nil { 119 return err 120 } 121 122 self.Total, _ = table["MemTotal"] 123 self.Free, _ = table["MemFree"] 124 buffers, _ := table["Buffers"] 125 self.Cached, _ = table["Cached"] 126 127 if available, ok := table["MemAvailable"]; ok { 128 // MemAvailable is in /proc/meminfo (kernel 3.14+) 129 self.ActualFree = available 130 } else { 131 self.ActualFree = self.Free + buffers + self.Cached 132 } 133 134 self.Used = self.Total - self.Free 135 self.ActualUsed = self.Total - self.ActualFree 136 137 return nil 138 }