123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 |
- // 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 (
- "fmt"
- "time"
- "github.com/google/cadvisor/info/v1"
- "k8s.io/klog"
- )
- func machineFsStatsFromV1(fsStats []v1.FsStats) []MachineFsStats {
- var result []MachineFsStats
- for i := range fsStats {
- stat := fsStats[i]
- readDuration := time.Millisecond * time.Duration(stat.ReadTime)
- writeDuration := time.Millisecond * time.Duration(stat.WriteTime)
- ioDuration := time.Millisecond * time.Duration(stat.IoTime)
- weightedDuration := time.Millisecond * time.Duration(stat.WeightedIoTime)
- machineFsStat := MachineFsStats{
- Device: stat.Device,
- Type: stat.Type,
- Capacity: &stat.Limit,
- Usage: &stat.Usage,
- Available: &stat.Available,
- DiskStats: DiskStats{
- ReadsCompleted: &stat.ReadsCompleted,
- ReadsMerged: &stat.ReadsMerged,
- SectorsRead: &stat.SectorsRead,
- ReadDuration: &readDuration,
- WritesCompleted: &stat.WritesCompleted,
- WritesMerged: &stat.WritesMerged,
- SectorsWritten: &stat.SectorsWritten,
- WriteDuration: &writeDuration,
- IoInProgress: &stat.IoInProgress,
- IoDuration: &ioDuration,
- WeightedIoDuration: &weightedDuration,
- },
- }
- if stat.HasInodes {
- machineFsStat.InodesFree = &stat.InodesFree
- }
- result = append(result, machineFsStat)
- }
- return result
- }
- func MachineStatsFromV1(cont *v1.ContainerInfo) []MachineStats {
- var stats []MachineStats
- var last *v1.ContainerStats
- for i := range cont.Stats {
- val := cont.Stats[i]
- stat := MachineStats{
- Timestamp: val.Timestamp,
- }
- if cont.Spec.HasCpu {
- stat.Cpu = &val.Cpu
- cpuInst, err := InstCpuStats(last, val)
- if err != nil {
- klog.Warningf("Could not get instant cpu stats: %v", err)
- } else {
- stat.CpuInst = cpuInst
- }
- last = val
- }
- if cont.Spec.HasMemory {
- stat.Memory = &val.Memory
- }
- if cont.Spec.HasNetwork {
- stat.Network = &NetworkStats{
- // FIXME: Use reflection instead.
- Tcp: TcpStat(val.Network.Tcp),
- Tcp6: TcpStat(val.Network.Tcp6),
- Interfaces: val.Network.Interfaces,
- }
- }
- if cont.Spec.HasFilesystem {
- stat.Filesystem = machineFsStatsFromV1(val.Filesystem)
- }
- // TODO(rjnagal): Handle load stats.
- stats = append(stats, stat)
- }
- return stats
- }
- func ContainerStatsFromV1(containerName string, spec *v1.ContainerSpec, stats []*v1.ContainerStats) []*ContainerStats {
- newStats := make([]*ContainerStats, 0, len(stats))
- var last *v1.ContainerStats
- for _, val := range stats {
- stat := &ContainerStats{
- Timestamp: val.Timestamp,
- }
- if spec.HasCpu {
- stat.Cpu = &val.Cpu
- cpuInst, err := InstCpuStats(last, val)
- if err != nil {
- klog.Warningf("Could not get instant cpu stats: %v", err)
- } else {
- stat.CpuInst = cpuInst
- }
- last = val
- }
- if spec.HasMemory {
- stat.Memory = &val.Memory
- }
- if spec.HasNetwork {
- // TODO: Handle TcpStats
- stat.Network = &NetworkStats{
- Tcp: TcpStat(val.Network.Tcp),
- Tcp6: TcpStat(val.Network.Tcp6),
- Interfaces: val.Network.Interfaces,
- }
- }
- if spec.HasFilesystem {
- if len(val.Filesystem) == 1 {
- stat.Filesystem = &FilesystemStats{
- TotalUsageBytes: &val.Filesystem[0].Usage,
- BaseUsageBytes: &val.Filesystem[0].BaseUsage,
- InodeUsage: &val.Filesystem[0].Inodes,
- }
- } else if len(val.Filesystem) > 1 && containerName != "/" {
- // Cannot handle multiple devices per container.
- klog.V(4).Infof("failed to handle multiple devices for container %s. Skipping Filesystem stats", containerName)
- }
- }
- if spec.HasDiskIo {
- stat.DiskIo = &val.DiskIo
- }
- if spec.HasCustomMetrics {
- stat.CustomMetrics = val.CustomMetrics
- }
- if len(val.Accelerators) > 0 {
- stat.Accelerators = val.Accelerators
- }
- // TODO(rjnagal): Handle load stats.
- newStats = append(newStats, stat)
- }
- return newStats
- }
- func DeprecatedStatsFromV1(cont *v1.ContainerInfo) []DeprecatedContainerStats {
- stats := make([]DeprecatedContainerStats, 0, len(cont.Stats))
- var last *v1.ContainerStats
- for _, val := range cont.Stats {
- stat := DeprecatedContainerStats{
- Timestamp: val.Timestamp,
- HasCpu: cont.Spec.HasCpu,
- HasMemory: cont.Spec.HasMemory,
- HasNetwork: cont.Spec.HasNetwork,
- HasFilesystem: cont.Spec.HasFilesystem,
- HasDiskIo: cont.Spec.HasDiskIo,
- HasCustomMetrics: cont.Spec.HasCustomMetrics,
- }
- if stat.HasCpu {
- stat.Cpu = val.Cpu
- cpuInst, err := InstCpuStats(last, val)
- if err != nil {
- klog.Warningf("Could not get instant cpu stats: %v", err)
- } else {
- stat.CpuInst = cpuInst
- }
- last = val
- }
- if stat.HasMemory {
- stat.Memory = val.Memory
- }
- if stat.HasNetwork {
- stat.Network.Interfaces = val.Network.Interfaces
- }
- if stat.HasFilesystem {
- stat.Filesystem = val.Filesystem
- }
- if stat.HasDiskIo {
- stat.DiskIo = val.DiskIo
- }
- if stat.HasCustomMetrics {
- stat.CustomMetrics = val.CustomMetrics
- }
- // TODO(rjnagal): Handle load stats.
- stats = append(stats, stat)
- }
- return stats
- }
- func InstCpuStats(last, cur *v1.ContainerStats) (*CpuInstStats, error) {
- if last == nil {
- return nil, nil
- }
- if !cur.Timestamp.After(last.Timestamp) {
- return nil, fmt.Errorf("container stats move backwards in time")
- }
- if len(last.Cpu.Usage.PerCpu) != len(cur.Cpu.Usage.PerCpu) {
- return nil, fmt.Errorf("different number of cpus")
- }
- timeDelta := cur.Timestamp.Sub(last.Timestamp)
- // Nanoseconds to gain precision and avoid having zero seconds if the
- // difference between the timestamps is just under a second
- timeDeltaNs := uint64(timeDelta.Nanoseconds())
- convertToRate := func(lastValue, curValue uint64) (uint64, error) {
- if curValue < lastValue {
- return 0, fmt.Errorf("cumulative stats decrease")
- }
- valueDelta := curValue - lastValue
- // Use float64 to keep precision
- return uint64(float64(valueDelta) / float64(timeDeltaNs) * 1e9), nil
- }
- total, err := convertToRate(last.Cpu.Usage.Total, cur.Cpu.Usage.Total)
- if err != nil {
- return nil, err
- }
- percpu := make([]uint64, len(last.Cpu.Usage.PerCpu))
- for i := range percpu {
- var err error
- percpu[i], err = convertToRate(last.Cpu.Usage.PerCpu[i], cur.Cpu.Usage.PerCpu[i])
- if err != nil {
- return nil, err
- }
- }
- user, err := convertToRate(last.Cpu.Usage.User, cur.Cpu.Usage.User)
- if err != nil {
- return nil, err
- }
- system, err := convertToRate(last.Cpu.Usage.System, cur.Cpu.Usage.System)
- if err != nil {
- return nil, err
- }
- return &CpuInstStats{
- Usage: CpuInstUsage{
- Total: total,
- PerCpu: percpu,
- User: user,
- System: system,
- },
- }, nil
- }
- // Get V2 container spec from v1 container info.
- func ContainerSpecFromV1(specV1 *v1.ContainerSpec, aliases []string, namespace string) ContainerSpec {
- specV2 := ContainerSpec{
- CreationTime: specV1.CreationTime,
- HasCpu: specV1.HasCpu,
- HasMemory: specV1.HasMemory,
- HasFilesystem: specV1.HasFilesystem,
- HasNetwork: specV1.HasNetwork,
- HasDiskIo: specV1.HasDiskIo,
- HasCustomMetrics: specV1.HasCustomMetrics,
- Image: specV1.Image,
- Labels: specV1.Labels,
- Envs: specV1.Envs,
- }
- 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
- }
- if specV1.HasCustomMetrics {
- specV2.CustomMetrics = specV1.CustomMetrics
- }
- specV2.Aliases = aliases
- specV2.Namespace = namespace
- return specV2
- }
|