1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
#!/usr/bin/env python
import sys
import requests
import signal
import curses
import time
import math
def eng_str( x, format='%s', si=False):
sign = ''
if x < 0:
x = -x
sign = '-'
exp = int( math.floor( math.log10( x)))
exp3 = exp - ( exp % 3)
x3 = x / float( 10 ** exp3)
if si and exp3 >= -24 and exp3 <= 24 and exp3 != 0:
exp3_text = 'yzafpnum KMGTPEZY'[ ( exp3 - (-24)) / 3]
elif exp3 == 0:
exp3_text = ''
else:
exp3_text = 'e%s' % exp3
return ( '%s'+format+'%s') % ( sign, x3, exp3_text)
def endSession():
curses.nocbreak(); stdscr.keypad(0); curses.echo()
curses.endwin()
def sig_handler(signal,frame):
endSession()
exit(0)
signal.signal(signal.SIGINT, sig_handler)
if __name__ == '__main__':
import optparse
import json
import os.path
parser = optparse.OptionParser()
parser.add_option("", "--flow", dest="flow", default="flows",
help="name of sFlow-RT flow defintion")
parser.add_option("", "--server", dest="server", default="localhost",
help="name or IP address of sFlow-RT server")
(options,args) = parser.parse_args()
specurl = 'http://' + options.server + ':8008/flow/' + options.flow + '/json'
r = requests.get(specurl)
if r.status_code != 200:
print('Cannot retrieve flow definition for ' + options.flow)
sys.exit(1)
spec = r.json()
keyfields = str(spec['keys']).split(',')
valuefield = str(spec['value'])
fieldsep = str(spec['fs'])
stdscr = curses.initscr()
curses.noecho()
curses.cbreak()
stdscr.keypad(1)
stdscr.nodelay(1)
pad = None
try:
while True:
ch = -1
ch = stdscr.getch()
if ch == ord('q'): break
if ch == ord('Q'): break
if ch == curses.KEY_RESIZE or pad is None:
(maxY,maxX) = stdscr.getmaxyx()
cw = maxX / (len(keyfields) + 1)
flowsurl = 'http://' + options.server + ':8008/activeflows/ALL/' + options.flow + '/json?maxFlows=' + str(maxY - 2)
pad = curses.newpad(maxY,maxX)
# get latest flow data
r = requests.get(flowsurl)
if r.status_code != 200: break
flows = r.json()
if len(flows) == 0: continue
# write headers
pad.clear()
for h in range(0,len(keyfields)):
pad.addstr(0,h * cw,format(keyfields[h],"<"+str(cw)),curses.A_STANDOUT)
pad.addstr(0,len(keyfields)*cw,format(valuefield,">"+str(cw)), curses.A_STANDOUT)
# write rows
for r in range(0, len(flows)):
keys = flows[r]['key'].split(',')
value = int(flows[r]['value'])
if value == 0: continue
for c in range(0,len(keys)):
pad.addstr(1+r,c * cw,format(keys[c],"<"+str(cw)))
# pad.addstr(1+r,len(keys)*cw,format(value,">"+str(cw)+".6g"))
pad.addstr(1+r,len(keys)*cw,format(eng_str(value,"%.3f",True),">"+str(cw)))
# sync to screen - may fail during resize
try: pad.refresh(0,0,0,0,maxY,maxX)
except: pass
# sleep may be interrupted - e.g. during resize
# so put this in a loop to make sure we don't
# thrash and send too many requests
wake = time.time() + 1.9
while True:
time.sleep(2)
if time.time() >= wake: break
finally:
endSession()
|