Merge pull request #559 from rjnagal/version

Move derived stats to v2. Add v2 container spec.
This commit is contained in:
Victor Marmol 2015-03-04 10:53:01 -08:00
commit d3754abee1
11 changed files with 140 additions and 59 deletions

View File

@ -21,6 +21,7 @@ import (
"github.com/golang/glog"
"github.com/google/cadvisor/events"
info "github.com/google/cadvisor/info/v1"
"github.com/google/cadvisor/info/v2"
"github.com/google/cadvisor/manager"
)
@ -330,8 +331,29 @@ func (self *version2_0) HandleRequest(requestType string, request []string, m ma
if err != nil {
return err
}
return writeResult(spec, w)
specV2 := convertSpec(spec)
return writeResult(specV2, w)
default:
return self.baseVersion.HandleRequest(requestType, request, m, w, r)
}
}
// Convert container spec from v1 to v2.
func convertSpec(specV1 info.ContainerSpec) v2.ContainerSpec {
specV2 := v2.ContainerSpec{
CreationTime: specV1.CreationTime,
HasCpu: specV1.HasCpu,
HasMemory: specV1.HasMemory,
}
if specV1.HasCpu {
specV2.Cpu.Limit = specV1.Cpu.Limit
specV2.Cpu.MaxLimit = specV1.Cpu.MaxLimit
specV2.Cpu.Mask = specV1.Cpu.Mask
}
if specV1.HasMemory {
specV2.Memory.Limit = specV1.Memory.Limit
specV2.Memory.Reservation = specV1.Memory.Reservation
specV2.Memory.SwapLimit = specV1.Memory.SwapLimit
}
return specV2
}

View File

@ -455,47 +455,3 @@ func calculateCpuUsage(prev, cur uint64) uint64 {
}
return cur - prev
}
type Percentiles struct {
// Indicates whether the stats are present or not.
// If true, values below do not have any data.
Present bool `json:"present"`
// Average over the collected sample.
Mean uint64 `json:"mean"`
// Max seen over the collected sample.
Max uint64 `json:"max"`
// 90th percentile over the collected sample.
Ninety uint64 `json:"ninety"`
}
type Usage struct {
// Indicates amount of data available [0-100].
// If we have data for half a day, we'll still process DayUsage,
// but set PercentComplete to 50.
PercentComplete int32 `json:"percent_complete"`
// Mean, Max, and 90p cpu rate value in milliCpus/seconds. Converted to milliCpus to avoid floats.
Cpu Percentiles `json:"cpu"`
// Mean, Max, and 90p memory size in bytes.
Memory Percentiles `json:"memory"`
}
// latest sample collected for a container.
type InstantUsage struct {
// cpu rate in cpu milliseconds/second.
Cpu uint64 `json:"cpu"`
// Memory usage in bytes.
Memory uint64 `json:"memory"`
}
type DerivedStats struct {
// Time of generation of these stats.
Timestamp time.Time `json:"timestamp"`
// Latest instantaneous sample.
LatestUsage InstantUsage `json:"latest_usage"`
// Percentiles in last observed minute.
MinuteUsage Usage `json:"minute_usage"`
// Percentile in last hour.
HourUsage Usage `json:"hour_usage"`
// Percentile in last day.
DayUsage Usage `json:"day_usage"`
}

99
info/v2/container.go Normal file
View File

@ -0,0 +1,99 @@
// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v2
import (
"time"
)
type CpuSpec struct {
// Requested cpu shares. Default is 1024.
Limit uint64 `json:"limit"`
// Requested cpu hard limit. Default is unlimited (0).
// Units: milli-cpus.
MaxLimit uint64 `json:"max_limit"`
// Cpu affinity mask.
// TODO(rjnagal): Add a library to convert mask string to set of cpu bitmask.
Mask string `json:"mask,omitempty"`
}
type MemorySpec struct {
// The amount of memory requested. Default is unlimited (-1).
// Units: bytes.
Limit uint64 `json:"limit,omitempty"`
// The amount of guaranteed memory. Default is 0.
// Units: bytes.
Reservation uint64 `json:"reservation,omitempty"`
// The amount of swap space requested. Default is unlimited (-1).
// Units: bytes.
SwapLimit uint64 `json:"swap_limit,omitempty"`
}
type ContainerSpec struct {
// Time at which the container was created.
CreationTime time.Time `json:"creation_time,omitempty"`
HasCpu bool `json:"has_cpu"`
Cpu CpuSpec `json:"cpu,omitempty"`
HasMemory bool `json:"has_memory"`
Memory MemorySpec `json:"memory,omitempty"`
}
type Percentiles struct {
// Indicates whether the stats are present or not.
// If true, values below do not have any data.
Present bool `json:"present"`
// Average over the collected sample.
Mean uint64 `json:"mean"`
// Max seen over the collected sample.
Max uint64 `json:"max"`
// 90th percentile over the collected sample.
Ninety uint64 `json:"ninety"`
}
type Usage struct {
// Indicates amount of data available [0-100].
// If we have data for half a day, we'll still process DayUsage,
// but set PercentComplete to 50.
PercentComplete int32 `json:"percent_complete"`
// Mean, Max, and 90p cpu rate value in milliCpus/seconds. Converted to milliCpus to avoid floats.
Cpu Percentiles `json:"cpu"`
// Mean, Max, and 90p memory size in bytes.
Memory Percentiles `json:"memory"`
}
// latest sample collected for a container.
type InstantUsage struct {
// cpu rate in cpu milliseconds/second.
Cpu uint64 `json:"cpu"`
// Memory usage in bytes.
Memory uint64 `json:"memory"`
}
type DerivedStats struct {
// Time of generation of these stats.
Timestamp time.Time `json:"timestamp"`
// Latest instantaneous sample.
LatestUsage InstantUsage `json:"latest_usage"`
// Percentiles in last observed minute.
MinuteUsage Usage `json:"minute_usage"`
// Percentile in last hour.
HourUsage Usage `json:"hour_usage"`
// Percentile in last day.
DayUsage Usage `json:"day_usage"`
}

View File

@ -26,6 +26,7 @@ import (
"github.com/golang/glog"
"github.com/google/cadvisor/container"
info "github.com/google/cadvisor/info/v1"
"github.com/google/cadvisor/info/v2"
"github.com/google/cadvisor/storage/memory"
"github.com/google/cadvisor/summary"
"github.com/google/cadvisor/utils/cpuload"
@ -101,9 +102,9 @@ func (c *containerData) GetInfo() (*containerInfo, error) {
return &c.info, nil
}
func (c *containerData) DerivedStats() (info.DerivedStats, error) {
func (c *containerData) DerivedStats() (v2.DerivedStats, error) {
if c.summaryReader == nil {
return info.DerivedStats{}, fmt.Errorf("derived stats not enabled for container %q", c.info.Name)
return v2.DerivedStats{}, fmt.Errorf("derived stats not enabled for container %q", c.info.Name)
}
return c.summaryReader.DerivedStats()
}

View File

@ -31,6 +31,7 @@ import (
"github.com/google/cadvisor/container/raw"
"github.com/google/cadvisor/events"
info "github.com/google/cadvisor/info/v1"
"github.com/google/cadvisor/info/v2"
"github.com/google/cadvisor/storage/memory"
"github.com/google/cadvisor/utils/cpuload"
"github.com/google/cadvisor/utils/oomparser"
@ -65,7 +66,7 @@ type Manager interface {
GetContainerSpec(containerName string) (info.ContainerSpec, error)
// Get derived stats for a container.
GetContainerDerivedStats(containerName string) (info.DerivedStats, error)
GetContainerDerivedStats(containerName string) (v2.DerivedStats, error)
// Get information about the machine.
GetMachineInfo() (*info.MachineInfo, error)
@ -424,7 +425,7 @@ func (self *manager) containerDataSliceToContainerInfoSlice(containers []*contai
return output, nil
}
func (self *manager) GetContainerDerivedStats(containerName string) (info.DerivedStats, error) {
func (self *manager) GetContainerDerivedStats(containerName string) (v2.DerivedStats, error) {
var ok bool
var cont *containerData
func() {
@ -433,7 +434,7 @@ func (self *manager) GetContainerDerivedStats(containerName string) (info.Derive
cont, ok = self.containers[namespacedContainerName{Name: containerName}]
}()
if !ok {
return info.DerivedStats{}, fmt.Errorf("unknown container %q", containerName)
return v2.DerivedStats{}, fmt.Errorf("unknown container %q", containerName)
}
return cont.DerivedStats()
}

View File

@ -17,6 +17,7 @@ package manager
import (
"github.com/google/cadvisor/events"
info "github.com/google/cadvisor/info/v1"
"github.com/google/cadvisor/info/v2"
"github.com/stretchr/testify/mock"
)
@ -59,9 +60,9 @@ func (c *ManagerMock) GetContainerSpec(containerName string) (info.ContainerSpec
return args.Get(0).(info.ContainerSpec), args.Error(1)
}
func (c *ManagerMock) GetContainerDerivedStats(containerName string) (info.DerivedStats, error) {
func (c *ManagerMock) GetContainerDerivedStats(containerName string) (v2.DerivedStats, error) {
args := c.Called(containerName)
return args.Get(0).(info.DerivedStats), args.Error(1)
return args.Get(0).(v2.DerivedStats), args.Error(1)
}
func (c *ManagerMock) WatchForEvents(queryuest *events.Request, passedChannel chan *events.Event) error {

View File

@ -15,7 +15,7 @@
package summary
import (
info "github.com/google/cadvisor/info/v1"
info "github.com/google/cadvisor/info/v2"
)
// Manages a buffer of usage samples.

View File

@ -18,7 +18,7 @@ import (
"reflect"
"testing"
info "github.com/google/cadvisor/info/v1"
info "github.com/google/cadvisor/info/v2"
)
func createSample(i uint64) info.Usage {

View File

@ -22,7 +22,7 @@ import (
"sort"
"github.com/golang/glog"
info "github.com/google/cadvisor/info/v1"
info "github.com/google/cadvisor/info/v2"
)
const secondsToMilliSeconds = 1000

View File

@ -18,7 +18,7 @@ import (
"testing"
"time"
info "github.com/google/cadvisor/info/v1"
info "github.com/google/cadvisor/info/v2"
)
const Nanosecond = 1000000000

View File

@ -25,7 +25,8 @@ import (
"sync"
"time"
info "github.com/google/cadvisor/info/v1"
"github.com/google/cadvisor/info/v1"
info "github.com/google/cadvisor/info/v2"
)
// Usage fields we track for generating percentiles.
@ -56,7 +57,7 @@ type StatsSummary struct {
// Adds a new seconds sample.
// If enough seconds samples are collected, a minute sample is generated and derived
// stats are updated.
func (s *StatsSummary) AddSample(stat info.ContainerStats) error {
func (s *StatsSummary) AddSample(stat v1.ContainerStats) error {
sample := secondSample{}
sample.Timestamp = stat.Timestamp
if s.available.Cpu {
@ -168,7 +169,7 @@ func (s *StatsSummary) DerivedStats() (info.DerivedStats, error) {
return s.derivedStats, nil
}
func New(spec info.ContainerSpec) (*StatsSummary, error) {
func New(spec v1.ContainerSpec) (*StatsSummary, error) {
summary := StatsSummary{}
if spec.HasCpu {
summary.available.Cpu = true