Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Additional tcp metrics #949

Merged
merged 12 commits into from
May 20, 2014
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Changes
* Memcached
* Mesos
* MySQL
* Network

#### Changes
* [BUGFIX] Fix incorrect open file descriptors metric name in process check: See [#904]. Warning: As the metric name will be changed. Your dashboards will have to be updated.
Expand All @@ -37,6 +38,7 @@ Changes
* [BUGFIX] Varnish: Fix a bug that was causing tags to be continuously added in some cases.
* [FEATURE] Add an option to disable Dogstastsd: See [#927]
* [FEATURE] Memcached: Add support for local unix socket connections: See [#891][] (Thanks to [@mike-lerch][])
* [FEATURE] Network: Add additional metrics for TCP: See [#949]


# 4.2.2 / 04-25-2014
Expand Down
94 changes: 94 additions & 0 deletions checks.d/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,17 @@
# project
from checks import AgentCheck
from util import Platform
BSD_TCP_METRICS = [
(re.compile("^\s*(\d+) data packets \(\d+ bytes\) retransmitted\s*$"), 'system.net.tcp.retrans_packs'),
(re.compile("^\s*(\d+) packets sent\s*$"), 'system.net.tcp.sent_packs'),
(re.compile("^\s*(\d+) packets received\s*$"), 'system.net.tcp.rcv_packs')
]

SOLARIS_TCP_METRICS = [
(re.compile("\s*tcpRetransSegs\s*=\s*(\d+)\s*"), 'system.net.tcp.retrans_segs'),
(re.compile("\s*tcpOutDataSegs\s*=\s*(\d+)\s*"), 'system.net.tcp.in_segs'),
(re.compile("\s*tcpInSegs\s*=\s*(\d+)\s*"), 'system.net.tcp.out_segs')
]

class Network(AgentCheck):

Expand Down Expand Up @@ -118,6 +128,14 @@ def _parse_value(self, v):
except ValueError:
return 0

def _submit_regexed_values(self, output, regex_list):
lines=output.split("\n")
for line in lines:
for regex, metric in regex_list:
value = re.match(regex, line)
if value:
self.rate(metric, self._parse_value(value.group(1)))

def _check_linux(self, instance):
if self._collect_cx_state:
netstat = subprocess.Popen(["netstat", "-n", "-u", "-t", "-a"],
Expand Down Expand Up @@ -180,6 +198,42 @@ def _check_linux(self, instance):
}
self._submit_devicemetrics(iface, metrics)


proc = open('/proc/net/snmp', 'r')
# IP: Forwarding DefaultTTL InReceives InHdrErrors ...
# IP: 2 64 377145470 0 ...
# Icmp: InMsgs InErrors InDestUnreachs InTimeExcds ...
# Icmp: 1644495 1238 1643257 0 ...
# IcmpMsg: InType3 OutType3
# IcmpMsg: 1643257 1643257
# Tcp: RtoAlgorithm RtoMin RtoMax MaxConn ...
# Tcp: 1 200 120000 -1 ...
# Udp: InDatagrams NoPorts InErrors OutDatagrams ...
# Udp: 24249494 1643257 0 25892947 ...
# UdpLite: InDatagrams Noports InErrors OutDatagrams ...
# UdpLite: 0 0 0 0 ...
try:
lines = proc.readlines()
finally:
proc.close()

column_names = lines[6].strip().split()
values = lines[7].strip().split()

tcp_metrics = dict(zip(column_names,values))

# line start indicating what kind of metrics we're looking at
assert(tcp_metrics['Tcp:']=='Tcp:')

tcp_metrics_name = {
'RetransSegs': 'system.net.tcp.retrans_segs',
'InSegs' : 'system.net.tcp.in_segs',
'OutSegs' : 'system.net.tcp.out_segs'
}

for key, metric in tcp_metrics_name.iteritems():
self.rate(metric, self._parse_value(tcp_metrics[key]))

def _check_bsd(self, instance):
netstat = subprocess.Popen(["netstat", "-i", "-b"],
stdout=subprocess.PIPE,
Expand Down Expand Up @@ -246,6 +300,31 @@ def _check_bsd(self, instance):
}
self._submit_devicemetrics(iface, metrics)


netstat = subprocess.Popen(["netstat", "-s","-p" "tcp"],
stdout=subprocess.PIPE,
close_fds=True).communicate()[0]
#3651535 packets sent
# 972097 data packets (615753248 bytes)
# 5009 data packets (2832232 bytes) retransmitted
# 0 resends initiated by MTU discovery
# 2086952 ack-only packets (471 delayed)
# 0 URG only packets
# 0 window probe packets
# 310851 window update packets
# 336829 control packets
# 0 data packets sent after flow control
# 3058232 checksummed in software
# 3058232 segments (571218834 bytes) over IPv4
# 0 segments (0 bytes) over IPv6
#4807551 packets received
# 1143534 acks (for 616095538 bytes)
# 165400 duplicate acks
# ...

self._submit_regexed_values(netstat, BSD_TCP_METRICS)


def _check_solaris(self, instance):
# Can't get bytes sent and received via netstat
# Default to kstat -p link:0:
Expand All @@ -256,6 +335,21 @@ def _check_solaris(self, instance):
for interface, metrics in metrics_by_interface.iteritems():
self._submit_devicemetrics(interface, metrics)

netstat = subprocess.Popen(["netstat", "-s","-P" "tcp"],
stdout=subprocess.PIPE,
close_fds=True).communicate()[0]
# TCP: tcpRtoAlgorithm= 4 tcpRtoMin = 200
# tcpRtoMax = 60000 tcpMaxConn = -1
# tcpActiveOpens = 57 tcpPassiveOpens = 50
# tcpAttemptFails = 1 tcpEstabResets = 0
# tcpCurrEstab = 0 tcpOutSegs = 254
# tcpOutDataSegs = 995 tcpOutDataBytes =1216733
# tcpRetransSegs = 0 tcpRetransBytes = 0
# tcpOutAck = 185 tcpOutAckDelayed = 4
# ...
self._submit_regexed_values(netstat, SOLARIS_TCP_METRICS)


def _parse_solaris_netstat(self, netstat_output):
"""
Return a mapping of network metrics by interface. For example:
Expand Down
3 changes: 3 additions & 0 deletions tests/test_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,9 @@ def testNetwork(self):

assert 'system.net.bytes_rcvd' in metric_names
assert 'system.net.bytes_sent' in metric_names
assert 'system.net.tcp.retrans_segs' in metric_names
assert 'system.net.tcp.in_segs' in metric_names
assert 'system.net.tcp.out_segs' in metric_names


if __name__ == "__main__":
Expand Down