Merge pull request #1488 from tcolgate/master
Add udp and udp6 network statistics
This commit is contained in:
commit
359ef5b100
@ -33,6 +33,7 @@ import (
|
|||||||
"github.com/google/cadvisor/version"
|
"github.com/google/cadvisor/version"
|
||||||
|
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -60,13 +61,17 @@ var collectorKey = flag.String("collector_key", "", "Key for the collector's cer
|
|||||||
var (
|
var (
|
||||||
// Metrics to be ignored.
|
// Metrics to be ignored.
|
||||||
// Tcp metrics are ignored by default.
|
// Tcp metrics are ignored by default.
|
||||||
ignoreMetrics metricSetValue = metricSetValue{container.MetricSet{container.NetworkTcpUsageMetrics: struct{}{}}}
|
ignoreMetrics metricSetValue = metricSetValue{container.MetricSet{
|
||||||
|
container.NetworkTcpUsageMetrics: struct{}{},
|
||||||
|
container.NetworkUdpUsageMetrics: struct{}{},
|
||||||
|
}}
|
||||||
|
|
||||||
// List of metrics that can be ignored.
|
// List of metrics that can be ignored.
|
||||||
ignoreWhitelist = container.MetricSet{
|
ignoreWhitelist = container.MetricSet{
|
||||||
container.DiskUsageMetrics: struct{}{},
|
container.DiskUsageMetrics: struct{}{},
|
||||||
container.NetworkUsageMetrics: struct{}{},
|
container.NetworkUsageMetrics: struct{}{},
|
||||||
container.NetworkTcpUsageMetrics: struct{}{},
|
container.NetworkTcpUsageMetrics: struct{}{},
|
||||||
|
container.NetworkUdpUsageMetrics: struct{}{},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -98,7 +103,7 @@ func (ml *metricSetValue) Set(value string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
flag.Var(&ignoreMetrics, "disable_metrics", "comma-separated list of `metrics` to be disabled. Options are 'disk', 'network', 'tcp'. Note: tcp is disabled by default due to high CPU usage.")
|
flag.Var(&ignoreMetrics, "disable_metrics", "comma-separated list of `metrics` to be disabled. Options are 'disk', 'network', 'tcp', 'udp'. Note: tcp and udp are disabled by default due to high CPU usage.")
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -28,6 +28,12 @@ func TestTcpMetricsAreDisabledByDefault(t *testing.T) {
|
|||||||
assert.True(t, ignoreMetrics.Has(container.NetworkTcpUsageMetrics))
|
assert.True(t, ignoreMetrics.Has(container.NetworkTcpUsageMetrics))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUdpMetricsAreDisabledByDefault(t *testing.T) {
|
||||||
|
assert.True(t, ignoreMetrics.Has(container.NetworkUdpUsageMetrics))
|
||||||
|
flag.Parse()
|
||||||
|
assert.True(t, ignoreMetrics.Has(container.NetworkUdpUsageMetrics))
|
||||||
|
}
|
||||||
|
|
||||||
func TestIgnoreMetrics(t *testing.T) {
|
func TestIgnoreMetrics(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
value string
|
value string
|
||||||
|
@ -48,6 +48,7 @@ const (
|
|||||||
DiskUsageMetrics MetricKind = "disk"
|
DiskUsageMetrics MetricKind = "disk"
|
||||||
NetworkUsageMetrics MetricKind = "network"
|
NetworkUsageMetrics MetricKind = "network"
|
||||||
NetworkTcpUsageMetrics MetricKind = "tcp"
|
NetworkTcpUsageMetrics MetricKind = "tcp"
|
||||||
|
NetworkUdpUsageMetrics MetricKind = "udp"
|
||||||
AppMetrics MetricKind = "app"
|
AppMetrics MetricKind = "app"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ package libcontainer
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
@ -118,6 +119,21 @@ func GetStats(cgroupManager cgroups.Manager, rootFs string, pid int, ignoreMetri
|
|||||||
stats.Network.Tcp6 = t6
|
stats.Network.Tcp6 = t6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !ignoreMetrics.Has(container.NetworkUdpUsageMetrics) {
|
||||||
|
u, err := udpStatsFromProc(rootFs, pid, "net/udp")
|
||||||
|
if err != nil {
|
||||||
|
glog.V(2).Infof("Unable to get udp stats from pid %d: %v", pid, err)
|
||||||
|
} else {
|
||||||
|
stats.Network.Udp = u
|
||||||
|
}
|
||||||
|
|
||||||
|
u6, err := udpStatsFromProc(rootFs, pid, "net/udp6")
|
||||||
|
if err != nil {
|
||||||
|
glog.V(2).Infof("Unable to get udp6 stats from pid %d: %v", pid, err)
|
||||||
|
} else {
|
||||||
|
stats.Network.Udp6 = u6
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// For backwards compatibility.
|
// For backwards compatibility.
|
||||||
if len(stats.Network.Interfaces) > 0 {
|
if len(stats.Network.Interfaces) > 0 {
|
||||||
@ -291,6 +307,74 @@ func scanTcpStats(tcpStatsFile string) (info.TcpStat, error) {
|
|||||||
return stats, nil
|
return stats, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func udpStatsFromProc(rootFs string, pid int, file string) (info.UdpStat, error) {
|
||||||
|
var err error
|
||||||
|
var udpStats info.UdpStat
|
||||||
|
|
||||||
|
udpStatsFile := path.Join(rootFs, "proc", strconv.Itoa(pid), file)
|
||||||
|
|
||||||
|
r, err := os.Open(udpStatsFile)
|
||||||
|
if err != nil {
|
||||||
|
return udpStats, fmt.Errorf("failure opening %s: %v", udpStatsFile, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
udpStats, err = scanUdpStats(r)
|
||||||
|
if err != nil {
|
||||||
|
return udpStats, fmt.Errorf("couldn't read udp stats: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return udpStats, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func scanUdpStats(r io.Reader) (info.UdpStat, error) {
|
||||||
|
var stats info.UdpStat
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(r)
|
||||||
|
scanner.Split(bufio.ScanLines)
|
||||||
|
|
||||||
|
// Discard header line
|
||||||
|
if b := scanner.Scan(); !b {
|
||||||
|
return stats, scanner.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
listening := uint64(0)
|
||||||
|
dropped := uint64(0)
|
||||||
|
rxQueued := uint64(0)
|
||||||
|
txQueued := uint64(0)
|
||||||
|
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := scanner.Text()
|
||||||
|
// Format: sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode ref pointer drops
|
||||||
|
|
||||||
|
listening++
|
||||||
|
|
||||||
|
fs := strings.Fields(line)
|
||||||
|
if len(fs) != 13 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
rx, tx := uint64(0), uint64(0)
|
||||||
|
fmt.Sscanf(fs[4], "%X:%X", &rx, &tx)
|
||||||
|
rxQueued += rx
|
||||||
|
txQueued += tx
|
||||||
|
|
||||||
|
d, err := strconv.Atoi(string(fs[12]))
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
dropped += uint64(d)
|
||||||
|
}
|
||||||
|
|
||||||
|
stats = info.UdpStat{
|
||||||
|
Listen: listening,
|
||||||
|
Dropped: dropped,
|
||||||
|
RxQueued: rxQueued,
|
||||||
|
TxQueued: txQueued,
|
||||||
|
}
|
||||||
|
|
||||||
|
return stats, nil
|
||||||
|
}
|
||||||
|
|
||||||
func GetProcesses(cgroupManager cgroups.Manager) ([]int, error) {
|
func GetProcesses(cgroupManager cgroups.Manager) ([]int, error) {
|
||||||
pids, err := cgroupManager.GetPids()
|
pids, err := cgroupManager.GetPids()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
package libcontainer
|
package libcontainer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
info "github.com/google/cadvisor/info/v1"
|
info "github.com/google/cadvisor/info/v1"
|
||||||
@ -61,3 +62,27 @@ func TestScanInterfaceStats(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestScanUDPStats(t *testing.T) {
|
||||||
|
udpStatsFile := "testdata/procnetudp"
|
||||||
|
r, err := os.Open(udpStatsFile)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failure opening %s: %v", udpStatsFile, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
stats, err := scanUdpStats(r)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var udpstats = info.UdpStat{
|
||||||
|
Listen: 2,
|
||||||
|
Dropped: 4,
|
||||||
|
RxQueued: 10,
|
||||||
|
TxQueued: 11,
|
||||||
|
}
|
||||||
|
|
||||||
|
if stats != udpstats {
|
||||||
|
t.Errorf("Expected %#v, got %#v", udpstats, stats)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
3
container/libcontainer/testdata/procnetudp
vendored
Normal file
3
container/libcontainer/testdata/procnetudp
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode ref pointer drops
|
||||||
|
1: 00000000:07D3 00000000:0000 07 00000000:00000000 00:00000000 00000000 0 0 16583 2 ffff8800b4549400 0
|
||||||
|
21: 00000000:A841 00000000:0000 07 0000000A:0000000B 00:00000000 00000000 1000 0 114299623 2 ffff880338477800 4
|
@ -386,6 +386,10 @@ type NetworkStats struct {
|
|||||||
Tcp TcpStat `json:"tcp"`
|
Tcp TcpStat `json:"tcp"`
|
||||||
// TCP6 connection stats (Established, Listen...)
|
// TCP6 connection stats (Established, Listen...)
|
||||||
Tcp6 TcpStat `json:"tcp6"`
|
Tcp6 TcpStat `json:"tcp6"`
|
||||||
|
// UDP connection stats
|
||||||
|
Udp UdpStat `json:"udp"`
|
||||||
|
// UDP6 connection stats
|
||||||
|
Udp6 UdpStat `json:"udp6"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type TcpStat struct {
|
type TcpStat struct {
|
||||||
@ -413,6 +417,20 @@ type TcpStat struct {
|
|||||||
Closing uint64
|
Closing uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UdpStat struct {
|
||||||
|
// Count of UDP sockets in state "Listen"
|
||||||
|
Listen uint64
|
||||||
|
|
||||||
|
// Count of UDP packets dropped by the IP stack
|
||||||
|
Dropped uint64
|
||||||
|
|
||||||
|
// Count of packets Queued for Receieve
|
||||||
|
RxQueued uint64
|
||||||
|
|
||||||
|
// Count of packets Queued for Transmit
|
||||||
|
TxQueued uint64
|
||||||
|
}
|
||||||
|
|
||||||
type FsStats struct {
|
type FsStats struct {
|
||||||
// The block device name associated with the filesystem.
|
// The block device name associated with the filesystem.
|
||||||
Device string `json:"device,omitempty"`
|
Device string `json:"device,omitempty"`
|
||||||
|
@ -269,6 +269,10 @@ type NetworkStats struct {
|
|||||||
Tcp TcpStat `json:"tcp"`
|
Tcp TcpStat `json:"tcp"`
|
||||||
// TCP6 connection stats (Established, Listen...)
|
// TCP6 connection stats (Established, Listen...)
|
||||||
Tcp6 TcpStat `json:"tcp6"`
|
Tcp6 TcpStat `json:"tcp6"`
|
||||||
|
// UDP connection stats
|
||||||
|
Udp v1.UdpStat `json:"udp"`
|
||||||
|
// UDP6 connection stats
|
||||||
|
Udp6 v1.UdpStat `json:"udp6"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Instantaneous CPU stats
|
// Instantaneous CPU stats
|
||||||
|
Loading…
Reference in New Issue
Block a user