github.com/jwhonce/docker@v0.6.7-0.20190327063223-da823cf3a5a3/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 ) 13 14 /* 15 #include <unistd.h> 16 */ 17 import "C" 18 19 // platformNewStatsCollector performs platform specific initialisation of the 20 // Collector structure. 21 func platformNewStatsCollector(s *Collector) { 22 s.clockTicksPerSecond = uint64(system.GetClockTicks()) 23 } 24 25 const nanoSecondsPerSecond = 1e9 26 27 // getSystemCPUUsage returns the host system's cpu usage in 28 // nanoseconds. An error is returned if the format of the underlying 29 // file does not match. 30 // 31 // Uses /proc/stat defined by POSIX. Looks for the cpu 32 // statistics line and then sums up the first seven fields 33 // provided. See `man 5 proc` for details on specific field 34 // information. 35 func (s *Collector) getSystemCPUUsage() (uint64, error) { 36 f, err := os.Open("/proc/stat") 37 if err != nil { 38 return 0, err 39 } 40 defer func() { 41 s.bufReader.Reset(nil) 42 f.Close() 43 }() 44 s.bufReader.Reset(f) 45 46 for { 47 line, err := s.bufReader.ReadString('\n') 48 if err != nil { 49 break 50 } 51 parts := strings.Fields(line) 52 switch parts[0] { 53 case "cpu": 54 if len(parts) < 8 { 55 return 0, fmt.Errorf("invalid number of cpu fields") 56 } 57 var totalClockTicks uint64 58 for _, i := range parts[1:8] { 59 v, err := strconv.ParseUint(i, 10, 64) 60 if err != nil { 61 return 0, fmt.Errorf("Unable to convert value %s to int: %s", i, err) 62 } 63 totalClockTicks += v 64 } 65 return (totalClockTicks * nanoSecondsPerSecond) / 66 s.clockTicksPerSecond, nil 67 } 68 } 69 return 0, fmt.Errorf("invalid stat format. Error trying to parse the '/proc/stat' file") 70 } 71 72 func (s *Collector) getNumberOnlineCPUs() (uint32, error) { 73 i, err := C.sysconf(C._SC_NPROCESSORS_ONLN) 74 // According to POSIX - errno is undefined after successful 75 // sysconf, and can be non-zero in several cases, so look for 76 // error in returned value not in errno. 77 // (https://sourceware.org/bugzilla/show_bug.cgi?id=21536) 78 if i == -1 { 79 return 0, err 80 } 81 return uint32(i), nil 82 }