From 55d167d1543cdea53b85e514f00a589a3ff56e77 Mon Sep 17 00:00:00 2001 From: Victor Marmol Date: Thu, 7 May 2015 15:37:52 -0700 Subject: [PATCH] Update cAdvisor dependency. - Better handling of time-based queries - Better handling of errors detecting machine topology Fixes #7906 --- Godeps/Godeps.json | 84 +++++++++---------- .../google/cadvisor/container/raw/handler.go | 6 +- .../google/cadvisor/events/handler_test.go | 6 +- .../google/cadvisor/manager/machine.go | 3 +- .../google/cadvisor/utils/timed_store.go | 48 +++++++---- 5 files changed, 83 insertions(+), 64 deletions(-) diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index fc021de5a28..176653abdf4 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -201,97 +201,97 @@ }, { "ImportPath": "github.com/google/cadvisor/api", - "Comment": "0.13.0-22-ge3aa15a", - "Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356" + "Comment": "0.13.0-32-g832c6e9", + "Rev": "832c6e94c325ecdf05da884880c503be45594818" }, { "ImportPath": "github.com/google/cadvisor/collector", - "Comment": "0.13.0-22-ge3aa15a", - "Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356" + "Comment": "0.13.0-32-g832c6e9", + "Rev": "832c6e94c325ecdf05da884880c503be45594818" }, { "ImportPath": "github.com/google/cadvisor/container", - "Comment": "0.13.0-22-ge3aa15a", - "Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356" + "Comment": "0.13.0-32-g832c6e9", + "Rev": "832c6e94c325ecdf05da884880c503be45594818" }, { "ImportPath": "github.com/google/cadvisor/events", - "Comment": "0.13.0-22-ge3aa15a", - "Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356" + "Comment": "0.13.0-32-g832c6e9", + "Rev": "832c6e94c325ecdf05da884880c503be45594818" }, { "ImportPath": "github.com/google/cadvisor/fs", - "Comment": "0.13.0-22-ge3aa15a", - "Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356" + "Comment": "0.13.0-32-g832c6e9", + "Rev": "832c6e94c325ecdf05da884880c503be45594818" }, { "ImportPath": "github.com/google/cadvisor/healthz", - "Comment": "0.13.0-22-ge3aa15a", - "Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356" + "Comment": "0.13.0-32-g832c6e9", + "Rev": "832c6e94c325ecdf05da884880c503be45594818" }, { "ImportPath": "github.com/google/cadvisor/http", - "Comment": "0.13.0-22-ge3aa15a", - "Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356" + "Comment": "0.13.0-32-g832c6e9", + "Rev": "832c6e94c325ecdf05da884880c503be45594818" }, { "ImportPath": "github.com/google/cadvisor/info/v1", - "Comment": "0.13.0-22-ge3aa15a", - "Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356" + "Comment": "0.13.0-32-g832c6e9", + "Rev": "832c6e94c325ecdf05da884880c503be45594818" }, { "ImportPath": "github.com/google/cadvisor/info/v2", - "Comment": "0.13.0-22-ge3aa15a", - "Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356" + "Comment": "0.13.0-32-g832c6e9", + "Rev": "832c6e94c325ecdf05da884880c503be45594818" }, { "ImportPath": "github.com/google/cadvisor/manager", - "Comment": "0.13.0-22-ge3aa15a", - "Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356" + "Comment": "0.13.0-32-g832c6e9", + "Rev": "832c6e94c325ecdf05da884880c503be45594818" }, { "ImportPath": "github.com/google/cadvisor/metrics", - "Comment": "0.13.0-22-ge3aa15a", - "Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356" + "Comment": "0.13.0-32-g832c6e9", + "Rev": "832c6e94c325ecdf05da884880c503be45594818" }, { "ImportPath": "github.com/google/cadvisor/pages", - "Comment": "0.13.0-22-ge3aa15a", - "Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356" + "Comment": "0.13.0-32-g832c6e9", + "Rev": "832c6e94c325ecdf05da884880c503be45594818" }, { "ImportPath": "github.com/google/cadvisor/storage", - "Comment": "0.13.0-22-ge3aa15a", - "Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356" + "Comment": "0.13.0-32-g832c6e9", + "Rev": "832c6e94c325ecdf05da884880c503be45594818" }, { "ImportPath": "github.com/google/cadvisor/summary", - "Comment": "0.13.0-22-ge3aa15a", - "Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356" + "Comment": "0.13.0-32-g832c6e9", + "Rev": "832c6e94c325ecdf05da884880c503be45594818" }, { "ImportPath": "github.com/google/cadvisor/utils", - "Comment": "0.13.0-22-ge3aa15a", - "Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356" + "Comment": "0.13.0-32-g832c6e9", + "Rev": "832c6e94c325ecdf05da884880c503be45594818" }, { "ImportPath": "github.com/google/cadvisor/validate", - "Comment": "0.13.0-22-ge3aa15a", - "Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356" + "Comment": "0.13.0-32-g832c6e9", + "Rev": "832c6e94c325ecdf05da884880c503be45594818" }, { "ImportPath": "github.com/google/cadvisor/version", - "Comment": "0.13.0-22-ge3aa15a", - "Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356" + "Comment": "0.13.0-32-g832c6e9", + "Rev": "832c6e94c325ecdf05da884880c503be45594818" + }, + { + "ImportPath": "github.com/google/go-github/github", + "Rev": "930e6fdb8dc2b11458fdeb55b3cd68e5370a1a28" + }, + { + "ImportPath": "github.com/google/go-querystring/query", + "Rev": "547ef5ac979778feb2f760cdb5f4eae1a2207b86" }, - { - "ImportPath": "github.com/google/go-github/github", - "Rev": "930e6fdb8dc2b11458fdeb55b3cd68e5370a1a28" - }, - { - "ImportPath": "github.com/google/go-querystring/query", - "Rev": "547ef5ac979778feb2f760cdb5f4eae1a2207b86" - }, { "ImportPath": "github.com/google/gofuzz", "Rev": "bbcb9da2d746f8bdbd6a936686a0a6067ada0ec5" diff --git a/Godeps/_workspace/src/github.com/google/cadvisor/container/raw/handler.go b/Godeps/_workspace/src/github.com/google/cadvisor/container/raw/handler.go index 3d258e534f7..836d879a521 100644 --- a/Godeps/_workspace/src/github.com/google/cadvisor/container/raw/handler.go +++ b/Godeps/_workspace/src/github.com/google/cadvisor/container/raw/handler.go @@ -177,7 +177,11 @@ func (self *rawContainerHandler) GetSpec() (info.ContainerSpec, error) { now := time.Now() lowestTime := now for _, cgroupPath := range self.cgroupPaths { - // The modified time of the cgroup directory is when the container was created. + // The modified time of the cgroup directory changes whenever a subcontainer is created. + // eg. /docker will have creation time matching the creation of latest docker container. + // Use clone_children as a workaround as it isn't usually modified. It is only likely changed + // immediately after creating a container. + cgroupPath = path.Join(cgroupPath, "cgroup.clone_children") fi, err := os.Stat(cgroupPath) if err == nil && fi.ModTime().Before(lowestTime) { lowestTime = fi.ModTime() diff --git a/Godeps/_workspace/src/github.com/google/cadvisor/events/handler_test.go b/Godeps/_workspace/src/github.com/google/cadvisor/events/handler_test.go index 65b38897e4d..abda4cbcff0 100644 --- a/Godeps/_workspace/src/github.com/google/cadvisor/events/handler_test.go +++ b/Godeps/_workspace/src/github.com/google/cadvisor/events/handler_test.go @@ -170,8 +170,8 @@ func TestGetEventsForOneEvent(t *testing.T) { func TestGetEventsForTimePeriod(t *testing.T) { myEventHolder, myRequest, fakeEvent, fakeEvent2 := initializeScenario(t) - myRequest.StartTime = createOldTime(t).Add(-1 * time.Second * 10) - myRequest.EndTime = createOldTime(t).Add(time.Second * 10) + myRequest.StartTime = time.Now().Add(-1 * time.Second * 10) + myRequest.EndTime = time.Now().Add(time.Second * 10) myRequest.EventType[info.EventOom] = true myEventHolder.AddEvent(fakeEvent) @@ -181,7 +181,7 @@ func TestGetEventsForTimePeriod(t *testing.T) { assert.Nil(t, err) checkNumberOfEvents(t, 1, len(receivedEvents)) - ensureProperEventReturned(t, fakeEvent, receivedEvents[0]) + ensureProperEventReturned(t, fakeEvent2, receivedEvents[0]) } func TestGetEventsForNoTypeRequested(t *testing.T) { diff --git a/Godeps/_workspace/src/github.com/google/cadvisor/manager/machine.go b/Godeps/_workspace/src/github.com/google/cadvisor/manager/machine.go index c1927a44385..ea83fa19263 100644 --- a/Godeps/_workspace/src/github.com/google/cadvisor/manager/machine.go +++ b/Godeps/_workspace/src/github.com/google/cadvisor/manager/machine.go @@ -187,7 +187,8 @@ func getTopology(sysFs sysfs.SysFs, cpuinfo string) ([]info.Node, int, error) { for idx, node := range nodes { caches, err := sysinfo.GetCacheInfo(sysFs, node.Cores[0].Threads[0]) if err != nil { - return nil, -1, fmt.Errorf("failed to get cache information for node %d: %v", node.Id, err) + glog.Errorf("failed to get cache information for node %d: %v", node.Id, err) + continue } numThreadsPerCore := len(node.Cores[0].Threads) numThreadsPerNode := len(node.Cores) * numThreadsPerCore diff --git a/Godeps/_workspace/src/github.com/google/cadvisor/utils/timed_store.go b/Godeps/_workspace/src/github.com/google/cadvisor/utils/timed_store.go index cfd492361d6..70c310d321c 100644 --- a/Godeps/_workspace/src/github.com/google/cadvisor/utils/timed_store.go +++ b/Godeps/_workspace/src/github.com/google/cadvisor/utils/timed_store.go @@ -19,10 +19,24 @@ import ( "time" ) +type timedStoreDataSlice []timedStoreData + +func (t timedStoreDataSlice) Less(i, j int) bool { + return t[i].timestamp.Before(t[j].timestamp) +} + +func (t timedStoreDataSlice) Len() int { + return len(t) +} + +func (t timedStoreDataSlice) Swap(i, j int) { + t[i], t[j] = t[j], t[i] +} + // A time-based buffer for ContainerStats. // Holds information for a specific time period and/or a max number of items. type TimedStore struct { - buffer []timedStoreData + buffer timedStoreDataSlice age time.Duration maxItems int } @@ -36,7 +50,7 @@ type timedStoreData struct { // A maxItems value of -1 means no limit. func NewTimedStore(age time.Duration, maxItems int) *TimedStore { return &TimedStore{ - buffer: make([]timedStoreData, 0), + buffer: make(timedStoreDataSlice, 0), age: age, maxItems: maxItems, } @@ -44,7 +58,21 @@ func NewTimedStore(age time.Duration, maxItems int) *TimedStore { // Adds an element to the start of the buffer (removing one from the end if necessary). func (self *TimedStore) Add(timestamp time.Time, item interface{}) { - // Remove any elements before the eviction time. + // Remove any elements if over our max size. + if self.maxItems >= 0 && (len(self.buffer)+1) > self.maxItems { + startIndex := len(self.buffer) + 1 - self.maxItems + self.buffer = self.buffer[startIndex:] + } + // Add the new element first and sort. We can then remove an expired element, if required. + copied := item + self.buffer = append(self.buffer, timedStoreData{ + timestamp: timestamp, + data: copied, + }) + + sort.Sort(self.buffer) + // Remove any elements before eviction time. + // TODO(rjnagal): This is assuming that the added entry has timestamp close to now. evictTime := timestamp.Add(-self.age) index := sort.Search(len(self.buffer), func(index int) bool { return self.buffer[index].timestamp.After(evictTime) @@ -53,17 +81,6 @@ func (self *TimedStore) Add(timestamp time.Time, item interface{}) { self.buffer = self.buffer[index:] } - // Remove any elements if over our max size. - if self.maxItems >= 0 && (len(self.buffer)+1) > self.maxItems { - startIndex := len(self.buffer) + 1 - self.maxItems - self.buffer = self.buffer[startIndex:] - } - - copied := item - self.buffer = append(self.buffer, timedStoreData{ - timestamp: timestamp, - data: copied, - }) } // Returns up to maxResult elements in the specified time period (inclusive). @@ -80,9 +97,6 @@ func (self *TimedStore) InTimeRange(start, end time.Time, maxResults int) []inte maxResults = -1 } - // NOTE: Since we store the elments in descending timestamp order "start" will - // be a higher index than "end". - var startIndex int if start.IsZero() { // None specified, start at the beginning.