More configurability, and a test. mode for data

—testvalues will prefix all data points with “test.” and shift the timestamp range it pulls in to a similar sized range just before now().
This commit is contained in:
Alan Paxton 2022-03-21 12:58:24 +00:00
parent c7376003cf
commit 8441ebf197

View File

@ -11,6 +11,7 @@ In order to finally yield the output of benchmark tests.
import argparse import argparse
from ast import Dict from ast import Dict
from collections import namedtuple from collections import namedtuple
import datetime
import email import email
import itertools import itertools
import pickle import pickle
@ -26,6 +27,17 @@ import requests
from dateutil import parser from dateutil import parser
class Configuration:
graphite_server = 'localhost'
graphite_pickle_port = 2004
circle_user_id = 'e7d4aab13e143360f95e258be0a89b5c8e256773' # rotate those tokens !!
circle_vcs = 'github'
circle_username = 'facebook'
circle_project = 'rocksdb'
circle_ci_api = 'https://circleci.com/api/v2'
graphite_name_prefix = 'rocksdb.benchmark'
class TupleObject: class TupleObject:
def mapper(input_mapping): def mapper(input_mapping):
@ -210,17 +222,16 @@ class BenchmarkUtils:
return True return True
def enhance(row): def enhance(row):
(dt, fuzz) = parser.parse(row['test_date'], fuzzy_with_tokens=True) (dt, _) = parser.parse(row['test_date'], fuzzy_with_tokens=True)
row['timestamp'] = int(dt.timestamp()) row['timestamp'] = int(dt.timestamp())
return row return row
def graphite(row): def graphite(row, metric_path=Configuration.graphite_name_prefix):
'''Convert a row (dictionary of values) '''Convert a row (dictionary of values)
into the form of object that graphite likes to receive into the form of object that graphite likes to receive
( <path>, (<timestamp>, <value>) ) ( <path>, (<timestamp>, <value>) )
''' '''
result = [] result = []
metric_path = 'rocksdb.benchmark'
for metric_key in BenchmarkUtils.expected_keys: for metric_key in BenchmarkUtils.expected_keys:
metric_id = metric_path + '.' + row['test_name'] + '.' + metric_key metric_id = metric_path + '.' + row['test_name'] + '.' + metric_key
metric_value = 0.0 metric_value = 0.0
@ -229,10 +240,28 @@ class BenchmarkUtils:
except (ValueError, TypeError): except (ValueError, TypeError):
# metric doesn't have a float value # metric doesn't have a float value
continue continue
metric = (metric_id, (row['timestamp'], float(row[metric_key]))) metric = (metric_id, (row['timestamp'], metric_value))
result.append(metric) result.append(metric)
return result return result
def test_graphite(rows, metric_prefix='test.'):
'''Modify the output of graphite
Stick a test. in front of the name
Change times to shift range of samples up to just before now()
'''
max_ts = None
for row in rows:
(_, (timestamp, _)) = row
if max_ts == None or timestamp > max_ts:
max_ts = timestamp
delta = int(datetime.datetime.now().timestamp() - max_ts)
rows2 = []
for row in rows:
(metric_id, (timestamp, metric_value)) = row
rows2.append((metric_prefix + metric_id,
(timestamp + delta, metric_value)))
return rows2
class ResultParser: class ResultParser:
def __init__(self, field="(\w|[+-:.])+", intrafield="(\s)+", separator="\t"): def __init__(self, field="(\w|[+-:.])+", intrafield="(\s)+", separator="\t"):
@ -427,14 +456,19 @@ def load_reports_from_tsv(filename: str):
return report return report
def push_pickle_to_graphite(reports): def push_pickle_to_graphite(reports, test_values: bool):
sanitized = [[BenchmarkUtils.enhance(row) sanitized = [[BenchmarkUtils.enhance(row)
for row in rows if BenchmarkUtils.sanity_check(row)] for rows in reports] for row in rows if BenchmarkUtils.sanity_check(row)] for rows in reports]
graphite = [] graphite = []
for rows in sanitized: for rows in sanitized:
for row in rows: for row in rows:
for point in BenchmarkUtils.graphite(row): for point in BenchmarkUtils.graphite(row, Configuration.graphite_name_prefix):
graphite.append(point) graphite.append(point)
# Do this if we are asked to create a recent record of test. data points
if test_values:
graphite = BenchmarkUtils.test_graphite(graphite)
# Careful not to use too modern a protocol for Graphite (it is Python2) # Careful not to use too modern a protocol for Graphite (it is Python2)
payload = pickle.dumps(graphite, protocol=1) payload = pickle.dumps(graphite, protocol=1)
header = struct.pack("!L", len(payload)) header = struct.pack("!L", len(payload))
@ -456,16 +490,6 @@ def push_pickle_to_graphite(reports):
{'server': Configuration.graphite_server, 'port': Configuration.graphite_pickle_port}) {'server': Configuration.graphite_server, 'port': Configuration.graphite_pickle_port})
class Configuration:
graphite_server = 'localhost'
graphite_pickle_port = 2004
circle_user_id = 'e7d4aab13e143360f95e258be0a89b5c8e256773' # rotate those tokens !!
circle_vcs = 'github'
circle_username = 'facebook'
circle_project = 'rocksdb'
circle_ci_api = 'https://circleci.com/api/v2'
def main(): def main():
'''Fetch and parse benchmark results from CircleCI '''Fetch and parse benchmark results from CircleCI
Save to a pickle file Save to a pickle file
@ -485,12 +509,14 @@ def main():
# push results presented as a TSV file (slightly different proposed format) # push results presented as a TSV file (slightly different proposed format)
# this is how we get used "inline" on the test machine when running benchmarks # this is how we get used "inline" on the test machine when running benchmarks
# #
parser.add_argument('--action', choices=['fetch', 'push', 'all', 'tsv'], default='push', parser.add_argument('--action', choices=['fetch', 'push', 'all', 'tsv'], default='tsv',
help='Which action to perform') help='Which action to perform')
parser.add_argument('--picklefile', default='reports.pickle', parser.add_argument('--picklefile', default='reports.pickle',
help='File in which to save pickled report') help='File in which to save pickled report')
parser.add_argument('--tsvfile', default='build_tools/circle_api_scraper_input.txt', parser.add_argument('--tsvfile', default='build_tools/circle_api_scraper_input.txt',
help='File from which to read tsv report') help='File from which to read tsv report')
parser.add_arguments('--testvalues', default=False,
help='Timeshift and test. prefix values')
args = parser.parse_args() args = parser.parse_args()
if args.action == 'all': if args.action == 'all':
@ -503,10 +529,10 @@ def main():
pass pass
elif args.action == 'push': elif args.action == 'push':
reports = load_reports_from_local(args.picklefile) reports = load_reports_from_local(args.picklefile)
push_pickle_to_graphite(reports) push_pickle_to_graphite(reports, args.testvalues)
elif args.action == 'tsv': elif args.action == 'tsv':
reports = load_reports_from_tsv(args.tsvfile) reports = [load_reports_from_tsv(args.tsvfile)]
push_pickle_to_graphite(reports) push_pickle_to_graphite(reports, args.testvalues)
if __name__ == '__main__': if __name__ == '__main__':