Procházet zdrojové kódy

Merge pull request #6198 from vishh/stats2

Add more stats to libcontainer.
Michael Crosby před 11 roky
rodič
revize
fd21da4b0b

+ 25 - 19
pkg/libcontainer/cgroups/fs/cpuacct.go

@@ -20,6 +20,8 @@ var (
 	clockTicks = uint64(system.GetClockTicks())
 	clockTicks = uint64(system.GetClockTicks())
 )
 )
 
 
+const nanosecondsInSecond = 1000000000
+
 type cpuacctGroup struct {
 type cpuacctGroup struct {
 }
 }
 
 
@@ -37,13 +39,13 @@ func (s *cpuacctGroup) Remove(d *data) error {
 
 
 func (s *cpuacctGroup) GetStats(d *data, stats *cgroups.Stats) error {
 func (s *cpuacctGroup) GetStats(d *data, stats *cgroups.Stats) error {
 	var (
 	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")
 	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
 		return err
 	}
 	}
+	startCpu = kernelModeUsage + userModeUsage
 	if startSystem, err = s.getSystemCpuUsage(d); err != nil {
 	if startSystem, err = s.getSystemCpuUsage(d); err != nil {
 		return err
 		return err
 	}
 	}
@@ -53,9 +55,10 @@ func (s *cpuacctGroup) GetStats(d *data, stats *cgroups.Stats) error {
 	}
 	}
 	// sample for 100ms
 	// sample for 100ms
 	time.Sleep(100 * time.Millisecond)
 	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
 		return err
 	}
 	}
+	lastCpu = kernelModeUsage + userModeUsage
 	if lastSystem, err = s.getSystemCpuUsage(d); err != nil {
 	if lastSystem, err = s.getSystemCpuUsage(d); err != nil {
 		return err
 		return err
 	}
 	}
@@ -82,6 +85,8 @@ func (s *cpuacctGroup) GetStats(d *data, stats *cgroups.Stats) error {
 		return err
 		return err
 	}
 	}
 	stats.CpuStats.CpuUsage.PercpuUsage = percpuUsage
 	stats.CpuStats.CpuUsage.PercpuUsage = percpuUsage
+	stats.CpuStats.CpuUsage.UsageInKernelmode = (kernelModeUsage * nanosecondsInSecond) / clockTicks
+	stats.CpuStats.CpuUsage.UsageInUsermode = (userModeUsage * nanosecondsInSecond) / clockTicks
 	return nil
 	return nil
 }
 }
 
 
@@ -119,24 +124,25 @@ func (s *cpuacctGroup) getSystemCpuUsage(d *data) (uint64, error) {
 	return 0, fmt.Errorf("invalid stat format")
 	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 {
 	if err != nil {
-		return 0, err
+		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
+	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
 	}
 	}
-	return cpuTotal, nil
+	if kernelModeUsage, err = strconv.ParseUint(fields[3], 10, 64); err != nil {
+		return 0, 0, err
+	}
+
+	return kernelModeUsage, userModeUsage, nil
 }
 }
 
 
 func (s *cpuacctGroup) getPercpuUsage(path string) ([]uint64, error) {
 func (s *cpuacctGroup) getPercpuUsage(path string) ([]uint64, error) {

+ 5 - 0
pkg/libcontainer/cgroups/fs/memory.go

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

+ 3 - 1
pkg/libcontainer/cgroups/fs/memory_test.go

@@ -11,6 +11,7 @@ const (
 rss 1024`
 rss 1024`
 	memoryUsageContents    = "2048\n"
 	memoryUsageContents    = "2048\n"
 	memoryMaxUsageContents = "4096\n"
 	memoryMaxUsageContents = "4096\n"
+	memoryFailcnt          = "100\n"
 )
 )
 
 
 func TestMemoryStats(t *testing.T) {
 func TestMemoryStats(t *testing.T) {
@@ -20,6 +21,7 @@ func TestMemoryStats(t *testing.T) {
 		"memory.stat":               memoryStatContents,
 		"memory.stat":               memoryStatContents,
 		"memory.usage_in_bytes":     memoryUsageContents,
 		"memory.usage_in_bytes":     memoryUsageContents,
 		"memory.max_usage_in_bytes": memoryMaxUsageContents,
 		"memory.max_usage_in_bytes": memoryMaxUsageContents,
+		"memory.failcnt":            memoryFailcnt,
 	})
 	})
 
 
 	memory := &memoryGroup{}
 	memory := &memoryGroup{}
@@ -27,7 +29,7 @@ func TestMemoryStats(t *testing.T) {
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		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)
 	expectMemoryStatEquals(t, expectedStats, actualStats.MemoryStats)
 }
 }
 
 

+ 6 - 0
pkg/libcontainer/cgroups/stats.go

@@ -15,6 +15,10 @@ type CpuUsage struct {
 	// nanoseconds of cpu time consumed over the last 100 ms.
 	// nanoseconds of cpu time consumed over the last 100 ms.
 	CurrentUsage uint64   `json:"current_usage,omitempty"`
 	CurrentUsage uint64   `json:"current_usage,omitempty"`
 	PercpuUsage  []uint64 `json:"percpu_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 {
 type CpuStats struct {
@@ -30,6 +34,8 @@ type MemoryStats struct {
 	// TODO(vishh): Export these as stronger types.
 	// TODO(vishh): Export these as stronger types.
 	// all the stats exported via memory.stat.
 	// all the stats exported via memory.stat.
 	Stats map[string]uint64 `json:"stats,omitempty"`
 	Stats map[string]uint64 `json:"stats,omitempty"`
+	// number of times memory usage hits limits.
+	Failcnt uint64 `json:"failcnt"`
 }
 }
 
 
 type BlkioStatEntry struct {
 type BlkioStatEntry struct {