From 7201af3ca5227b0266fb6cde9ba6acc49f3811f0 Mon Sep 17 00:00:00 2001 From: Rohit Jnagal Date: Wed, 18 Feb 2015 18:07:38 +0000 Subject: [PATCH] Expose a minimal 2.0 API with the first summary endpoint. Right now, we just do raw container name. More types to follow. We'll re-do the older endpoint in 2.0 before we publish it. --- api/versions.go | 54 +++++++++++++++++++++++++++++++++++++------- manager/container.go | 7 ++++++ manager/manager.go | 17 ++++++++++++++ summary/summary.go | 3 ++- 4 files changed, 72 insertions(+), 9 deletions(-) diff --git a/api/versions.go b/api/versions.go index e726a187..a3038d90 100644 --- a/api/versions.go +++ b/api/versions.go @@ -28,6 +28,7 @@ const ( subcontainersApi = "subcontainers" machineApi = "machine" dockerApi = "docker" + summaryApi = "summary" ) // Interface for a cAdvisor API version @@ -47,7 +48,8 @@ func getApiVersions() []ApiVersion { v1_0 := &version1_0{} v1_1 := newVersion1_1(v1_0) v1_2 := newVersion1_2(v1_1) - return []ApiVersion{v1_0, v1_1, v1_2} + v2_0 := newVersion2_0(v1_2) + return []ApiVersion{v1_0, v1_1, v1_2, v2_0} } // API v1.0 @@ -64,8 +66,8 @@ func (self *version1_0) SupportedRequestTypes() []string { } func (self *version1_0) HandleRequest(requestType string, request []string, m manager.Manager, w http.ResponseWriter, r *http.Request) error { - switch { - case requestType == machineApi: + switch requestType { + case machineApi: glog.V(2).Infof("Api - Machine") // Get the MachineInfo @@ -78,7 +80,7 @@ func (self *version1_0) HandleRequest(requestType string, request []string, m ma if err != nil { return err } - case requestType == containersApi: + case containersApi: containerName := getContainerName(request) glog.V(2).Infof("Api - Container(%s)", containerName) @@ -127,8 +129,8 @@ func (self *version1_1) SupportedRequestTypes() []string { } func (self *version1_1) HandleRequest(requestType string, request []string, m manager.Manager, w http.ResponseWriter, r *http.Request) error { - switch { - case requestType == subcontainersApi: + switch requestType { + case subcontainersApi: containerName := getContainerName(request) glog.V(2).Infof("Api - Subcontainers(%s)", containerName) @@ -177,8 +179,8 @@ func (self *version1_2) SupportedRequestTypes() []string { } func (self *version1_2) HandleRequest(requestType string, request []string, m manager.Manager, w http.ResponseWriter, r *http.Request) error { - switch { - case requestType == dockerApi: + switch requestType { + case dockerApi: glog.V(2).Infof("Api - Docker(%v)", request) // Get the query request. @@ -223,3 +225,39 @@ func (self *version1_2) HandleRequest(requestType string, request []string, m ma return self.baseVersion.HandleRequest(requestType, request, m, w, r) } } + +// v2.0 builds on v1.2 +type version2_0 struct { + baseVersion *version1_2 +} + +func newVersion2_0(v *version1_2) *version2_0 { + return &version2_0{ + baseVersion: v, + } +} + +func (self *version2_0) Version() string { + return "v2.0" +} + +func (self *version2_0) SupportedRequestTypes() []string { + return append(self.baseVersion.SupportedRequestTypes(), summaryApi) +} + +func (self *version2_0) HandleRequest(requestType string, request []string, m manager.Manager, w http.ResponseWriter, r *http.Request) error { + switch requestType { + case summaryApi: + containerName := getContainerName(request) + glog.V(2).Infof("Api - Summary(%v)", containerName) + + stats, err := m.GetContainerDerivedStats(containerName) + if err != nil { + return err + } + + return writeResult(stats, w) + default: + return self.baseVersion.HandleRequest(requestType, request, m, w, r) + } +} diff --git a/manager/container.go b/manager/container.go index 78d95ae3..53f746df 100644 --- a/manager/container.go +++ b/manager/container.go @@ -100,6 +100,13 @@ func (c *containerData) GetInfo() (*containerInfo, error) { return &c.info, nil } +func (c *containerData) DerivedStats() (info.DerivedStats, error) { + if c.summaryReader == nil { + return info.DerivedStats{}, fmt.Errorf("derived stats not enabled for container %q", c.info.Name) + } + return c.summaryReader.DerivedStats() +} + func newContainerData(containerName string, driver storage.StorageDriver, handler container.ContainerHandler, loadReader cpuload.CpuLoadReader, logUsage bool) (*containerData, error) { if driver == nil { return nil, fmt.Errorf("nil storage driver") diff --git a/manager/manager.go b/manager/manager.go index ff5f7615..bbdc268e 100644 --- a/manager/manager.go +++ b/manager/manager.go @@ -58,6 +58,9 @@ type Manager interface { // Gets information about a specific Docker container. The specified name is within the Docker namespace. DockerContainer(dockerName string, query *info.ContainerInfoRequest) (info.ContainerInfo, error) + // Get derived stats for a container. + GetContainerDerivedStats(containerName string) (info.DerivedStats, error) + // Get information about the machine. GetMachineInfo() (*info.MachineInfo, error) @@ -364,6 +367,20 @@ func (self *manager) containerDataSliceToContainerInfoSlice(containers []*contai return output, nil } +func (self *manager) GetContainerDerivedStats(containerName string) (info.DerivedStats, error) { + var ok bool + var cont *containerData + func() { + self.containersLock.RLock() + defer self.containersLock.RUnlock() + cont, ok = self.containers[namespacedContainerName{Name: containerName}] + }() + if !ok { + return info.DerivedStats{}, fmt.Errorf("unknown container %q", containerName) + } + return cont.DerivedStats() +} + func (m *manager) GetMachineInfo() (*info.MachineInfo, error) { // Copy and return the MachineInfo. return &m.machineInfo, nil diff --git a/summary/summary.go b/summary/summary.go index d8847977..4d0012fa 100644 --- a/summary/summary.go +++ b/summary/summary.go @@ -57,6 +57,7 @@ type StatsSummary struct { // stats are updated. func (s *StatsSummary) AddSample(stat info.ContainerStats) error { sample := secondSample{} + sample.Timestamp = stat.Timestamp if s.available.Cpu { sample.Cpu = stat.Cpu.Usage.Total } @@ -119,7 +120,7 @@ func (s *StatsSummary) getDerivedUsage(n int) (info.Usage, error) { // We generate derived stats even with partial data. usage := GetDerivedPercentiles(samples) // Assumes we have equally placed minute samples. - usage.PercentComplete = int32(numSamples / n) + usage.PercentComplete = int32(numSamples * 100 / n) return usage, nil }