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