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