Add stats for memory allocation failure count and instantaneous cpu usage in the usermode and kernelmode.

Docker-DCO-1.1-Signed-off-by: Vishnu Kannan <vishnuk@google.com> (github: vishh)
This commit is contained in:
Vishnu Kannan 2014-06-04 06:41:03 +00:00
parent 2616e87cad
commit 59c33dfe0b
4 changed files with 39 additions and 20 deletions

View file

@ -20,6 +20,8 @@ var (
clockTicks = uint64(system.GetClockTicks())
)
const nanosecondsInSecond = 1000000000
type cpuacctGroup struct {
}
@ -37,13 +39,13 @@ func (s *cpuacctGroup) Remove(d *data) error {
func (s *cpuacctGroup) GetStats(d *data, stats *cgroups.Stats) error {
var (
startCpu, lastCpu, startSystem, lastSystem, startUsage, lastUsage uint64
percentage uint64
startCpu, lastCpu, startSystem, lastSystem, startUsage, lastUsage, kernelModeUsage, userModeUsage, percentage uint64
)
path, err := d.path("cpuacct")
if startCpu, err = s.getCpuUsage(d, path); err != nil {
if kernelModeUsage, userModeUsage, err = s.getCpuUsage(d, path); err != nil {
return err
}
startCpu = kernelModeUsage + userModeUsage
if startSystem, err = s.getSystemCpuUsage(d); err != nil {
return err
}
@ -53,9 +55,10 @@ func (s *cpuacctGroup) GetStats(d *data, stats *cgroups.Stats) error {
}
// sample for 100ms
time.Sleep(100 * time.Millisecond)
if lastCpu, err = s.getCpuUsage(d, path); err != nil {
if kernelModeUsage, userModeUsage, err = s.getCpuUsage(d, path); err != nil {
return err
}
lastCpu = kernelModeUsage + userModeUsage
if lastSystem, err = s.getSystemCpuUsage(d); err != nil {
return err
}
@ -82,6 +85,8 @@ func (s *cpuacctGroup) GetStats(d *data, stats *cgroups.Stats) error {
return err
}
stats.CpuStats.CpuUsage.PercpuUsage = percpuUsage
stats.CpuStats.CpuUsage.UsageInKernelmode = (kernelModeUsage * nanosecondsInSecond) / clockTicks
stats.CpuStats.CpuUsage.UsageInUsermode = (userModeUsage * nanosecondsInSecond) / clockTicks
return nil
}
@ -119,24 +124,25 @@ func (s *cpuacctGroup) getSystemCpuUsage(d *data) (uint64, error) {
return 0, fmt.Errorf("invalid stat format")
}
func (s *cpuacctGroup) getCpuUsage(d *data, path string) (uint64, error) {
cpuTotal := uint64(0)
f, err := os.Open(filepath.Join(path, "cpuacct.stat"))
func (s *cpuacctGroup) getCpuUsage(d *data, path string) (uint64, uint64, error) {
kernelModeUsage := uint64(0)
userModeUsage := uint64(0)
data, err := ioutil.ReadFile(filepath.Join(path, "cpuacct.stat"))
if err != nil {
return 0, err
return 0, 0, err
}
fields := strings.Fields(string(data))
if len(fields) != 4 {
return 0, 0, fmt.Errorf("Failure - %s is expected to have 4 fields", filepath.Join(path, "cpuacct.stat"))
}
if userModeUsage, err = strconv.ParseUint(fields[1], 10, 64); err != nil {
return 0, 0, err
}
if kernelModeUsage, err = strconv.ParseUint(fields[3], 10, 64); err != nil {
return 0, 0, err
}
defer f.Close()
sc := bufio.NewScanner(f)
for sc.Scan() {
_, v, err := getCgroupParamKeyValue(sc.Text())
if err != nil {
return 0, err
}
// set the raw data in map
cpuTotal += v
}
return cpuTotal, nil
return kernelModeUsage, userModeUsage, nil
}
func (s *cpuacctGroup) getPercpuUsage(path string) ([]uint64, error) {

View file

@ -84,6 +84,11 @@ func (s *memoryGroup) GetStats(d *data, stats *cgroups.Stats) error {
return err
}
stats.MemoryStats.MaxUsage = value
value, err = getCgroupParamInt(path, "memory.failcnt")
if err != nil {
return err
}
stats.MemoryStats.Failcnt = value
return nil
}

View file

@ -11,6 +11,7 @@ const (
rss 1024`
memoryUsageContents = "2048\n"
memoryMaxUsageContents = "4096\n"
memoryFailcnt = "100\n"
)
func TestMemoryStats(t *testing.T) {
@ -20,6 +21,7 @@ func TestMemoryStats(t *testing.T) {
"memory.stat": memoryStatContents,
"memory.usage_in_bytes": memoryUsageContents,
"memory.max_usage_in_bytes": memoryMaxUsageContents,
"memory.failcnt": memoryFailcnt,
})
memory := &memoryGroup{}
@ -27,7 +29,7 @@ func TestMemoryStats(t *testing.T) {
if err != nil {
t.Fatal(err)
}
expectedStats := cgroups.MemoryStats{Usage: 2048, MaxUsage: 4096, Stats: map[string]uint64{"cache": 512, "rss": 1024}}
expectedStats := cgroups.MemoryStats{Usage: 2048, MaxUsage: 4096, Failcnt: 100, Stats: map[string]uint64{"cache": 512, "rss": 1024}}
expectMemoryStatEquals(t, expectedStats, actualStats.MemoryStats)
}

View file

@ -15,6 +15,10 @@ type CpuUsage struct {
// nanoseconds of cpu time consumed over the last 100 ms.
CurrentUsage uint64 `json:"current_usage,omitempty"`
PercpuUsage []uint64 `json:"percpu_usage,omitempty"`
// Time spent by tasks of the cgroup in kernel mode. Units: nanoseconds.
UsageInKernelmode uint64 `json:"usage_in_kernelmode"`
// Time spent by tasks of the cgroup in user mode. Units: nanoseconds.
UsageInUsermode uint64 `json:"usage_in_usermode"`
}
type CpuStats struct {
@ -30,6 +34,8 @@ type MemoryStats struct {
// TODO(vishh): Export these as stronger types.
// all the stats exported via memory.stat.
Stats map[string]uint64 `json:"stats,omitempty"`
// number of times memory usage hits limits.
Failcnt uint64 `json:"failcnt"`
}
type BlkioStatEntry struct {