xref: /iperf/contrib/iperf3_to_gnuplot.py (revision 2d3eb211)
1#!/usr/bin/env python
2
3"""
4Extract iperf data from json blob and format for gnuplot.
5"""
6
7import json
8import os
9import sys
10
11from optparse import OptionParser
12
13import pprint
14# for debugging, so output to stderr to keep verbose
15# output out of any redirected stdout.
16pp = pprint.PrettyPrinter(indent=4, stream=sys.stderr)
17
18
19def generate_output(iperf, options):
20    """Do the actual formatting."""
21    for i in iperf.get('intervals'):
22        for ii in i.get('streams'):
23            if options.verbose:
24                pp.pprint(ii)
25            row = '{0} {1} {2} {3} {4}\n'.format(
26                round(float(ii.get('start')), 4),
27                ii.get('bytes'),
28                # to Gbits/sec
29                round(float(ii.get('bits_per_second')) / (1000*1000*1000), 3),
30                ii.get('retransmits'),
31                round(float(ii.get('snd_cwnd')) / (1000*1000), 2)
32            )
33            yield row
34
35
36def main():
37    """Execute the read and formatting."""
38    usage = '%prog [ -f FILE | -o OUT | -v ]'
39    parser = OptionParser(usage=usage)
40    parser.add_option('-f', '--file', metavar='FILE',
41                      type='string', dest='filename',
42                      help='Input filename.')
43    parser.add_option('-o', '--output', metavar='OUT',
44                      type='string', dest='output',
45                      help='Optional file to append output to.')
46    parser.add_option('-v', '--verbose',
47                      dest='verbose', action='store_true', default=False,
48                      help='Verbose debug output to stderr.')
49    options, _ = parser.parse_args()
50
51    if not options.filename:
52        parser.error('Filename is required.')
53
54    file_path = os.path.normpath(options.filename)
55
56    if not os.path.exists(file_path):
57        parser.error('{f} does not exist'.format(f=file_path))
58
59    with open(file_path, 'r') as fh:
60        data = fh.read()
61
62    try:
63        iperf = json.loads(data)
64    except Exception as ex:  # pylint: disable=broad-except
65        parser.error('Could not parse JSON from file (ex): {0}'.format(str(ex)))
66
67    if options.output:
68        absp = os.path.abspath(options.output)
69        output_dir, _ = os.path.split(absp)
70        if not os.path.exists(output_dir):
71            parser.error('Output file directory path {0} does not exist'.format(output_dir))
72        fh = open(absp, 'a')
73    else:
74        fh = sys.stdout
75
76    for i in generate_output(iperf, options):
77        fh.write(i)
78
79
80if __name__ == '__main__':
81    main()