From bce54ce3f5e9287cc053c8043583bb2437eb523e Mon Sep 17 00:00:00 2001 From: Victor Marmol Date: Mon, 4 May 2015 15:16:18 -0700 Subject: [PATCH] Run custom collectors in container housekeeping. This will allow us to register and run custom collectors for each container. --- manager/container.go | 30 ++++++++++++++++++++++++------ manager/container_test.go | 3 ++- manager/manager.go | 8 +++++++- manager/manager_test.go | 3 ++- 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/manager/container.go b/manager/container.go index 1d77adcf..ed62dbdc 100644 --- a/manager/container.go +++ b/manager/container.go @@ -24,6 +24,7 @@ import ( "github.com/docker/docker/pkg/units" "github.com/golang/glog" + "github.com/google/cadvisor/collector" "github.com/google/cadvisor/container" info "github.com/google/cadvisor/info/v1" "github.com/google/cadvisor/info/v2" @@ -63,6 +64,9 @@ type containerData struct { // Tells the container to stop. stop chan bool + + // Runs custom metric collectors. + collectorManager collector.CollectorManager } func (c *containerData) Start() error { @@ -109,7 +113,7 @@ func (c *containerData) DerivedStats() (v2.DerivedStats, error) { return c.summaryReader.DerivedStats() } -func newContainerData(containerName string, memoryStorage *memory.InMemoryStorage, handler container.ContainerHandler, loadReader cpuload.CpuLoadReader, logUsage bool) (*containerData, error) { +func newContainerData(containerName string, memoryStorage *memory.InMemoryStorage, handler container.ContainerHandler, loadReader cpuload.CpuLoadReader, logUsage bool, collectorManager collector.CollectorManager) (*containerData, error) { if memoryStorage == nil { return nil, fmt.Errorf("nil memory storage") } @@ -129,6 +133,7 @@ func newContainerData(containerName string, memoryStorage *memory.InMemoryStorag logUsage: logUsage, loadAvg: -1.0, // negative value indicates uninitialized. stop: make(chan bool, 1), + collectorManager: collectorManager, } cont.info.ContainerReference = ref @@ -172,6 +177,7 @@ func (self *containerData) nextHousekeeping(lastHousekeeping time.Time) time.Tim return lastHousekeeping.Add(self.housekeepingInterval) } +// TODO(vmarmol): Implement stats collecting as a custom collector. func (c *containerData) housekeeping() { // Long housekeeping is either 100ms or half of the housekeeping interval. longHousekeeping := 100 * time.Millisecond @@ -226,12 +232,24 @@ func (c *containerData) housekeeping() { } } - // Schedule the next housekeeping. Sleep until that time. - nextHousekeeping := c.nextHousekeeping(lastHousekeeping) - if time.Now().Before(nextHousekeeping) { - time.Sleep(nextHousekeeping.Sub(time.Now())) + // Run custom collectors. + nextCollectionTime, err := c.collectorManager.Collect() + if err != nil && c.allowErrorLogging() { + glog.Warningf("[%s] Collection failed: %v", c.info.Name, err) } - lastHousekeeping = nextHousekeeping + + // Next housekeeping is the first of the stats or the custom collector's housekeeping. + nextHousekeeping := c.nextHousekeeping(lastHousekeeping) + next := nextHousekeeping + if !nextCollectionTime.IsZero() && nextCollectionTime.Before(nextHousekeeping) { + next = nextCollectionTime + } + + // Schedule the next housekeeping. Sleep until that time. + if time.Now().Before(next) { + time.Sleep(next.Sub(time.Now())) + } + lastHousekeeping = next } } diff --git a/manager/container_test.go b/manager/container_test.go index bd73a119..bb5bbb9f 100644 --- a/manager/container_test.go +++ b/manager/container_test.go @@ -22,6 +22,7 @@ import ( "testing" "time" + "github.com/google/cadvisor/collector" "github.com/google/cadvisor/container" info "github.com/google/cadvisor/info/v1" itest "github.com/google/cadvisor/info/v1/test" @@ -40,7 +41,7 @@ func setupContainerData(t *testing.T, spec info.ContainerSpec) (*containerData, nil, ) memoryStorage := memory.New(60, nil) - ret, err := newContainerData(containerName, memoryStorage, mockHandler, nil, false) + ret, err := newContainerData(containerName, memoryStorage, mockHandler, nil, false, &collector.FakeCollectorManager{}) if err != nil { t.Fatal(err) } diff --git a/manager/manager.go b/manager/manager.go index 3d5e02e2..b078ceaa 100644 --- a/manager/manager.go +++ b/manager/manager.go @@ -27,6 +27,7 @@ import ( "github.com/docker/libcontainer/cgroups" "github.com/golang/glog" + "github.com/google/cadvisor/collector" "github.com/google/cadvisor/container" "github.com/google/cadvisor/container/docker" "github.com/google/cadvisor/container/raw" @@ -650,8 +651,13 @@ func (m *manager) createContainer(containerName string) error { glog.V(4).Infof("ignoring container %q", containerName) return nil } + // TODO(vmarmol): Register collectors. + collectorManager, err := collector.NewCollectorManager() + if err != nil { + return err + } logUsage := *logCadvisorUsage && containerName == m.cadvisorContainer - cont, err := newContainerData(containerName, m.memoryStorage, handler, m.loadReader, logUsage) + cont, err := newContainerData(containerName, m.memoryStorage, handler, m.loadReader, logUsage, collectorManager) if err != nil { return err } diff --git a/manager/manager_test.go b/manager/manager_test.go index 382f71ca..89cfe7aa 100644 --- a/manager/manager_test.go +++ b/manager/manager_test.go @@ -22,6 +22,7 @@ import ( "testing" "time" + "github.com/google/cadvisor/collector" "github.com/google/cadvisor/container" "github.com/google/cadvisor/container/docker" info "github.com/google/cadvisor/info/v1" @@ -52,7 +53,7 @@ func createManagerAndAddContainers( spec, nil, ).Once() - cont, err := newContainerData(name, memoryStorage, mockHandler, nil, false) + cont, err := newContainerData(name, memoryStorage, mockHandler, nil, false, &collector.FakeCollectorManager{}) if err != nil { t.Fatal(err) }