Skip to content

Commit

Permalink
Expose multiple network interfaces in API.
Browse files Browse the repository at this point in the history
Part of google#686
  • Loading branch information
vmarmol committed Jun 8, 2015
1 parent 48f14dc commit b923eff
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 44 deletions.
3 changes: 1 addition & 2 deletions api/versions.go
Original file line number Diff line number Diff line change
Expand Up @@ -426,8 +426,7 @@ func convertStats(cont *info.ContainerInfo) []v2.ContainerStats {
stat.Memory = val.Memory
}
if stat.HasNetwork {
// TODO(rjnagal): Return stats about all network interfaces.
stat.Network = append(stat.Network, val.Network)
stat.Network.Interfaces = val.Network.Interfaces
}
if stat.HasFilesystem {
stat.Filesystem = val.Filesystem
Expand Down
30 changes: 19 additions & 11 deletions container/docker/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,17 +261,10 @@ func (self *dockerContainerHandler) GetStats() (*info.ContainerStats, error) {
}

// TODO(rjnagal): Remove the conversion when network stats are read from libcontainer.
net := stats.Network
// Ingress for host veth is from the container.
// Hence tx_bytes stat on the host veth is actually number of bytes received by the container.
stats.Network.RxBytes = net.TxBytes
stats.Network.RxPackets = net.TxPackets
stats.Network.RxErrors = net.TxErrors
stats.Network.RxDropped = net.TxDropped
stats.Network.TxBytes = net.RxBytes
stats.Network.TxPackets = net.RxPackets
stats.Network.TxErrors = net.RxErrors
stats.Network.TxDropped = net.RxDropped
convertInterfaceStats(&stats.Network.InterfaceStats)
for i := range stats.Network.Interfaces {
convertInterfaceStats(&stats.Network.Interfaces[i])
}

// Get filesystem stats.
err = self.getFsStats(stats)
Expand All @@ -282,6 +275,21 @@ func (self *dockerContainerHandler) GetStats() (*info.ContainerStats, error) {
return stats, nil
}

func convertInterfaceStats(stats *info.InterfaceStats) {
net := stats

// Ingress for host veth is from the container.
// Hence tx_bytes stat on the host veth is actually number of bytes received by the container.
stats.RxBytes = net.TxBytes
stats.RxPackets = net.TxPackets
stats.RxErrors = net.TxErrors
stats.RxDropped = net.TxDropped
stats.TxBytes = net.RxBytes
stats.TxPackets = net.RxPackets
stats.TxErrors = net.RxErrors
stats.TxDropped = net.RxDropped
}

func (self *dockerContainerHandler) ListContainers(listType container.ListType) ([]info.ContainerReference, error) {
if self.name != "/docker" {
return []info.ContainerReference{}, nil
Expand Down
43 changes: 29 additions & 14 deletions container/libcontainer/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,20 @@ func GetStats(cgroupManager cgroups.Manager, networkInterfaces []string) (*info.
}
stats := toContainerStats(libcontainerStats)

if len(networkInterfaces) != 0 {
// ContainerStats only reports stat for one network device.
// TODO(rjnagal): Handle multiple physical network devices.
// TODO(rjnagal): Use networking stats directly from libcontainer.
stats.Network, err = sysinfo.GetNetworkStats(networkInterfaces[0])
// TODO(rjnagal): Use networking stats directly from libcontainer.
stats.Network.Interfaces = make([]info.InterfaceStats, len(networkInterfaces))
for i := range networkInterfaces {
interfaceStats, err := sysinfo.GetNetworkStats(networkInterfaces[i])
if err != nil {
return stats, err
}
stats.Network.Interfaces[i] = interfaceStats
}
// For backwards compatability.
if len(networkInterfaces) > 0 {
stats.Network.InterfaceStats = stats.Network.Interfaces[0]
}

return stats, nil
}

Expand Down Expand Up @@ -213,15 +218,25 @@ func toContainerStats2(s *cgroups.Stats, ret *info.ContainerStats) {
}

func toContainerStats3(libcontainerStats *libcontainer.Stats, ret *info.ContainerStats) {
// TODO(vmarmol): Handle multiple interfaces.
ret.Network.RxBytes = libcontainerStats.Interfaces[0].RxBytes
ret.Network.RxPackets = libcontainerStats.Interfaces[0].RxPackets
ret.Network.RxErrors = libcontainerStats.Interfaces[0].RxErrors
ret.Network.RxDropped = libcontainerStats.Interfaces[0].RxDropped
ret.Network.TxBytes = libcontainerStats.Interfaces[0].TxBytes
ret.Network.TxPackets = libcontainerStats.Interfaces[0].TxPackets
ret.Network.TxErrors = libcontainerStats.Interfaces[0].TxErrors
ret.Network.TxDropped = libcontainerStats.Interfaces[0].TxDropped
ret.Network.Interfaces = make([]info.InterfaceStats, len(libcontainerStats.Interfaces))
for i := range libcontainerStats.Interfaces {
ret.Network.Interfaces[i] = info.InterfaceStats{
Name: libcontainerStats.Interfaces[i].Name,
RxBytes: libcontainerStats.Interfaces[i].RxBytes,
RxPackets: libcontainerStats.Interfaces[i].RxPackets,
RxErrors: libcontainerStats.Interfaces[i].RxErrors,
RxDropped: libcontainerStats.Interfaces[i].RxDropped,
TxBytes: libcontainerStats.Interfaces[i].TxBytes,
TxPackets: libcontainerStats.Interfaces[i].TxPackets,
TxErrors: libcontainerStats.Interfaces[i].TxErrors,
TxDropped: libcontainerStats.Interfaces[i].TxDropped,
}
}

// Add to base struct for backwards compatability.
if len(ret.Network.Interfaces) > 0 {
ret.Network.InterfaceStats = ret.Network.Interfaces[0]
}
}

func toContainerStats(libcontainerStats *libcontainer.Stats) *info.ContainerStats {
Expand Down
9 changes: 8 additions & 1 deletion info/v1/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,9 @@ type MemoryStatsMemoryData struct {
Pgmajfault uint64 `json:"pgmajfault"`
}

type NetworkStats struct {
type InterfaceStats struct {
// The name of the interface.
Name string `json:"name"`
// Cumulative count of bytes received.
RxBytes uint64 `json:"rx_bytes"`
// Cumulative count of packets received.
Expand All @@ -331,6 +333,11 @@ type NetworkStats struct {
TxDropped uint64 `json:"tx_dropped"`
}

type NetworkStats struct {
InterfaceStats `json:",inline"`
Interfaces []InterfaceStats `json:"interfaces,omitempty"`
}

type FsStats struct {
// The block device name associated with the filesystem.
Device string `json:"device,omitempty"`
Expand Down
9 changes: 7 additions & 2 deletions info/v2/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ type ContainerStats struct {
HasMemory bool `json:"has_memory"`
Memory v1.MemoryStats `json:"memory,omitempty"`
// Network statistics
HasNetwork bool `json:"has_network"`
Network []v1.NetworkStats `json:"network,omitempty"`
HasNetwork bool `json:"has_network"`
Network NetworkStats `json:"network,omitempty"`
// Filesystem statistics
HasFilesystem bool `json:"has_filesystem"`
Filesystem []v1.FsStats `json:"filesystem,omitempty"`
Expand Down Expand Up @@ -189,3 +189,8 @@ type ProcessInfo struct {
CgroupPath string `json:"cgroup_path"`
Cmd string `json:"cmd"`
}

type NetworkStats struct {
// Network stats by interface.
Interfaces []v1.InterfaceStats `json:"interfaces,omitempty"`
}
19 changes: 11 additions & 8 deletions metrics/prometheus_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,17 @@ func (p testSubcontainersInfoProvider) SubcontainersInfo(string, *info.Container
},
},
Network: info.NetworkStats{
RxBytes: 14,
RxPackets: 15,
RxErrors: 16,
RxDropped: 17,
TxBytes: 18,
TxPackets: 19,
TxErrors: 20,
TxDropped: 21,
InterfaceStats: info.InterfaceStats{
Name: "eth0",
RxBytes: 14,
RxPackets: 15,
RxErrors: 16,
RxDropped: 17,
TxBytes: 18,
TxPackets: 19,
TxErrors: 20,
TxDropped: 21,
},
},
Filesystem: []info.FsStats{
{
Expand Down
10 changes: 5 additions & 5 deletions utils/sysinfo/sysinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,19 +157,19 @@ func GetCacheInfo(sysFs sysfs.SysFs, id int) ([]sysfs.CacheInfo, error) {
return info, nil
}

func GetNetworkStats(name string) (info.NetworkStats, error) {
stats := info.NetworkStats{}
func GetNetworkStats(name string) (info.InterfaceStats, error) {
// TODO(rjnagal): Take syfs as an argument.
sysFs, err := sysfs.NewRealSysFs()
if err != nil {
return stats, err
return info.InterfaceStats{}, err
}
return getNetworkStats(name, sysFs)
}

func getNetworkStats(name string, sysFs sysfs.SysFs) (info.NetworkStats, error) {
stats := info.NetworkStats{}
func getNetworkStats(name string, sysFs sysfs.SysFs) (info.InterfaceStats, error) {
var stats info.InterfaceStats
var err error
stats.Name = name
stats.RxBytes, err = sysFs.GetNetworkStatValue(name, "rx_bytes")
if err != nil {
return stats, err
Expand Down
3 changes: 2 additions & 1 deletion utils/sysinfo/sysinfo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ func TestGetCacheInfo(t *testing.T) {
}

func TestGetNetworkStats(t *testing.T) {
expected_stats := info.NetworkStats{
expected_stats := info.InterfaceStats{
Name: "eth0",
RxBytes: 1024,
RxPackets: 1024,
RxErrors: 1024,
Expand Down

0 comments on commit b923eff

Please sign in to comment.