Add network stats to root container. Provides machine-level networking stats.
This commit is contained in:
parent
7e73bca3fb
commit
45334c6f71
@ -33,6 +33,7 @@ import (
|
|||||||
"github.com/google/cadvisor/fs"
|
"github.com/google/cadvisor/fs"
|
||||||
"github.com/google/cadvisor/info"
|
"github.com/google/cadvisor/info"
|
||||||
"github.com/google/cadvisor/utils"
|
"github.com/google/cadvisor/utils"
|
||||||
|
"github.com/google/cadvisor/utils/sysinfo"
|
||||||
)
|
)
|
||||||
|
|
||||||
type rawContainerHandler struct {
|
type rawContainerHandler struct {
|
||||||
@ -145,6 +146,18 @@ func readInt64(dirpath string, file string) uint64 {
|
|||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *rawContainerHandler) GetRootNetworkDevices() ([]info.NetInfo, error) {
|
||||||
|
nd := []info.NetInfo{}
|
||||||
|
if self.name == "/" {
|
||||||
|
mi, err := self.machineInfoFactory.GetMachineInfo()
|
||||||
|
if err != nil {
|
||||||
|
return nd, err
|
||||||
|
}
|
||||||
|
return mi.NetworkDevices, nil
|
||||||
|
}
|
||||||
|
return nd, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (self *rawContainerHandler) GetSpec() (info.ContainerSpec, error) {
|
func (self *rawContainerHandler) GetSpec() (info.ContainerSpec, error) {
|
||||||
var spec info.ContainerSpec
|
var spec info.ContainerSpec
|
||||||
|
|
||||||
@ -197,6 +210,15 @@ func (self *rawContainerHandler) GetSpec() (info.ContainerSpec, error) {
|
|||||||
if self.networkInterface != nil {
|
if self.networkInterface != nil {
|
||||||
spec.HasNetwork = true
|
spec.HasNetwork = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check physical network devices for root container.
|
||||||
|
nd, err := self.GetRootNetworkDevices()
|
||||||
|
if err != nil {
|
||||||
|
return spec, err
|
||||||
|
}
|
||||||
|
if len(nd) != 0 {
|
||||||
|
spec.HasNetwork = true
|
||||||
|
}
|
||||||
return spec, nil
|
return spec, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,6 +305,19 @@ func (self *rawContainerHandler) GetStats() (*info.ContainerStats, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fill in network stats for root.
|
||||||
|
nd, err := self.GetRootNetworkDevices()
|
||||||
|
if err != nil {
|
||||||
|
return stats, err
|
||||||
|
}
|
||||||
|
if len(nd) != 0 {
|
||||||
|
// ContainerStats only reports stat for one network device.
|
||||||
|
// TODO(rjnagal): Handle multiple physical network devices.
|
||||||
|
stats.Network, err = sysinfo.GetNetworkStats(nd[0].Name)
|
||||||
|
if err != nil {
|
||||||
|
return stats, err
|
||||||
|
}
|
||||||
|
}
|
||||||
return stats, nil
|
return stats, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +85,10 @@ func (self *FakeSysFs) GetNetworkSpeed(name string) (string, error) {
|
|||||||
return "1000\n", nil
|
return "1000\n", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *FakeSysFs) GetNetworkStatValue(name string, stat string) (uint64, error) {
|
||||||
|
return 1024, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (self *FakeSysFs) GetCaches(id int) ([]os.FileInfo, error) {
|
func (self *FakeSysFs) GetCaches(id int) ([]os.FileInfo, error) {
|
||||||
self.info.EntryName = "index0"
|
self.info.EntryName = "index0"
|
||||||
return []os.FileInfo{&self.info}, nil
|
return []os.FileInfo{&self.info}, nil
|
||||||
|
@ -52,6 +52,7 @@ type SysFs interface {
|
|||||||
GetNetworkAddress(string) (string, error)
|
GetNetworkAddress(string) (string, error)
|
||||||
GetNetworkMtu(string) (string, error)
|
GetNetworkMtu(string) (string, error)
|
||||||
GetNetworkSpeed(string) (string, error)
|
GetNetworkSpeed(string) (string, error)
|
||||||
|
GetNetworkStatValue(dev string, stat string) (uint64, error)
|
||||||
|
|
||||||
// Get directory information for available caches accessible to given cpu.
|
// Get directory information for available caches accessible to given cpu.
|
||||||
GetCaches(id int) ([]os.FileInfo, error)
|
GetCaches(id int) ([]os.FileInfo, error)
|
||||||
@ -113,6 +114,20 @@ func (self *realSysFs) GetNetworkSpeed(name string) (string, error) {
|
|||||||
return string(speed), nil
|
return string(speed), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *realSysFs) GetNetworkStatValue(dev string, stat string) (uint64, error) {
|
||||||
|
statPath := path.Join(netDir, dev, "/statistics", stat)
|
||||||
|
out, err := ioutil.ReadFile(statPath)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("failed to read stat from %q for device %q", statPath, dev)
|
||||||
|
}
|
||||||
|
var s uint64
|
||||||
|
n, err := fmt.Sscanf(string(out), "%d", &s)
|
||||||
|
if err != nil || n != 1 {
|
||||||
|
return 0, fmt.Errorf("could not parse value from %q for file %s", string(out), statPath)
|
||||||
|
}
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (self *realSysFs) GetCaches(id int) ([]os.FileInfo, error) {
|
func (self *realSysFs) GetCaches(id int) ([]os.FileInfo, error) {
|
||||||
cpuPath := fmt.Sprintf("%s%d/cache", cacheDir, id)
|
cpuPath := fmt.Sprintf("%s%d/cache", cacheDir, id)
|
||||||
return ioutil.ReadDir(cpuPath)
|
return ioutil.ReadDir(cpuPath)
|
||||||
|
@ -133,3 +133,51 @@ func GetCacheInfo(sysFs sysfs.SysFs, id int) ([]sysfs.CacheInfo, error) {
|
|||||||
}
|
}
|
||||||
return info, nil
|
return info, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetNetworkStats(name string) (info.NetworkStats, error) {
|
||||||
|
stats := info.NetworkStats{}
|
||||||
|
// TODO(rjnagal): Take syfs as an argument.
|
||||||
|
sysFs, err := sysfs.NewRealSysFs()
|
||||||
|
if err != nil {
|
||||||
|
return stats, err
|
||||||
|
}
|
||||||
|
return getNetworkStats(name, sysFs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNetworkStats(name string, sysFs sysfs.SysFs) (info.NetworkStats, error) {
|
||||||
|
stats := info.NetworkStats{}
|
||||||
|
var err error
|
||||||
|
stats.RxBytes, err = sysFs.GetNetworkStatValue(name, "rx_bytes")
|
||||||
|
if err != nil {
|
||||||
|
return stats, err
|
||||||
|
}
|
||||||
|
stats.RxPackets, err = sysFs.GetNetworkStatValue(name, "rx_packets")
|
||||||
|
if err != nil {
|
||||||
|
return stats, err
|
||||||
|
}
|
||||||
|
stats.RxErrors, err = sysFs.GetNetworkStatValue(name, "rx_errors")
|
||||||
|
if err != nil {
|
||||||
|
return stats, err
|
||||||
|
}
|
||||||
|
stats.RxDropped, err = sysFs.GetNetworkStatValue(name, "rx_dropped")
|
||||||
|
if err != nil {
|
||||||
|
return stats, err
|
||||||
|
}
|
||||||
|
stats.TxBytes, err = sysFs.GetNetworkStatValue(name, "tx_bytes")
|
||||||
|
if err != nil {
|
||||||
|
return stats, err
|
||||||
|
}
|
||||||
|
stats.TxPackets, err = sysFs.GetNetworkStatValue(name, "tx_packets")
|
||||||
|
if err != nil {
|
||||||
|
return stats, err
|
||||||
|
}
|
||||||
|
stats.TxErrors, err = sysFs.GetNetworkStatValue(name, "tx_errors")
|
||||||
|
if err != nil {
|
||||||
|
return stats, err
|
||||||
|
}
|
||||||
|
stats.TxDropped, err = sysFs.GetNetworkStatValue(name, "tx_dropped")
|
||||||
|
if err != nil {
|
||||||
|
return stats, err
|
||||||
|
}
|
||||||
|
return stats, nil
|
||||||
|
}
|
||||||
|
@ -17,6 +17,7 @@ package sysinfo
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/cadvisor/info"
|
||||||
"github.com/google/cadvisor/utils/sysfs"
|
"github.com/google/cadvisor/utils/sysfs"
|
||||||
"github.com/google/cadvisor/utils/sysfs/fakesysfs"
|
"github.com/google/cadvisor/utils/sysfs/fakesysfs"
|
||||||
)
|
)
|
||||||
@ -88,3 +89,24 @@ func TestGetCacheInfo(t *testing.T) {
|
|||||||
t.Errorf("expected to find cacheinfo %+v. Got %+v", cacheInfo, caches[0])
|
t.Errorf("expected to find cacheinfo %+v. Got %+v", cacheInfo, caches[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetNetworkStats(t *testing.T) {
|
||||||
|
expected_stats := info.NetworkStats{
|
||||||
|
RxBytes: 1024,
|
||||||
|
RxPackets: 1024,
|
||||||
|
RxErrors: 1024,
|
||||||
|
RxDropped: 1024,
|
||||||
|
TxBytes: 1024,
|
||||||
|
TxPackets: 1024,
|
||||||
|
TxErrors: 1024,
|
||||||
|
TxDropped: 1024,
|
||||||
|
}
|
||||||
|
fakeSys := &fakesysfs.FakeSysFs{}
|
||||||
|
netStats, err := getNetworkStats("eth0", fakeSys)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("call to getNetworkStats() failed with %s", err)
|
||||||
|
}
|
||||||
|
if expected_stats != netStats {
|
||||||
|
t.Errorf("expected to get stats %+v, got %+v", expected_stats, netStats)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user