Add network stats to root container. Provides machine-level networking stats.

This commit is contained in:
Rohit Jnagal 2014-12-30 17:12:42 +00:00
parent 7e73bca3fb
commit 45334c6f71
5 changed files with 124 additions and 0 deletions

View File

@ -33,6 +33,7 @@ import (
"github.com/google/cadvisor/fs"
"github.com/google/cadvisor/info"
"github.com/google/cadvisor/utils"
"github.com/google/cadvisor/utils/sysinfo"
)
type rawContainerHandler struct {
@ -145,6 +146,18 @@ func readInt64(dirpath string, file string) uint64 {
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) {
var spec info.ContainerSpec
@ -197,6 +210,15 @@ func (self *rawContainerHandler) GetSpec() (info.ContainerSpec, error) {
if self.networkInterface != nil {
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
}
@ -283,6 +305,19 @@ func (self *rawContainerHandler) GetStats() (*info.ContainerStats, error) {
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
}

View File

@ -85,6 +85,10 @@ func (self *FakeSysFs) GetNetworkSpeed(name string) (string, error) {
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) {
self.info.EntryName = "index0"
return []os.FileInfo{&self.info}, nil

View File

@ -52,6 +52,7 @@ type SysFs interface {
GetNetworkAddress(string) (string, error)
GetNetworkMtu(string) (string, error)
GetNetworkSpeed(string) (string, error)
GetNetworkStatValue(dev string, stat string) (uint64, error)
// Get directory information for available caches accessible to given cpu.
GetCaches(id int) ([]os.FileInfo, error)
@ -113,6 +114,20 @@ func (self *realSysFs) GetNetworkSpeed(name string) (string, error) {
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) {
cpuPath := fmt.Sprintf("%s%d/cache", cacheDir, id)
return ioutil.ReadDir(cpuPath)

View File

@ -133,3 +133,51 @@ func GetCacheInfo(sysFs sysfs.SysFs, id int) ([]sysfs.CacheInfo, error) {
}
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
}

View File

@ -17,6 +17,7 @@ package sysinfo
import (
"testing"
"github.com/google/cadvisor/info"
"github.com/google/cadvisor/utils/sysfs"
"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])
}
}
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)
}
}