summaryrefslogtreecommitdiff
path: root/sflow-rt/extras/topflows.py
diff options
context:
space:
mode:
author姜萍 <[email protected]>2022-05-29 17:59:26 +0800
committer姜萍 <[email protected]>2022-05-29 17:59:26 +0800
commit9f0f12ed28357ae167cb9aab3a614da0f8cd4bab (patch)
tree0eac2d3fbfc11e7639b9a0254a8c24d8a43bd8f2 /sflow-rt/extras/topflows.py
initmaster
Diffstat (limited to 'sflow-rt/extras/topflows.py')
-rwxr-xr-xsflow-rt/extras/topflows.py114
1 files changed, 114 insertions, 0 deletions
diff --git a/sflow-rt/extras/topflows.py b/sflow-rt/extras/topflows.py
new file mode 100755
index 0000000..ee234c8
--- /dev/null
+++ b/sflow-rt/extras/topflows.py
@@ -0,0 +1,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()
+