Skip to content

Commit 3bec8bf

Browse files
Fixed run exec regarding multiple tear-down steps (#7)
* [fix] fixed static project being redisearch for it to be loaded from the config * [fix] Fixed run exec regarding multiple teardown steps
1 parent 019d08a commit 3bec8bf

File tree

8 files changed

+363
-278
lines changed

8 files changed

+363
-278
lines changed

poetry.lock

Lines changed: 272 additions & 212 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[tool.poetry]
22
name = "redisbench-admin"
3-
version = "0.1.10"
4-
description = "Redis benchmark run helper. A wrapper around ftsb_redisearch ( future versions will also support redis-benchmark and memtier_benchmark )."
3+
version = "0.1.11"
4+
description = "Redis benchmark run helper. A wrapper around Redis and Redis Modules benchmark tools ( ftsb_redisearch, memtier_benchmark, redis-benchmark, aibench, etc... )."
55
authors = ["filipecosta90 <[email protected]>"]
66
readme = "README.md"
77

redisbench_admin/cli.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import argparse
22
import sys
33

4+
# import toml
45
import toml
56

67
from redisbench_admin import __version__

redisbench_admin/export/args.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,15 @@ def create_export_arguments(parser):
33
help="benchmark results files to read results from. can be a local file, a remote link, or an s3 bucket.")
44
parser.add_argument('--steps', type=str, default="setup,benchmark",
55
help="comma separated list of steps to be analyzed given the benchmark result files")
6-
parser.add_argument('--exporter', type=str, default="csv",
6+
parser.add_argument('--exporter', type=str, default="redistimeseries",
77
help="exporter to be used ( either csv or redistimeseries )")
88
parser.add_argument('--use-result', type=str, default="median-result",
99
help="for each key-metric, use either worst-result, best-result, or median-result")
1010
parser.add_argument('--extra-tags', type=str, default="", help='comma separated extra tags in the format of key1=value,key2=value,...')
11+
parser.add_argument('--host', type=str, default="localhost",
12+
help="redistimeseries host")
13+
parser.add_argument('--port', type=int, default=6379,
14+
help="redistimeseries port")
15+
parser.add_argument('--password', type=str, default=None,
16+
help="redistimeseries password")
1117
return parser

redisbench_admin/export/export.py

Lines changed: 43 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
import os
22
import pandas as pd
3+
import redis
4+
35
from redisbench_admin.compare.compare import get_key_results_and_values
46
from redisbench_admin.utils.utils import retrieve_local_or_remote_input_json
57
import matplotlib.pyplot as plt
68
import seaborn as sns
9+
710
sns.set(style="darkgrid")
811
from redistimeseries.client import Client
912

13+
1014
def get_timeserie_name(labels_kv_array):
1115
name = ""
1216
for label_kv in labels_kv_array:
1317
k = list(label_kv.keys())[0]
1418
v = list(label_kv.values())[0]
15-
k= prepare_tags(k)
19+
k = prepare_tags(k)
1620
v = prepare_tags(v)
1721
if name != "":
1822
name += ":"
@@ -47,7 +51,7 @@ def extract_benchmark_config_details(benchmark_result):
4751
specifications_version = benchmark_config["specifications-version"]
4852
testcase_description = benchmark_config["description"]
4953
key_metrics_specs = benchmark_config["key-metrics"]
50-
return testcase_name, specifications_version, testcase_description,key_metrics_specs
54+
return testcase_name, specifications_version, testcase_description, key_metrics_specs
5155

5256

5357
def extract_key_configs(benchmark_result):
@@ -66,14 +70,14 @@ def extract_key_configs(benchmark_result):
6670
return deployment_type, deployment_shards, project, project_version, git_sha
6771

6872

69-
def add_datapoint(time_series_dict, broader_ts_name, start_time_ms, metric_value, tags_array ):
73+
def add_datapoint(time_series_dict, broader_ts_name, start_time_ms, metric_value, tags_array):
7074
if broader_ts_name not in time_series_dict:
7175
tags_dict = {}
7276
for tag_kv in tags_array:
7377
k = list(tag_kv.keys())[0]
7478
v = list(tag_kv.values())[0]
75-
tags_dict[k]=v
76-
time_series_dict[broader_ts_name]={"index":[],"data":[],"tags-array":tags_array, "tags":tags_dict}
79+
tags_dict[k] = v
80+
time_series_dict[broader_ts_name] = {"index": [], "data": [], "tags-array": tags_array, "tags": tags_dict}
7781
time_series_dict[broader_ts_name]["index"].append(start_time_ms)
7882
time_series_dict[broader_ts_name]["data"].append(metric_value)
7983

@@ -85,9 +89,9 @@ def split_tags_string(extra_tags):
8589
for extra_tag in extra_tags:
8690
kv = extra_tag.split("=")
8791
if len(kv) == 2:
88-
k= prepare_tags (kv[0])
92+
k = prepare_tags(kv[0])
8993
v = prepare_tags(kv[1])
90-
result.append({k:v})
94+
result.append({k: v})
9195
return result
9296

9397

@@ -99,33 +103,36 @@ def split_key_metrics_by_step(key_metrics_specs):
99103
step = key_metric_spec["step"]
100104
metric_name = key_metric_spec["metric-name"]
101105
if step not in key_metrics_by_step:
102-
key_metrics_by_step[step]={}
103-
key_metrics_by_step[step][metric_name]=key_metric_spec
106+
key_metrics_by_step[step] = {}
107+
key_metrics_by_step[step][metric_name] = key_metric_spec
104108
return key_metrics_by_step
105109

106-
def get_or_None(dict,property):
110+
111+
def get_or_None(dict, property):
107112
result = None
108113
if property in dict:
109114
result = dict[property]
110115
return result
111116

117+
112118
def get_metric_detail(key_metric_spec):
113-
metric_step = get_or_None( key_metric_spec, "step")
114-
metric_family = get_or_None( key_metric_spec, "metric-family")
119+
metric_step = get_or_None(key_metric_spec, "step")
120+
metric_family = get_or_None(key_metric_spec, "metric-family")
115121
metric_json_path = get_or_None(key_metric_spec, "metric-json-path")
116-
metric_name = get_or_None( key_metric_spec, "metric-name")
117-
metric_unit = get_or_None( key_metric_spec, "unit")
118-
metric_type = get_or_None( key_metric_spec, "metric-type")
119-
metric_comparison = get_or_None( key_metric_spec, "comparison")
120-
metric_per_step_comparison_priority = get_or_None( key_metric_spec, "per-step-comparison-metric-priority")
121-
return metric_step,metric_family,metric_json_path,metric_name,metric_unit,metric_type,metric_comparison,metric_per_step_comparison_priority
122+
metric_name = get_or_None(key_metric_spec, "metric-name")
123+
metric_unit = get_or_None(key_metric_spec, "unit")
124+
metric_type = get_or_None(key_metric_spec, "metric-type")
125+
metric_comparison = get_or_None(key_metric_spec, "comparison")
126+
metric_per_step_comparison_priority = get_or_None(key_metric_spec, "per-step-comparison-metric-priority")
127+
return metric_step, metric_family, metric_json_path, metric_name, metric_unit, metric_type, metric_comparison, metric_per_step_comparison_priority
128+
122129

123130
def export_command_logic(args):
124131
benchmark_files = args.benchmark_result_files
125132
local_path = os.path.abspath(args.local_dir)
126133
use_result = args.use_result
127134
included_steps = args.steps.split(",")
128-
135+
129136
extra_tags_array = split_tags_string(args.extra_tags)
130137
print(extra_tags_array)
131138
results_type = "key-results"
@@ -134,10 +141,12 @@ def export_command_logic(args):
134141
for filename, benchmark_result in benchmark_results.items():
135142
print(filename)
136143
key_result_steps = benchmark_result[results_type].keys()
137-
testcase_name, specifications_version, testcase_description,key_metrics_specs = extract_benchmark_config_details(benchmark_result)
144+
testcase_name, specifications_version, testcase_description, key_metrics_specs = extract_benchmark_config_details(
145+
benchmark_result)
138146
key_metrics_specs_per_step = split_key_metrics_by_step(key_metrics_specs)
139147
deployment_type, deployment_shards, project, project_version, git_sha = extract_key_configs(benchmark_result)
140-
start_time_ms, start_time_humanized, end_time_ms, end_time_humanized, duration_ms, duration_humanized = extract_benchmark_run_info_details(benchmark_result)
148+
start_time_ms, start_time_humanized, end_time_ms, end_time_humanized, duration_ms, duration_humanized = extract_benchmark_run_info_details(
149+
benchmark_result)
141150

142151
for step in key_result_steps:
143152
common_broader_kv_tags = [
@@ -168,8 +177,7 @@ def export_command_logic(args):
168177
git_sha_ts_name = get_timeserie_name(git_sha_kv)
169178

170179
key_metric_spec = key_metrics_specs[metric_name]
171-
metric_step, metric_family, _, _, metric_unit, _, _,_ = get_metric_detail(key_metric_spec)
172-
180+
metric_step, metric_family, _, _, metric_unit, _, _, _ = get_metric_detail(key_metric_spec)
173181

174182
# add_datapoint(time_series_dict,broader_ts_name,start_time_ms,metric_value,tags_kv)
175183
# add_datapoint(time_series_dict, version_ts_name, start_time_ms, metric_value, tags_kv)
@@ -178,30 +186,18 @@ def export_command_logic(args):
178186
git_sha_tags_kv.extend(
179187
[{"metric-step": metric_step}, {"metric-family": metric_family}, {"metric-unit": metric_unit}])
180188
add_datapoint(time_series_dict, git_sha_ts_name, start_time_ms, metric_value, git_sha_tags_kv)
181-
# print(broader_ts_name)
182-
# print(version_ts_name)
183-
# print(git_sha_ts_name)
184-
# print(time_series_dict)
185-
rts = Client()
189+
rts = Client(host=args.host,port=args.port,password=args.password)
186190
for timeseries_name, time_series in time_series_dict.items():
187-
rts.create(timeseries_name,labels=time_series['tags'])
188-
for pos,timestamp in enumerate(time_series['index']):
191+
try:
192+
rts.create(timeseries_name, labels=time_series['tags'])
193+
except redis.exceptions.ResponseError:
194+
# if ts already exists continue
195+
pass
196+
for pos, timestamp in enumerate(time_series['index']):
189197
value = time_series['data'][pos]
190-
rts.add(timeseries_name, timestamp, value)
191-
192-
#
193-
# index = pd.to_datetime(time_series['index'], unit='ms')
194-
# df = pd.Series(time_series['data'], index=index)
195-
# print(df)
196-
197-
# import matplotlib.pyplot as plt
198-
# fig, ax = plt.subplots()
199-
# # Plot the responses for different events and regions
200-
# sns.lineplot( x="timepoint", y="signal",
201-
# data=df, ax=ax)
202-
# bottom, top = plt.ylim()
203-
# plt.ylim(0,top)
204-
# plt.savefig('{}.png'.format(timeseries_name))
205-
206-
198+
try:
199+
rts.add(timeseries_name, timestamp, value)
200+
except redis.exceptions.ResponseError:
201+
# if ts already exists continue
202+
pass
207203

redisbench_admin/run/ftsb_redisearch/ftsb_redisearch.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
# Copyright (C) 2020 Redis Labs Ltd.
2+
#
3+
# This file is part of redisbench-admin.
4+
#
5+
# redisbench-admin is free software: you can redistribute it and/or modify
6+
# it under the terms of the GNU General Public License as published by
7+
# the Free Software Foundation, version 2.
8+
#
9+
# redisbench-admin is distributed in the hope that it will be useful,
10+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
# GNU General Public License for more details.
13+
#
14+
# You should have received a copy of the GNU General Public License
15+
# along with redisbench-admin. If not, see <http://www.gnu.org/licenses/>.
16+
117
import json
218
import os
319
import subprocess
@@ -17,7 +33,7 @@ def get_run_options():
1733

1834

1935
def run_ftsb_redisearch(redis_url, ftsb_redisearch_path, setup_run_json_output_fullpath, options, input_file,
20-
workers):
36+
workers=1,args=[]):
2137
##################
2238
# Setup commands #
2339
##################

redisbench_admin/run/run.py

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -97,15 +97,7 @@ def run_command_logic(args):
9797
benchmark_infra["db-machines"]["db-machine-1"] = db_machine_1
9898
benchmark_infra["total-db-machines"] += 1
9999
benchmark_output_dict["key-configs"] = key_configs
100-
print("Running setup steps...")
101-
for command in benchmark_config["setup"]["commands"]:
102-
try:
103-
aux_client = redis.from_url(args.redis_url)
104-
aux_client.execute_command(" ".join(command))
105-
except redis.connection.ConnectionError as e:
106-
print('Error while issuing setup command to Redis.Command {}! Error message: {} Exiting..'.format(command,
107-
e.__str__()))
108-
sys.exit(1)
100+
109101
###############################
110102
# Go client stage starts here #
111103
###############################
@@ -118,16 +110,17 @@ def run_command_logic(args):
118110
total_steps += total_steps
119111
progress = tqdm(unit="bench steps", total=total_steps)
120112
for repetition in range(1, args.repetitions + 1):
121-
if "setup" in run_stages_inputs:
122-
if benchmark_repetitions_require_teardown is True or repetition == 1:
113+
if benchmark_repetitions_require_teardown is True or repetition == 1:
114+
aux_client = run_setup_commands(args, aux_client, benchmark_config)
115+
if "setup" in run_stages_inputs:
123116
setup_run_key = "setup-run-{}.json".format(repetition)
124117
setup_run_json_output_fullpath = "{}/{}".format(local_path, setup_run_key)
125118
input_file = run_stages_inputs["setup"]
126119
benchmark_output_dict["setup"][setup_run_key] = run_ftsb_redisearch(args.redis_url,
127120
benchmark_tool_path,
128121
setup_run_json_output_fullpath,
129122
options, input_file, workers)
130-
progress.update()
123+
progress.update()
131124

132125
######################
133126
# Benchmark commands #
@@ -196,6 +189,19 @@ def run_command_logic(args):
196189
upload_artifacts_to_s3(artifacts, s3_bucket_name, s3_bucket_path)
197190

198191

192+
def run_setup_commands(args, aux_client, benchmark_config):
193+
print("Running setup steps...")
194+
for command in benchmark_config["setup"]["commands"]:
195+
try:
196+
aux_client = redis.from_url(args.redis_url)
197+
aux_client.execute_command(" ".join(command))
198+
except redis.connection.ConnectionError as e:
199+
print('Error while issuing setup command to Redis.Command {}! Error message: {} Exiting..'.format(command,
200+
e.__str__()))
201+
sys.exit(1)
202+
return aux_client
203+
204+
199205
def prepare_run_info_metadata_dict(end_time, start_time):
200206
start_time_str = start_time.strftime("%Y-%m-%d-%H-%M-%S")
201207
end_time_str = end_time.strftime("%Y-%m-%d-%H-%M-%S")

redisbench_admin/utils/utils.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,20 +73,20 @@ def ts_milli(at_dt):
7373

7474

7575
def retrieve_local_or_remote_input_json(config_filename, local_path, option_name):
76-
benchmark_config = None
76+
benchmark_config = {}
7777

7878
if config_filename.startswith("http"):
7979
print("retrieving benchmark config file from remote url {}".format(config_filename))
8080
r = requests.get(config_filename)
81-
benchmark_config = r.json()
81+
benchmark_config[config_filename] = r.json()
8282
remote_filename = config_filename[config_filename.rfind('/') + 1:]
8383
local_config_file = "{}/{}".format(local_path, remote_filename)
8484
open(local_config_file, 'wb').write(r.content)
8585
print("To avoid fetching again the config file use the option {option_name} {filename}".format(
8686
option_name=option_name,
8787
filename=local_config_file))
8888

89-
elif config_filename.startswith("S3://"):
89+
elif config_filename.startswith("S3://") or config_filename.startswith("s3://"):
9090
print("s3")
9191
s3 = boto3.resource('s3')
9292
bucket_str = config_filename[5:].split("/")[0]

0 commit comments

Comments
 (0)