Skip to content

Commit

Permalink
Merge pull request #3 from nightlyone/no_netstat_on_linux
Browse files Browse the repository at this point in the history
Linux specific net statistics
  • Loading branch information
Tobias Schwab committed Oct 16, 2013
2 parents bb9ae29 + d57831b commit 03a21ac
Show file tree
Hide file tree
Showing 6 changed files with 207 additions and 0 deletions.
4 changes: 4 additions & 0 deletions fixtures/proc/net/netstat
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
TcpExt: SyncookiesSent SyncookiesRecv SyncookiesFailed EmbryonicRsts PruneCalled RcvPruned OfoPruned OutOfWindowIcmps LockDroppedIcmps ArpFilter TW TWRecycled TWKilled PAWSPassive PAWSActive PAWSEstab DelayedACKs DelayedACKLocked DelayedACKLost ListenOverflows ListenDrops TCPPrequeued TCPDirectCopyFromBacklog TCPDirectCopyFromPrequeue TCPPrequeueDropped TCPHPHits TCPHPHitsToUser TCPPureAcks TCPHPAcks TCPRenoRecovery TCPSackRecovery TCPSACKReneging TCPFACKReorder TCPSACKReorder TCPRenoReorder TCPTSReorder TCPFullUndo TCPPartialUndo TCPDSACKUndo TCPLossUndo TCPLostRetransmit TCPRenoFailures TCPSackFailures TCPLossFailures TCPFastRetrans TCPForwardRetrans TCPSlowStartRetrans TCPTimeouts TCPRenoRecoveryFail TCPSackRecoveryFail TCPSchedulerFailed TCPRcvCollapsed TCPDSACKOldSent TCPDSACKOfoSent TCPDSACKRecv TCPDSACKOfoRecv TCPAbortOnData TCPAbortOnClose TCPAbortOnMemory TCPAbortOnTimeout TCPAbortOnLinger TCPAbortFailed TCPMemoryPressures TCPSACKDiscard TCPDSACKIgnoredOld TCPDSACKIgnoredNoUndo TCPSpuriousRTOs TCPMD5NotFound TCPMD5Unexpected TCPSackShifted TCPSackMerged TCPSackShiftFallback TCPBacklogDrop TCPMinTTLDrop TCPDeferAcceptDrop IPReversePathFilter TCPTimeWaitOverflow TCPReqQFullDoCookies TCPReqQFullDrop TCPRetransFail TCPRcvCoalesce TCPOFOQueue TCPOFODrop TCPOFOMerge TCPChallengeACK TCPSYNChallenge TCPFastOpenActive TCPFastOpenPassive TCPFastOpenPassiveFail TCPFastOpenListenOverflow TCPFastOpenCookieReqd
TcpExt: 0 0 2 0 210 0 0 13 0 0 4208 0 0 0 0 12 37718 2 2138 0 0 16349 711126 22454433 400 561282 13391 94274 155821 0 17 0 0 0 0 4 12 4 40 448 0 0 1 27 17 12 44 1213 0 0 0 2555 2052 11 508 0 309 2898 0 180 0 6 0 0 1 117 4 0 0 0 0 1441 10 0 0 1458 0 0 0 6 198338 15942 0 11 446 445 0 0 0 0 0
IpExt: InNoRoutes InTruncatedPkts InMcastPkts OutMcastPkts InBcastPkts OutBcastPkts InOctets OutOctets InMcastOctets OutMcastOctets InBcastOctets OutBcastOctets
IpExt: 41 0 45863 1586 164429 0 934529039 1037097012 4228142 139009 21904800 0
12 changes: 12 additions & 0 deletions fixtures/proc/net/snmp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Ip: Forwarding DefaultTTL InReceives InHdrErrors InAddrErrors ForwDatagrams InUnknownProtos InDiscards InDelivers OutRequests OutDiscards OutNoRoutes ReasmTimeout ReasmReqds ReasmOKs ReasmFails FragOKs FragFails FragCreates
Ip: 2 64 1594741 0 0 0 0 0 1572047 2228197 5479 1154 0 390 78 0 0 0 0
Icmp: InMsgs InErrors InDestUnreachs InTimeExcds InParmProbs InSrcQuenchs InRedirects InEchos InEchoReps InTimestamps InTimestampReps InAddrMasks InAddrMaskReps OutMsgs OutErrors OutDestUnreachs OutTimeExcds OutParmProbs OutSrcQuenchs OutRedirects OutEchos OutEchoReps OutTimestamps OutTimestampReps OutAddrMasks OutAddrMaskReps
Icmp: 8043 192 8038 0 0 0 0 1 4 0 0 0 0 10066 0 10054 0 0 0 0 11 1 0 0 0 0
IcmpMsg: InType0 InType3 InType8 OutType0 OutType3 OutType8
IcmpMsg: 4 8038 1 1 10054 11
Tcp: RtoAlgorithm RtoMin RtoMax MaxConn ActiveOpens PassiveOpens AttemptFails EstabResets CurrEstab InSegs OutSegs RetransSegs InErrs OutRsts
Tcp: 1 200 120000 -1 22169 280 175 2989 9 1017368 949859 2611 441 3802
Udp: InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors
Udp: 339484 6204 95 1265074 0 4071
UdpLite: InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors
UdpLite: 0 0 0 0 0 0
2 changes: 2 additions & 0 deletions net.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// +build !linux

package main

import (
Expand Down
129 changes: 129 additions & 0 deletions net_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package main

import (
"io/ioutil"
"strconv"
"strings"
)

const NET = "net"

func init() {
parser.Add(NET, "true", "Collect network metrics")
}

var mapStatMapping = map[string]string{
"Ip.InReceives": "ip.TotalPacketsReceived",
"Ip.ForwDatagrams": "ip.Forwarded",
"Ip.InDiscards": "ip.IncomingPacketsDiscarded",
"Ip.InDelivers": "ip.IncomingPacketsDelivered",
"Ip.OutRequests": "ip.RequestsSentOut",
"Tcp.ActiveOpens": "tcp.ActiveConnectionsOpenings",
"Tcp.PassiveOpens": "tcp.PassiveConnectionsOpenings",
"Tcp.AttemptFails": "tcp.FailedConnectionAttempts",
"Tcp.EstabResets": "tcp.ConnectionResetsReceived",
"Tcp.CurrEstab": "tcp.ConnectionsEstablished",
"Tcp.InSegs": "tcp.SegmentsReceived",
"Tcp.OutSegs": "tcp.SegmentsSendOut",
"Tcp.RetransSegs": "tcp.SegmentsTransmitted",
"Tcp.InErrs": "tcp.BadSegmentsReceived",
"Tcp.OutRsts": "tcp.ResetsSent",
"Udp.InDatagrams": "udp.PacketsReceived",
"Udp.NoPorts.": "udp.PacketsToUnknownPortRecived",
"Udp.InErrors": "udp.PacketReceiveErrors",
"Udp.OutDatagrams": "udp.PacketsSent",
"IpExt.InOctets": "ip.InOctets",
"IpExt.OutOctets": "ip.OutOctets",
}

type Net struct {
RawStatus []byte
}

func (self *Net) fetch(key string) (b []byte, e error) {
return ioutil.ReadFile(ProcRoot() + "/proc/net/" + key)
}

func (self *Net) Prefix() string {
return "net"
}

// Parses the self documenting format of the linux net statistics interface.
// The interface is in /proc/net and contains two consecutive lines starting
// with the same prefix like "prefix:". The first line contains the header
// and the second line the actual signed 64 bit values.
// A value < 0 means, that this statistic is not supported.
func parse2lines(headers, values string) map[string]int64 {
keys := strings.Fields(headers)
vals := strings.Fields(values)
result := make(map[string]int64, len(keys))

if len(keys) != len(vals) || len(keys) <= 1 || keys[0] != vals[0] {
return result
}

// strip the ":" of "foo:" ...
topic := keys[0][:len(keys[0])-1]
// .. and just get the actual header entries and values
keys = keys[1:]
vals = vals[1:]

for i, k := range keys {
if v, e := strconv.ParseInt(vals[i], 10, 64); e == nil && v >= 0 {
result[topic+"."+k] = v
}
}
return result
}

func (self *Net) collect2LineFile(c *MetricsCollection, name string) (e error) {
b, e := self.fetch(name)
if e != nil {
return e
}
raw := string(b)
lines := strings.Split(raw, "\n")
for i := 0; i < len(lines) - 1; i+=2 {
for k, v := range parse2lines(lines[i], lines[i+1]) {
if mapped, ok := mapStatMapping[k]; ok {
c.Add(mapped, v)
}
}
}
return nil
}

func (self *Net) Collect(c *MetricsCollection) error {
for _, name := range []string{"snmp", "netstat"} {
if e := self.collect2LineFile(c, name); e != nil {
return e
}
}
return nil
}

func (self *Net) Keys() []string {
return []string{
"ip.TotalPacketsReceived",
"ip.Forwarded",
"ip.IncomingPacketsDiscarded",
"ip.IncomingPacketsDelivered",
"ip.RequestsSentOut",
"tcp.ActiveConnectionsOpenings",
"tcp.PassiveConnectionsOpenings",
"tcp.FailedConnectionAttempts",
"tcp.ConnectionResetsReceived",
"tcp.ConnectionsEstablished",
"tcp.SegmentsReceived",
"tcp.SegmentsSendOut",
"tcp.SegmentsTransmitted",
"tcp.BadSegmentsReceived",
"tcp.ResetsSent",
"udp.PacketsReceived",
"udp.PacketsToUnknownPortRecived",
"udp.PacketReceiveErrors",
"udp.PacketsSent",
"ip.InOctets",
"ip.OutOctets",
}
}
58 changes: 58 additions & 0 deletions net_linux_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package main

import (
"github.com/stretchr/testify/assert"
"testing"
)

func TestParse2lines(t *testing.T) {
header := "Ip: Forwarding DefaultTTL InReceives InHdrErrors InAddrErrors ForwDatagrams InUnknownProtos InDiscards InDelivers OutRequests OutDiscards OutNoRoutes ReasmTimeout ReasmReqds ReasmOKs ReasmFails FragOKs FragFails FragCreates"
value := "Ip: 2 64 1594741 0 0 0 0 0 1572047 2228197 5479 1154 0 390 78 0 0 0 0"
want := map[string]int64{
"Ip.Forwarding": 2,
"Ip.DefaultTTL": 64,

"Ip.InReceives": 1594741,
"Ip.InHdrErrors" : 0,
"Ip.InAddrErrors" : 0,

"Ip.ForwDatagrams": 0,

"Ip.InUnknownProtos": 0,
"Ip.InDiscards": 0,
"Ip.InDelivers": 1572047,

"Ip.OutRequests": 2228197,
"Ip.OutDiscards": 5479,
"Ip.OutNoRoutes": 1154,

"Ip.ReasmTimeout": 0,
"Ip.ReasmReqds": 390,
"Ip.ReasmOKs": 78,
"Ip.ReasmFails": 0,

"Ip.FragOKs": 0,
"Ip.FragFails": 0,
"Ip.FragCreates": 0,
}

got := parse2lines(header, value)
assert.Equal(t, got, want)
}

func TestNet(t *testing.T) {
t.Skip("not implemented yet")
return

mh := new(MetricHandler)
net := &Net{}
stats, _ := mh.Collect(net)
assert.True(t, len(stats) > 4)
assert.Equal(t, len(stats), 21)

assert.Equal(t, stats[0].Key, "net.ip.TotalPacketsReceived")
assert.Equal(t, stats[0].Value, int64(162673))

assert.Equal(t, stats[20].Key, "net.ip.OutOctets")
assert.Equal(t, stats[20].Value, int64(667161104))
}
2 changes: 2 additions & 0 deletions net_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// +build !linux

package main

import (
Expand Down

0 comments on commit 03a21ac

Please sign in to comment.