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  }