cpuacct.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. package cgroup
  2. import (
  3. "bufio"
  4. "bytes"
  5. "io/ioutil"
  6. "os"
  7. "path/filepath"
  8. "time"
  9. "notabug.org/themusicgod1/gosigar/sys/linux"
  10. )
  11. var clockTicks = uint64(linux.GetClockTicks())
  12. // CPUAccountingSubsystem contains metrics from the "cpuacct" subsystem.
  13. type CPUAccountingSubsystem struct {
  14. Metadata
  15. TotalNanos uint64 `json:"total_nanos"`
  16. UsagePerCPU []uint64 `json:"usage_percpu_nanos"`
  17. // CPU time statistics for tasks in this cgroup.
  18. Stats CPUAccountingStats `json:"stats,omitempty"`
  19. }
  20. // CPUAccountingStats contains the stats reported from the cpuacct subsystem.
  21. type CPUAccountingStats struct {
  22. UserNanos uint64 `json:"user_nanos"`
  23. SystemNanos uint64 `json:"system_nanos"`
  24. }
  25. // get reads metrics from the "cpuacct" subsystem. path is the filepath to the
  26. // cgroup hierarchy to read.
  27. func (cpuacct *CPUAccountingSubsystem) get(path string) error {
  28. if err := cpuacctStat(path, cpuacct); err != nil {
  29. return err
  30. }
  31. if err := cpuacctUsage(path, cpuacct); err != nil {
  32. return err
  33. }
  34. if err := cpuacctUsagePerCPU(path, cpuacct); err != nil {
  35. return err
  36. }
  37. return nil
  38. }
  39. func cpuacctStat(path string, cpuacct *CPUAccountingSubsystem) error {
  40. f, err := os.Open(filepath.Join(path, "cpuacct.stat"))
  41. if err != nil {
  42. if os.IsNotExist(err) {
  43. return nil
  44. }
  45. return err
  46. }
  47. defer f.Close()
  48. sc := bufio.NewScanner(f)
  49. for sc.Scan() {
  50. t, v, err := parseCgroupParamKeyValue(sc.Text())
  51. if err != nil {
  52. return err
  53. }
  54. switch t {
  55. case "user":
  56. cpuacct.Stats.UserNanos = convertJiffiesToNanos(v)
  57. case "system":
  58. cpuacct.Stats.SystemNanos = convertJiffiesToNanos(v)
  59. }
  60. }
  61. return sc.Err()
  62. }
  63. func cpuacctUsage(path string, cpuacct *CPUAccountingSubsystem) error {
  64. var err error
  65. cpuacct.TotalNanos, err = parseUintFromFile(path, "cpuacct.usage")
  66. if err != nil {
  67. return err
  68. }
  69. return nil
  70. }
  71. func cpuacctUsagePerCPU(path string, cpuacct *CPUAccountingSubsystem) error {
  72. contents, err := ioutil.ReadFile(filepath.Join(path, "cpuacct.usage_percpu"))
  73. if err != nil {
  74. if os.IsNotExist(err) {
  75. return nil
  76. }
  77. return err
  78. }
  79. var values []uint64
  80. usages := bytes.Fields(contents)
  81. for _, usage := range usages {
  82. value, err := parseUint(usage)
  83. if err != nil {
  84. return err
  85. }
  86. values = append(values, value)
  87. }
  88. cpuacct.UsagePerCPU = values
  89. return nil
  90. }
  91. func convertJiffiesToNanos(j uint64) uint64 {
  92. return (j * uint64(time.Second)) / clockTicks
  93. }