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/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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user