github.com/docker/docker@v299999999.0.0-20200612211812-aaf470eca7b5+incompatible/daemon/stats/collector_unix.go (about) 1 // +build !windows 2 3 package stats // import "github.com/docker/docker/daemon/stats" 4 5 import ( 6 "fmt" 7 "os" 8 "strconv" 9 "strings" 10 11 "github.com/opencontainers/runc/libcontainer/system" 12 "golang.org/x/sys/unix" 13 ) 14 15 // platformNewStatsCollector performs platform specific initialisation of the 16 // Collector structure. 17 func platformNewStatsCollector(s *Collector) { 18 s.clockTicksPerSecond = uint64(system.GetClockTicks()) 19 } 20 21 const nanoSecondsPerSecond = 1e9 22 23 // getSystemCPUUsage returns the host system's cpu usage in 24 // nanoseconds. An error is returned if the format of the underlying 25 // file does not match. 26 // 27 // Uses /proc/stat defined by POSIX. Looks for the cpu 28 // statistics line and then sums up the first seven fields 29 // provided. See `man 5 proc` for details on specific field 30 // information. 31 func (s *Collector) getSystemCPUUsage() (uint64, error) { 32 f, err := os.Open("/proc/stat") 33 if err != nil { 34 return 0, err 35 } 36 defer func() { 37 s.bufReader.Reset(nil) 38 f.Close() 39 }() 40 s.bufReader.Reset(f) 41 42 for { 43 line, err := s.bufReader.ReadString('\n') 44 if err != nil { 45 break 46 } 47 parts := strings.Fields(line) 48 switch parts[0] { 49 case "cpu": 50 if len(parts) < 8 { 51 return 0, fmt.Errorf("invalid number of cpu fields") 52 } 53 var totalClockTicks uint64 54 for _, i := range parts[1:8] { 55 v, err := strconv.ParseUint(i, 10, 64) 56 if err != nil { 57 return 0, fmt.Errorf("Unable to convert value %s to int: %s", i, err) 58 } 59 totalClockTicks += v 60 } 61 return (totalClockTicks * nanoSecondsPerSecond) / 62 s.clockTicksPerSecond, nil 63 } 64 } 65 return 0, fmt.Errorf("invalid stat format. Error trying to parse the '/proc/stat' file") 66 } 67 68 func (s *Collector) getNumberOnlineCPUs() (uint32, error) { 69 var cpuset unix.CPUSet 70 err := unix.SchedGetaffinity(0, &cpuset) 71 if err != nil { 72 return 0, err 73 } 74 return uint32(cpuset.Count()), nil 75 }