diff --git a/info/test/datagen.go b/info/test/datagen.go index 1be1dd19..abc1f3c3 100644 --- a/info/test/datagen.go +++ b/info/test/datagen.go @@ -52,7 +52,9 @@ func GenerateRandomStats(numStats, numCores int, duration time.Duration) []*info func GenerateRandomContainerSpec(numCores int) info.ContainerSpec { ret := info.ContainerSpec{ CreationTime: time.Now(), + HasCpu: true, Cpu: info.CpuSpec{}, + HasMemory: true, Memory: info.MemorySpec{}, } ret.Cpu.Limit = uint64(1000 + rand.Int63n(2000)) diff --git a/manager/container.go b/manager/container.go index 4e47789b..78d95ae3 100644 --- a/manager/container.go +++ b/manager/container.go @@ -26,6 +26,7 @@ import ( "github.com/google/cadvisor/container" "github.com/google/cadvisor/info" "github.com/google/cadvisor/storage" + "github.com/google/cadvisor/summary" "github.com/google/cadvisor/utils/cpuload" ) @@ -49,6 +50,7 @@ type containerData struct { storageDriver storage.StorageDriver lock sync.Mutex loadReader cpuload.CpuLoadReader + summaryReader *summary.StatsSummary loadAvg float64 // smoothed load average seen so far. housekeepingInterval time.Duration lastUpdatedTime time.Time @@ -121,6 +123,15 @@ func newContainerData(containerName string, driver storage.StorageDriver, handle } cont.info.ContainerReference = ref + err = cont.updateSpec() + if err != nil { + return nil, err + } + cont.summaryReader, err = summary.New(cont.info.Spec) + if err != nil { + return nil, fmt.Errorf("failed to create summary reader: %v", err) + } + return cont, nil } @@ -278,6 +289,13 @@ func (c *containerData) updateStats() error { stats.Cpu.LoadAverage = int32(c.loadAvg * 1000) } } + if c.summaryReader != nil { + err := c.summaryReader.AddSample(*stats) + if err != nil { + // Ignore summary errors for now. + glog.V(2).Infof("failed to add summary stats for %q: %v", c.info.Name, err) + } + } ref, err := c.handler.ContainerReference() if err != nil { // Ignore errors if the container is dead. diff --git a/manager/container_test.go b/manager/container_test.go index b1b31d03..1d23a506 100644 --- a/manager/container_test.go +++ b/manager/container_test.go @@ -31,9 +31,13 @@ import ( const containerName = "/container" -// Create a containerData instance for a test. Optionsl storage driver may be specified (one is made otherwise). -func newTestContainerData(t *testing.T) (*containerData, *container.MockContainerHandler, *stest.MockStorageDriver) { +// Create a containerData instance for a test. +func setupContainerData(t *testing.T, spec info.ContainerSpec) (*containerData, *container.MockContainerHandler, *stest.MockStorageDriver) { mockHandler := container.NewMockContainerHandler(containerName) + mockHandler.On("GetSpec").Return( + spec, + nil, + ) mockDriver := &stest.MockStorageDriver{} ret, err := newContainerData(containerName, mockDriver, mockHandler, nil, false) if err != nil { @@ -42,6 +46,13 @@ func newTestContainerData(t *testing.T) (*containerData, *container.MockContaine return ret, mockHandler, mockDriver } +// Create a containerData instance for a test and add a default GetSpec mock. +func newTestContainerData(t *testing.T) (*containerData, *container.MockContainerHandler, *stest.MockStorageDriver) { + spec := itest.GenerateRandomContainerSpec(4) + ret, mockHandler, mockDriver := setupContainerData(t, spec) + return ret, mockHandler, mockDriver +} + func TestUpdateSubcontainers(t *testing.T) { subcontainers := []info.ContainerReference{ {Name: "/container/ee0103"}, @@ -146,11 +157,7 @@ func TestGetInfo(t *testing.T) { {Name: "/container/abcd"}, {Name: "/container/something"}, } - cd, mockHandler, _ := newTestContainerData(t) - mockHandler.On("GetSpec").Return( - spec, - nil, - ) + cd, mockHandler, _ := setupContainerData(t, spec) mockHandler.On("ListContainers", container.ListSelf).Return( subcontainers, nil, diff --git a/manager/manager_test.go b/manager/manager_test.go index bbd6e1cb..2e380ce2 100644 --- a/manager/manager_test.go +++ b/manager/manager_test.go @@ -50,6 +50,11 @@ func createManagerAndAddContainers( if ret, ok := mif.(*manager); ok { for _, name := range containers { mockHandler := container.NewMockContainerHandler(name) + spec := itest.GenerateRandomContainerSpec(4) + mockHandler.On("GetSpec").Return( + spec, + nil, + ).Once() cont, err := newContainerData(name, driver, mockHandler, nil, false) if err != nil { t.Fatal(err) diff --git a/summary/percentiles.go b/summary/percentiles.go index 35e9fd01..01b70b7a 100644 --- a/summary/percentiles.go +++ b/summary/percentiles.go @@ -45,7 +45,7 @@ func (self uint64Slice) Get90Percentile() uint64 { idx, frac := math.Modf(n) index := int(idx) percentile := float64(self[index-1]) - if index > 1 || index < count { + if index > 1 && index < count { percentile += frac * float64(self[index]-self[index-1]) } return uint64(percentile)