Fix networking stats by switching Tx and Rx stats.
A better fix is to directly use stats collected by libcontainer.
This commit is contained in:
parent
81e099aae6
commit
dfcc05a953
@ -255,6 +255,19 @@ func (self *dockerContainerHandler) GetStats() (*info.ContainerStats, error) {
|
|||||||
return stats, err
|
return stats, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
// Get filesystem stats.
|
// Get filesystem stats.
|
||||||
err = self.getFsStats(stats)
|
err = self.getFsStats(stats)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -16,10 +16,7 @@ package libcontainer
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/docker/libcontainer"
|
"github.com/docker/libcontainer"
|
||||||
@ -90,6 +87,7 @@ func GetStats(cgroupManager cgroups.Manager, networkInterfaces []string) (*info.
|
|||||||
if len(networkInterfaces) != 0 {
|
if len(networkInterfaces) != 0 {
|
||||||
// ContainerStats only reports stat for one network device.
|
// ContainerStats only reports stat for one network device.
|
||||||
// TODO(rjnagal): Handle multiple physical network devices.
|
// TODO(rjnagal): Handle multiple physical network devices.
|
||||||
|
// TODO(rjnagal): Use networking stats directly from libcontainer.
|
||||||
stats.Network, err = sysinfo.GetNetworkStats(networkInterfaces[0])
|
stats.Network, err = sysinfo.GetNetworkStats(networkInterfaces[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return stats, err
|
return stats, err
|
||||||
@ -197,53 +195,5 @@ func toContainerStats(libcontainerStats *libcontainer.Stats) *info.ContainerStat
|
|||||||
ret.Network.TxErrors = libcontainerStats.Interfaces[0].TxErrors
|
ret.Network.TxErrors = libcontainerStats.Interfaces[0].TxErrors
|
||||||
ret.Network.TxDropped = libcontainerStats.Interfaces[0].TxDropped
|
ret.Network.TxDropped = libcontainerStats.Interfaces[0].TxDropped
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the network statistics for the network interfaces represented by the NetworkRuntimeInfo.
|
|
||||||
func GetNetworkInterfaceStats(interfaceName string) (*libcontainer.NetworkInterface, error) {
|
|
||||||
out := &libcontainer.NetworkInterface{
|
|
||||||
Name: interfaceName,
|
|
||||||
}
|
|
||||||
// This can happen if the network runtime information is missing - possible if the
|
|
||||||
// container was created by an old version of libcontainer.
|
|
||||||
if interfaceName == "" {
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
type netStatsPair struct {
|
|
||||||
// Where to write the output.
|
|
||||||
Out *uint64
|
|
||||||
// The network stats file to read.
|
|
||||||
File string
|
|
||||||
}
|
|
||||||
// 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.
|
|
||||||
netStats := []netStatsPair{
|
|
||||||
{Out: &out.RxBytes, File: "tx_bytes"},
|
|
||||||
{Out: &out.RxPackets, File: "tx_packets"},
|
|
||||||
{Out: &out.RxErrors, File: "tx_errors"},
|
|
||||||
{Out: &out.RxDropped, File: "tx_dropped"},
|
|
||||||
|
|
||||||
{Out: &out.TxBytes, File: "rx_bytes"},
|
|
||||||
{Out: &out.TxPackets, File: "rx_packets"},
|
|
||||||
{Out: &out.TxErrors, File: "rx_errors"},
|
|
||||||
{Out: &out.TxDropped, File: "rx_dropped"},
|
|
||||||
}
|
|
||||||
for _, netStat := range netStats {
|
|
||||||
data, err := readSysfsNetworkStats(interfaceName, netStat.File)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
*(netStat.Out) = data
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reads the specified statistics available under /sys/class/net/<EthInterface>/statistics
|
|
||||||
func readSysfsNetworkStats(ethInterface, statsFile string) (uint64, error) {
|
|
||||||
data, err := ioutil.ReadFile(path.Join("/sys/class/net", ethInterface, "statistics", statsFile))
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return strconv.ParseUint(strings.TrimSpace(string(data)), 10, 64)
|
|
||||||
}
|
|
||||||
|
@ -261,7 +261,7 @@ func TestDockerContainerNetworkStats(t *testing.T) {
|
|||||||
|
|
||||||
// Checks for NetworkStats.
|
// Checks for NetworkStats.
|
||||||
stat := containerInfo.Stats[0]
|
stat := containerInfo.Stats[0]
|
||||||
assert.NotEqual(t, 0, stat.Network.TxBytes, "Network tx bytes should not bet zero")
|
assert.NotEqual(t, 0, stat.Network.TxBytes, "Network tx bytes should not be zero")
|
||||||
assert.NotEqual(t, 0, stat.Network.TxPackets, "Network tx packets should not bet zero")
|
assert.NotEqual(t, 0, stat.Network.TxPackets, "Network tx packets should not be zero")
|
||||||
// TODO(vmarmol): Can probably do a better test with two containers pinging each other.
|
// TODO(vmarmol): Can probably do a better test with two containers pinging each other.
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user