github.com/openshift/moby-moby@v1.13.2-0.20170601211448-f5ec1e2936dc/daemon/stats_collector_unix.go (about)

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