From 6e98c926937d9bcfd4aec01c60f9b8a4c3d3b3e0 Mon Sep 17 00:00:00 2001 From: Nan Deng Date: Mon, 16 Jun 2014 15:41:46 -0700 Subject: [PATCH 1/4] changing info package to work with storage drivers. --- container/statssum.go | 2 +- container/statssum_test.go | 8 +++++--- info/container.go | 31 +++++++++++++++---------------- storage/storage.go | 9 +++++++++ 4 files changed, 30 insertions(+), 20 deletions(-) diff --git a/container/statssum.go b/container/statssum.go index b07ecec5..0987dfb3 100644 --- a/container/statssum.go +++ b/container/statssum.go @@ -118,9 +118,9 @@ func (self *percentilesContainerHandlerWrapper) StatsPercentiles() (*info.Contai stats := d.(*info.ContainerStatsSample) samples = append(samples, stats) }) - self.containerPercentiles.Samples = samples // XXX(dengnan): probably add to StatsParameter? self.containerPercentiles.FillPercentiles( + samples, []int{50, 80, 90, 95, 99}, []int{50, 80, 90, 95, 99}, ) diff --git a/container/statssum_test.go b/container/statssum_test.go index 7ccd60c0..3efab0a5 100644 --- a/container/statssum_test.go +++ b/container/statssum_test.go @@ -164,11 +164,13 @@ func TestSampleCpuUsage(t *testing.T) { } } - s, err := handler.StatsPercentiles() + _, err := handler.StatsPercentiles() if err != nil { t.Fatal(err) } - for _, sample := range s.Samples { + hs := handler.(*percentilesContainerHandlerWrapper) + hs.sampler.Map(func(d interface{}) { + sample := d.(*info.ContainerStatsSample) if sample.Duration != samplePeriod { t.Errorf("sample duration is %v, not %v", sample.Duration, samplePeriod) } @@ -182,5 +184,5 @@ func TestSampleCpuUsage(t *testing.T) { if !found { t.Errorf("unable to find cpu usage %v", cpuUsage) } - } + }) } diff --git a/info/container.go b/info/container.go index a0c8affc..4036a56b 100644 --- a/info/container.go +++ b/info/container.go @@ -69,6 +69,9 @@ type ContainerInfo struct { // Historical statistics gathered from the container. Stats []*ContainerStats `json:"stats,omitempty"` + // Randomly sampled container states. + Samples []*ContainerStatsSample `json:"samples,omitempty"` + StatsPercentiles *ContainerStatsPercentiles `json:"stats_summary,omitempty"` } @@ -177,19 +180,15 @@ type ContainerStatsSample struct { } `json:"memory"` } -// This is not exported. -// Use FillPercentile to calculate percentiles -type percentile struct { +type Percentile struct { Percentage int `json:"percentage"` Value uint64 `json:"value"` } type ContainerStatsPercentiles struct { - // TODO(dengnan): More things? - MaxMemoryUsage uint64 `json:"max_memory_usage,omitempty"` - Samples []*ContainerStatsSample `json:"samples,omitempty"` - MemoryUsagePercentiles []percentile `json:"memory_usage_percentiles,omitempty"` - CpuUsagePercentiles []percentile `json:"cpu_usage_percentiles,omitempty"` + MaxMemoryUsage uint64 `json:"max_memory_usage,omitempty"` + MemoryUsagePercentiles []Percentile `json:"memory_usage_percentiles,omitempty"` + CpuUsagePercentiles []Percentile `json:"cpu_usage_percentiles,omitempty"` } // Each sample needs two stats because the cpu usage in ContainerStats is @@ -237,11 +236,11 @@ func (self uint64Slice) Swap(i, j int) { self[i], self[j] = self[j], self[i] } -func (self uint64Slice) Percentiles(requestedPercentiles ...int) []percentile { +func (self uint64Slice) Percentiles(requestedPercentiles ...int) []Percentile { if len(self) == 0 { return nil } - ret := make([]percentile, 0, len(requestedPercentiles)) + ret := make([]Percentile, 0, len(requestedPercentiles)) sort.Sort(self) for _, p := range requestedPercentiles { idx := (len(self) * p / 100) - 1 @@ -250,7 +249,7 @@ func (self uint64Slice) Percentiles(requestedPercentiles ...int) []percentile { } ret = append( ret, - percentile{ + Percentile{ Percentage: p, Value: self[idx], }, @@ -259,14 +258,14 @@ func (self uint64Slice) Percentiles(requestedPercentiles ...int) []percentile { return ret } -func (self *ContainerStatsPercentiles) FillPercentiles(cpuPercentages, memoryPercentages []int) { - if len(self.Samples) == 0 { +func (self *ContainerStatsPercentiles) FillPercentiles(samples []*ContainerStatsSample, cpuPercentages, memoryPercentages []int) { + if len(samples) == 0 { return } - cpuUsages := make([]uint64, 0, len(self.Samples)) - memUsages := make([]uint64, 0, len(self.Samples)) + cpuUsages := make([]uint64, 0, len(samples)) + memUsages := make([]uint64, 0, len(samples)) - for _, sample := range self.Samples { + for _, sample := range samples { if sample == nil { continue } diff --git a/storage/storage.go b/storage/storage.go index f9990831..ca646fd6 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -18,4 +18,13 @@ import "github.com/google/cadvisor/info" type StorageDriver interface { AddStats(ref info.ContainerReference, stats *info.ContainerStats) error + + // Read most recent stats. numStats indicates max number of stats + // returned. The returned stats must be consecutive observed stats. If + // numStats < 0, then return all stats stored in the storage. + RecentStats(numStats int) ([]*info.ContainerStats, error) + + Percentiles(cpuUsagePercentiles []int, memUsagePercentiles []int) (*info.ContainerStatsPercentiles, error) + + Samples(numSamples int) ([]*info.ContainerStatsSample, error) } From 5f45128c318dfaa4573f5ff915ebfe33f5947960 Mon Sep 17 00:00:00 2001 From: Nan Deng Date: Mon, 16 Jun 2014 16:02:23 -0700 Subject: [PATCH 2/4] container name should be specified --- storage/storage.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/storage/storage.go b/storage/storage.go index ca646fd6..f3e48ca8 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -22,9 +22,9 @@ type StorageDriver interface { // Read most recent stats. numStats indicates max number of stats // returned. The returned stats must be consecutive observed stats. If // numStats < 0, then return all stats stored in the storage. - RecentStats(numStats int) ([]*info.ContainerStats, error) + RecentStats(containerName string, numStats int) ([]*info.ContainerStats, error) - Percentiles(cpuUsagePercentiles []int, memUsagePercentiles []int) (*info.ContainerStatsPercentiles, error) + Percentiles(containerName string, cpuUsagePercentiles []int, memUsagePercentiles []int) (*info.ContainerStatsPercentiles, error) - Samples(numSamples int) ([]*info.ContainerStatsSample, error) + Samples(containername string, numSamples int) ([]*info.ContainerStatsSample, error) } From cbc266bb64bd6d52944817ca505e9bf7dca60c81 Mon Sep 17 00:00:00 2001 From: Nan Deng Date: Mon, 16 Jun 2014 17:59:32 -0700 Subject: [PATCH 3/4] comment --- storage/storage.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/storage/storage.go b/storage/storage.go index f3e48ca8..84de7b57 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -24,7 +24,12 @@ type StorageDriver interface { // numStats < 0, then return all stats stored in the storage. RecentStats(containerName string, numStats int) ([]*info.ContainerStats, error) + // Read the specified percentiles of CPU and memory usage of the container. + // The implementation decides which time range to look at. Percentiles(containerName string, cpuUsagePercentiles []int, memUsagePercentiles []int) (*info.ContainerStatsPercentiles, error) + // Returns samples of the container stats. If numSamples < 0, then + // the number of returned samples is implementation defined. Otherwise, the driver + // should return at most numSamples samples. Samples(containername string, numSamples int) ([]*info.ContainerStatsSample, error) } From 626e2aba09656275a54f542e562bce47c185ed11 Mon Sep 17 00:00:00 2001 From: Nan Deng Date: Mon, 16 Jun 2014 18:06:23 -0700 Subject: [PATCH 4/4] unit test --- container/statssum_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/statssum_test.go b/container/statssum_test.go index 3efab0a5..35f27f3f 100644 --- a/container/statssum_test.go +++ b/container/statssum_test.go @@ -164,7 +164,7 @@ func TestSampleCpuUsage(t *testing.T) { } } - _, err := handler.StatsPercentiles() + _, err = handler.StatsPercentiles() if err != nil { t.Fatal(err) }