version 1.1.1.1, 2016/10/18 13:28:18
|
version 1.1.1.2, 2021/03/17 00:36:45
|
Line 1
|
Line 1
|
#!/usr/bin/env python
|
|
|
|
"""
|
|
Extract iperf data from json blob and format for gnuplot.
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import sys
|
|
|
|
import os.path
|
|
from optparse import OptionParser
|
|
|
|
import pprint
|
|
# for debugging, so output to stderr to keep verbose
|
|
# output out of any redirected stdout.
|
|
pp = pprint.PrettyPrinter(indent=4, stream=sys.stderr)
|
|
|
|
def generate_output(iperf, options):
|
|
for i in iperf.get('intervals'):
|
|
for ii in i.get('streams'):
|
|
if options.verbose: pp.pprint(ii)
|
|
row = '{0} {1} {2} {3} {4}\n'.format(
|
|
round(float(ii.get('start')), 4),
|
|
ii.get('bytes'),
|
|
# to Gbits/sec
|
|
round(float(ii.get('bits_per_second')) / (1000*1000*1000), 3),
|
|
ii.get('retransmits'),
|
|
round(float(ii.get('snd_cwnd')) / (1000*1000), 2)
|
|
)
|
|
yield row
|
|
|
|
def main():
|
|
usage = '%prog [ -f FILE | -o OUT | -v ]'
|
|
parser = OptionParser(usage=usage)
|
|
parser.add_option('-f', '--file', metavar='FILE',
|
|
type='string', dest='filename',
|
|
help='Input filename.')
|
|
parser.add_option('-o', '--output', metavar='OUT',
|
|
type='string', dest='output',
|
|
help='Optional file to append output to.')
|
|
parser.add_option('-v', '--verbose',
|
|
dest='verbose', action='store_true', default=False,
|
|
help='Verbose debug output to stderr.')
|
|
options, args = parser.parse_args()
|
|
|
|
if not options.filename:
|
|
parser.error('Filename is required.')
|
|
|
|
file_path = os.path.normpath(options.filename)
|
|
|
|
if not os.path.exists(file_path):
|
|
parser.error('{f} does not exist'.format(f=file_path))
|
|
|
|
with open(file_path,'r') as fh:
|
|
data = fh.read()
|
|
|
|
try:
|
|
iperf = json.loads(data)
|
|
except Exception as e:
|
|
parser.error('Could not parse JSON from file (ex): {0}'.format(str(e)))
|
|
|
|
if options.output:
|
|
absp = os.path.abspath(options.output)
|
|
d,f = os.path.split(absp)
|
|
if not os.path.exists(d):
|
|
parser.error('Output file directory path {0} does not exist'.format(d))
|
|
fh = open(absp, 'a')
|
|
else:
|
|
fh = sys.stdout
|
|
|
|
for i in generate_output(iperf, options):
|
|
fh.write(i)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main() |
|
|
|
|
#!/usr/bin/env python |
|
|
|
""" |
|
Extract iperf data from json blob and format for gnuplot. |
|
""" |
|
|
|
import json |
|
import os |
|
import sys |
|
|
|
from optparse import OptionParser |
|
|
|
import pprint |
|
# for debugging, so output to stderr to keep verbose |
|
# output out of any redirected stdout. |
|
pp = pprint.PrettyPrinter(indent=4, stream=sys.stderr) |
|
|
|
|
|
def generate_output(iperf, options): |
|
"""Do the actual formatting.""" |
|
for i in iperf.get('intervals'): |
|
for ii in i.get('streams'): |
|
if options.verbose: |
|
pp.pprint(ii) |
|
row = '{0} {1} {2} {3} {4}\n'.format( |
|
round(float(ii.get('start')), 4), |
|
ii.get('bytes'), |
|
# to Gbits/sec |
|
round(float(ii.get('bits_per_second')) / (1000*1000*1000), 3), |
|
ii.get('retransmits'), |
|
round(float(ii.get('snd_cwnd')) / (1000*1000), 2) |
|
) |
|
yield row |
|
|
|
|
|
def summed_output(iperf, options): |
|
"""Format summed output.""" |
|
|
|
for i in iperf.get('intervals'): |
|
|
|
row_header = None |
|
|
|
byte = list() |
|
bits_per_second = list() |
|
retransmits = list() |
|
snd_cwnd = list() |
|
|
|
for ii in i.get('streams'): |
|
if options.verbose: |
|
pp.pprint(i) |
|
# grab the first start value |
|
if row_header is None: |
|
row_header = round(float(ii.get('start')), 2) |
|
# aggregate the rest of the values |
|
byte.append(ii.get('bytes')) |
|
bits_per_second.append(float(ii.get('bits_per_second')) / (1000*1000*1000)) |
|
retransmits.append(ii.get('retransmits')) |
|
snd_cwnd.append(float(ii.get('snd_cwnd')) / (1000*1000)) |
|
|
|
row = '{h} {b} {bps} {r} {s}\n'.format( |
|
h=row_header, |
|
b=sum(byte), |
|
bps=round(sum(bits_per_second), 3), |
|
r=sum(retransmits), |
|
s=round(sum(snd_cwnd) / len(snd_cwnd), 2) |
|
) |
|
|
|
yield row |
|
|
|
|
|
def main(): |
|
"""Execute the read and formatting.""" |
|
usage = '%prog [ -f FILE | -o OUT | -v ]' |
|
parser = OptionParser(usage=usage) |
|
parser.add_option('-f', '--file', metavar='FILE', |
|
type='string', dest='filename', |
|
help='Input filename.') |
|
parser.add_option('-o', '--output', metavar='OUT', |
|
type='string', dest='output', |
|
help='Optional file to append output to.') |
|
parser.add_option('-s', '--sum', |
|
dest='summed', action='store_true', default=False, |
|
help='Summed version of the output.') |
|
parser.add_option('-v', '--verbose', |
|
dest='verbose', action='store_true', default=False, |
|
help='Verbose debug output to stderr.') |
|
options, _ = parser.parse_args() |
|
|
|
if not options.filename: |
|
parser.error('Filename is required.') |
|
|
|
file_path = os.path.normpath(options.filename) |
|
|
|
if not os.path.exists(file_path): |
|
parser.error('{f} does not exist'.format(f=file_path)) |
|
|
|
with open(file_path, 'r') as fh: |
|
data = fh.read() |
|
|
|
try: |
|
iperf = json.loads(data) |
|
except Exception as ex: # pylint: disable=broad-except |
|
parser.error('Could not parse JSON from file (ex): {0}'.format(str(ex))) |
|
|
|
if options.output: |
|
absp = os.path.abspath(options.output) |
|
output_dir, _ = os.path.split(absp) |
|
if not os.path.exists(output_dir): |
|
parser.error('Output file directory path {0} does not exist'.format(output_dir)) |
|
fh = open(absp, 'a') |
|
else: |
|
fh = sys.stdout |
|
|
|
if options.summed: |
|
fmt = summed_output |
|
else: |
|
fmt = generate_output |
|
|
|
for i in fmt(iperf, options): |
|
fh.write(i) |
|
|
|
|
|
if __name__ == '__main__': |
|
main() |