collector_unix.go 1.8 KB

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