Skip to content

Commit

Permalink
Proc netstats python module added
Browse files Browse the repository at this point in the history
It exports all you can find in /proc/net/netstat
without any further processing.
  • Loading branch information
ironsmile committed Aug 7, 2015
1 parent 37b6214 commit 124d256
Show file tree
Hide file tree
Showing 4 changed files with 240 additions and 70 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
.idea
*.pyc
*.sublime-project
*.sublime-workspace
21 changes: 21 additions & 0 deletions network/netstats/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
netstats
=====


Install
-------

Copy netstats.py from python_modules to your python modules directory, e.g. :

- /usr/lib/ganglia/python_modules
- /usr/lib64/ganglia/python_modules

Copy netstats.pyconf to the gmond conf.d directory, e.g. :

- /etc/ganglia/conf.d/

Tune the netstats.pyconf file to match your server interfaces and then restart gmond.

## AUTHOR

Author: Doychin Atanasov https://github.com/ironsmile
70 changes: 0 additions & 70 deletions network/netstats/conf.d/netstats.basic.pyconf
Original file line number Diff line number Diff line change
@@ -1,77 +1,7 @@
#######################################################################
# Use this config only if you interested in few metrics instead of
# the 100 or so metrics possible
#######################################################################

modules {
module {
name = "netstats"
language = "python"
}
}

collection_group {
collect_every = 15
time_threshold = 45

metric {
name = "tcpext_tcploss_percentage"
title = "TCP loss percentage"
value_threshold = 1.0
}

metric {
name = "tcp_retrans_percentage"
title = "TCP retransmit percentage"
value_threshold = 1.0
}

metric {
name = "tcp_outsegs"
title = "TCP segments sent"
value_threshold = 1.0
}

metric {
name = "tcp_insegs"
title = "TCP segments received"
value_threshold = 1.0
}

metric {
name = "udp_indatagrams"
title = "UDP packets in"
value_threshold = 1.0
}
metric {
name = "udp_outdatagrams"
title = "UDP packets out"
value_threshold = 1.0
}
metric {
name = "udp_inerrors"
title = "UDP packet receive errors"
value_threshold = 1.0
}

metric {
name = "udp_rcvbuferrors"
title = "UDP Receive buffer errors"
value_threshold = 1.0
}



metric {
name = "tcpext_listendrops"
title = "SYNs sent to LISTENing sockets ignored"
value_threshold = 1.0
}

metric {
name = "tcp_attemptfails"
title = "TCP Failed connection attempts"
value_threshold = 1.0
}

}
217 changes: 217 additions & 0 deletions network/netstats/python_modules/netstats.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import re
import sys
import traceback
import os
import threading
import time

MODULE_NAME = "netstat"
STATS_FILE = "/proc/net/netstat"

descriptors = list()
Desc_Skel = {}
_Worker_Thread = None
_Lock = threading.Lock() # synchronization lock
Debug = False


def dprint(f, *v):
if Debug:
print >>sys.stderr, MODULE_NAME + ": " + f % v


def floatable(str):
try:
float(str)
return True
except:
return False


class UpdateMetricThread(threading.Thread):
def __init__(self, params):
threading.Thread.__init__(self)

self.running = False
self.shuttingdown = False
self.refresh_rate = params["refresh_rate"]
self.mp = params["metrix_prefix"]
self.metric = {}
self.last_metric = {}

def shutdown(self):
self.shuttingdown = True

if not self.running:
return

self.join()

def run(self):
self.running = True

while not self.shuttingdown:
_Lock.acquire()
updated = self.update_metric()
_Lock.release()

if not updated:
time.sleep(0.2)
else:
if "time" in self.last_metric:
dprint("metric delta period %.3f" % (
self.metric['time'] -
self.last_metric['time']))

self.running = False

def update_metric(self):
if "time" in self.metric:
if (time.time() - self.metric['time']) < self.refresh_rate:
return False

dprint("updating metrics")

self.last_metric = self.metric.copy()

update_dict = {
'time': time.time(),
}

try:
for stat_type, key, value in netstat_iterator():
update_dict['%s_%s_%s' % (self.mp, stat_type, key)] = int(value)

except IOError:
dprint("unable to open " + STATS_FILE)
return False

self.metric.update(update_dict)

return True

def metric_delta(self, name):
val = 0

if name in self.metric and name in self.last_metric:
_Lock.acquire()
if self.metric['time'] - self.last_metric['time'] != 0:
val = (self.metric[name] - self.last_metric[name]) / (
self.metric['time'] - self.last_metric['time'])
_Lock.release()

return float(val)


def metric_init(params):
global descriptors, Desc_Skel, _Worker_Thread, Debug

# initialize skeleton of descriptors
Desc_Skel = {
'name': 'XXX',
'call_back': metric_delta,
'time_max': 60,
'value_type': 'float',
'format': '%d',
'units': 'XXX',
'slope': 'XXX', # zero|positive|negative|both
'description': 'XXX',
'groups': 'network'
}

params["refresh_rate"] = params.get("refresh_rate", 15)
params["metrix_prefix"] = params.get("metrix_prefix", MODULE_NAME)
Debug = params.get("debug", False)

dprint("debugging has been turned on")

_Worker_Thread = UpdateMetricThread(params)
_Worker_Thread.start()

mp = params["metrix_prefix"]

try:
for stat_type, key, value in netstat_iterator():
descriptors.append(create_desc(Desc_Skel, {
"name": '%s_%s_%s' % (mp, stat_type, key),
"units": "number",
"slope": "both",
"description": "Netstat %s metric %s" % (stat_type, key)
}))
except IOError:
return

return descriptors


def netstat_iterator():
f = open(STATS_FILE, 'r')

line_number = -1
labels = []
labels_type = None

with f:
for line in f:
line_number += 1

if not re.search(':', line):
continue

are_labels = (line_number % 2 == 0)

tokens = re.split('[:\s]+', line.strip())

if are_labels:
labels_type = tokens[0].strip(':')
labels = tokens[1:]
continue

values_type = tokens[0].strip(':')

if values_type != labels_type:
dprint("Expected values of type `%s` but they were `%s`" % (
labels_type, values_type))
continue

for ind, value in enumerate(tokens[1:]):
yield values_type, labels[ind], value


def create_desc(skel, prop):
d = skel.copy()
for k, v in prop.iteritems():
d[k] = v
return d


def metric_delta(name):
return _Worker_Thread.metric_delta(name)


def metric_cleanup():
_Worker_Thread.shutdown()

if __name__ == '__main__':
params = {
"debug": True,
"refresh_rate": 15
}

try:
metric_init(params)

while True:
time.sleep(params['refresh_rate'])
for d in descriptors:
v = d['call_back'](d['name'])
print ('value for %s is ' + d['format']) % (d['name'], v)
except KeyboardInterrupt:
time.sleep(0.2)
os._exit(1)
except:
traceback.print_exc()
os._exit(1)

0 comments on commit 124d256

Please sign in to comment.