Created
January 4, 2021 17:55
-
-
Save anarazel/c9a393d96cd54bd06e6a1c4b8cb1b0b6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import os | |
import sys | |
import re | |
from csv_helper import csv | |
import collections | |
import datetime | |
import signal | |
class PGBenchParser(object): | |
# progress: 560.0 s, 55376.5 tps, lat 0.866 ms stddev 0.268 | |
re_progress = re.compile(r"^progress: (\d+.\d+) s, (\d+.\d+) tps, lat (\d+.\d+) ms stddev (\d+.\d+|NaN)") | |
# latency average = 2.591 ms | |
# latency stddev = 1.300 ms | |
re_latency = re.compile(r"^latency (average|stddev) = (\d+.\d+) ms") | |
# tps = 18519.035816 (including connections establishing) | |
re_tps = re.compile(r"^tps = (\d+.\d+) \((including|excluding) connections establishing\)") | |
def __init__(self): | |
self.outdir = None | |
self.outputs = {} | |
def parse_pgbench(self, fh, outdir): | |
re_progress = self.re_progress | |
re_latency = self.re_latency | |
re_tps = self.re_tps | |
self.outdir = outdir | |
sum_stats = {} | |
for line in fh: | |
if line.startswith('progress'): | |
match = re_progress.match(line) | |
data = list(match.groups()) | |
if (float(data[0]) > 1000000000): | |
ts = datetime.datetime.fromtimestamp(float(match[1])) | |
ts = ts.astimezone() | |
data[0] = ts.isoformat(timespec = 'milliseconds') | |
self.output_progress(data) | |
elif line.startswith('latency'): | |
match = re_latency.match(line) | |
if match.group(1) == 'average': | |
sum_stats['lat_avg'] = match.group(2) | |
if match.group(1) == 'stddev': | |
sum_stats['lat_stddev'] = match.group(2) | |
elif line.startswith('tps'): | |
match = re_tps.match(line) | |
if match.group(2) == 'including': | |
sum_stats['tps_incl'] = match.group(1) | |
if match.group(2) == 'excluding': | |
sum_stats['tps_excl'] = match.group(1) | |
self.output_summary(sum_stats) | |
self.close_outputs() | |
self.outdir = None | |
progress_fieldnames = ('ts', 'tps', 'lat', 'stddev') | |
progress_filename = 'pgbench_progress.dat' | |
def output_progress(self, data): | |
name = self.progress_filename | |
fieldnames = self.progress_fieldnames | |
output = self.outputs.get(name, None) | |
if output is None: | |
output = self.CSVOutput(self.outdir, name, fieldnames) | |
self.outputs[name] = output | |
output.writer.writeheader() | |
output.writer.writerow(dict(zip(fieldnames, data))) | |
output.fh.flush() | |
summary_fieldnames = ('tps_incl', 'tps_excl', 'lat_avg', 'lat_stddev') | |
summary_filename = 'pgbench_summary.dat' | |
def output_summary(self, data): | |
name = self.summary_filename | |
fieldnames = self.summary_fieldnames | |
output = self.outputs.get(name, None) | |
if output is None: | |
output = self.CSVOutput(self.outdir, name, fieldnames) | |
self.outputs[name] = output | |
output.writer.writeheader() | |
output.writer.writerow(data) | |
output.fh.flush() | |
def close_outputs(self): | |
for key in list(self.outputs.keys()): | |
output = self.outputs.pop(key) | |
output.close() | |
assert(len(self.outputs) == 0) | |
class CSVOutput(object): | |
__slots__ = ['fh', 'writer'] | |
def __init__(self, outdir, name, fieldnames): | |
fname = os.path.join(outdir, name) | |
print(fname) | |
self.fh = open(fname, 'w') | |
self.writer = csv.DictWriter(self.fh, dialect='unix_tab', fieldnames=fieldnames) | |
def close(self): | |
del self.writer | |
self.fh.close() | |
del self.fh | |
def terminate_cleanly(signo, frame): | |
sys.stderr.write("\n") | |
sys.exit(0) | |
# FIXME: Add proper argument parsing | |
if __name__ == "__main__": | |
signal.signal(signal.SIGINT, terminate_cleanly) | |
signal.signal(signal.SIGTERM, terminate_cleanly) | |
parser = PGBenchParser() | |
for f in sys.argv[1:]: | |
if f == '-': | |
parser.parse_pgbench(sys.stdin, sys.argv[2]) | |
break; | |
else: | |
outdir = os.path.dirname(os.path.abspath(f)) | |
with open(f, "r") as fh: | |
parser.parse_pgbench(fh, outdir) |
Author
anarazel
commented
Jan 4, 2021
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment