redisbench-admin 0.11.40__py3-none-any.whl → 0.11.42__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -131,6 +131,7 @@ def create_compare_arguments(parser):
131
131
  parser.add_argument("--simple-table", type=bool, default=False)
132
132
  parser.add_argument("--use_metric_context_path", type=bool, default=False)
133
133
  parser.add_argument("--testname_regex", type=str, default=".*", required=False)
134
+ parser.add_argument("--test-regex", type=str, default=".*", required=False)
134
135
  parser.add_argument(
135
136
  "--regressions-percent-lower-limit",
136
137
  type=float,
@@ -254,7 +254,9 @@ def compare_command_logic(args, project_name, project_version):
254
254
  uid = args.grafana_uid
255
255
  if tf_github_repo.lower() in grafana_dashboards_uids and uid is None:
256
256
  uid = grafana_dashboards_uids[tf_github_repo.lower()]
257
- logging.info(f"Using uid from grafana_dashboards_uids. {grafana_dashboards_uids}. uid={uid}")
257
+ logging.info(
258
+ f"Using uid from grafana_dashboards_uids. {grafana_dashboards_uids}. uid={uid}"
259
+ )
258
260
  else:
259
261
  logging.info(f"Using uid from args. uid={uid}")
260
262
  grafana_link_base = None
@@ -324,9 +326,7 @@ def compare_command_logic(args, project_name, project_version):
324
326
  comparison_summary = "In summary:\n"
325
327
  if total_stable > 0:
326
328
  comparison_summary += (
327
- "- Detected a total of {} stable tests between versions.\n".format(
328
- total_stable,
329
- )
329
+ f"- Detected a total of {total_stable} stable tests between versions.\n"
330
330
  )
331
331
 
332
332
  if total_unstable > 0:
@@ -388,13 +388,10 @@ def compare_command_logic(args, project_name, project_version):
388
388
 
389
389
  comparison_summary += f" - {test_display_name}: {', '.join(commands_info)}{confidence_indicator}\n"
390
390
  if total_improvements > 0:
391
- comparison_summary += "- Detected a total of {} improvements above the improvement water line.\n".format(
392
- total_improvements
393
- )
391
+ comparison_summary += f"- Detected a total of {total_improvements} improvements above the improvement water line.\n"
394
392
  if total_regressions > 0:
395
- comparison_summary += "- Detected a total of {} regressions bellow the regression water line {}.\n".format(
396
- total_regressions, args.regressions_percent_lower_limit
397
- )
393
+ comparison_summary += f"- Detected a total of {total_regressions} regressions bellow the regression water line {args.regressions_percent_lower_limit}%.\n"
394
+ comparison_summary += "\n"
398
395
 
399
396
  comment_body += comparison_summary
400
397
  comment_body += "\n"
@@ -130,5 +130,32 @@ def create_run_remote_arguments(parser):
130
130
  action="store_true",
131
131
  help="Continue running benchmarks even if module check failed",
132
132
  )
133
+ parser.add_argument(
134
+ "--redis-conf",
135
+ required=False,
136
+ default=None,
137
+ type=str,
138
+ help="Path to custom redis.conf file to copy to remote host",
139
+ )
140
+ parser.add_argument(
141
+ "--redis-server-binary",
142
+ required=False,
143
+ default=None,
144
+ type=str,
145
+ help="Path to custom redis-server binary to copy to remote host",
146
+ )
147
+ parser.add_argument(
148
+ "--spin-test",
149
+ default=False,
150
+ action="store_true",
151
+ help="Setup standalone Redis server, run INFO SERVER, print output as markdown and exit",
152
+ )
153
+ parser.add_argument(
154
+ "--spin-test-config",
155
+ required=False,
156
+ default=None,
157
+ type=str,
158
+ help="Optional benchmark configuration file for spin-test mode (to execute install_steps)",
159
+ )
133
160
 
134
161
  return parser
@@ -51,6 +51,7 @@ from redisbench_admin.run_remote.remote_db import (
51
51
  remote_db_spin,
52
52
  db_error_artifacts,
53
53
  )
54
+ from redisbench_admin.run_remote.standalone import spin_test_standalone_redis
54
55
  from redisbench_admin.run_remote.remote_env import remote_env_setup
55
56
  from redisbench_admin.run_remote.remote_failures import failed_remote_run_artifact_store
56
57
  from redisbench_admin.run_remote.terraform import (
@@ -122,12 +123,15 @@ def run_remote_command_logic(args, project_name, project_version):
122
123
  tf_setup_name_sufix = "{}-{}".format(args.setup_name_sufix, tf_github_sha)
123
124
  s3_bucket_name = args.s3_bucket_name
124
125
  local_module_files = args.module_path
125
- for pos, module_file in enumerate(local_module_files):
126
- if " " in module_file:
127
- logging.info(
128
- "Detected multiple files in single module path {}".format(module_file)
129
- )
130
- local_module_files[pos] = module_file.split(" ")
126
+ if local_module_files is not None:
127
+ for pos, module_file in enumerate(local_module_files):
128
+ if " " in module_file:
129
+ logging.info(
130
+ "Detected multiple files in single module path {}".format(
131
+ module_file
132
+ )
133
+ )
134
+ local_module_files[pos] = module_file.split(" ")
131
135
  dbdir_folder = args.dbdir_folder
132
136
  private_key = args.private_key
133
137
  grafana_profile_dashboard = args.grafana_profile_dashboard
@@ -238,6 +242,63 @@ def run_remote_command_logic(args, project_name, project_version):
238
242
 
239
243
  ssh_pem_check(EC2_PRIVATE_PEM, private_key)
240
244
 
245
+ # Handle spin-test mode
246
+ if args.spin_test:
247
+ logging.info(
248
+ "🚀 Spin-test mode detected - setting up standalone Redis and running INFO SERVER"
249
+ )
250
+
251
+ # Parse inventory to get server details
252
+ if args.inventory is None:
253
+ logging.error(
254
+ "❌ --spin-test requires --inventory to specify the remote server"
255
+ )
256
+ exit(1)
257
+
258
+ # Parse inventory string
259
+ inventory_parts = args.inventory.split(",")
260
+ server_public_ip = None
261
+
262
+ for part in inventory_parts:
263
+ if "=" in part:
264
+ key, value = part.split("=", 1)
265
+ if key.strip() == "server_public_ip":
266
+ server_public_ip = value.strip()
267
+ break
268
+
269
+ if server_public_ip is None:
270
+ logging.error("❌ --spin-test requires server_public_ip in --inventory")
271
+ exit(1)
272
+
273
+ # Load benchmark config if provided
274
+ benchmark_config = None
275
+ if args.spin_test_config:
276
+ try:
277
+ import yaml
278
+ with open(args.spin_test_config, 'r') as config_file:
279
+ benchmark_config = yaml.safe_load(config_file)
280
+ logging.info(f"📋 Loaded benchmark config from {args.spin_test_config}")
281
+ except Exception as e:
282
+ logging.error(f"❌ Failed to load benchmark config: {e}")
283
+ exit(1)
284
+
285
+ # Run spin test
286
+ success = spin_test_standalone_redis(
287
+ server_public_ip=server_public_ip,
288
+ username=args.user,
289
+ private_key=private_key,
290
+ db_ssh_port=args.db_ssh_port,
291
+ redis_port=args.db_port,
292
+ local_module_files=local_module_files,
293
+ redis_configuration_parameters=None,
294
+ modules_configuration_parameters_map=None,
295
+ custom_redis_conf_path=args.redis_conf,
296
+ custom_redis_server_path=args.redis_server_binary,
297
+ benchmark_config=benchmark_config,
298
+ )
299
+
300
+ exit(0 if success else 1)
301
+
241
302
  (
242
303
  benchmark_defs_result,
243
304
  benchmark_definitions,
@@ -13,6 +13,7 @@ from redisbench_admin.utils.remote import (
13
13
  )
14
14
  from redisbench_admin.utils.ssh import SSHSession
15
15
  from redisbench_admin.utils.utils import redis_server_config_module_part
16
+ import tempfile
16
17
 
17
18
 
18
19
  def ensure_redis_server_available(server_public_ip, username, private_key, port=22):
@@ -148,6 +149,123 @@ def ensure_memtier_benchmark_available(
148
149
  logging.error("Failed to check memtier_benchmark availability")
149
150
 
150
151
 
152
+ def validate_remote_host_compatibility(
153
+ server_public_ip, username, private_key, custom_redis_server_path=None, port=22
154
+ ):
155
+ """
156
+ Validate remote host compatibility by checking OS version, stdlib version,
157
+ and optionally testing a custom redis-server binary.
158
+
159
+ Args:
160
+ server_public_ip: IP address of the remote server
161
+ username: SSH username
162
+ private_key: Path to SSH private key
163
+ custom_redis_server_path: Optional path to custom redis-server binary on remote host
164
+ port: SSH port (default 22)
165
+
166
+ Returns:
167
+ tuple: (success: bool, validation_info: dict)
168
+ """
169
+ logging.info("Validating remote host compatibility...")
170
+
171
+ validation_info = {}
172
+ success = True
173
+
174
+ try:
175
+ # Check OS version
176
+ os_commands = [
177
+ "uname -a", # System information
178
+ "cat /etc/os-release", # OS release info
179
+ "ldd --version", # glibc version
180
+ ]
181
+
182
+ os_results = execute_remote_commands(
183
+ server_public_ip, username, private_key, os_commands, port
184
+ )
185
+
186
+ # Process OS information
187
+ for i, (recv_exit_status, stdout, stderr) in enumerate(os_results):
188
+ if recv_exit_status == 0:
189
+ if i == 0: # uname -a
190
+ validation_info["system_info"] = "".join(stdout).strip()
191
+ logging.info(f"System info: {validation_info['system_info']}")
192
+ elif i == 1: # /etc/os-release
193
+ os_release = "".join(stdout).strip()
194
+ validation_info["os_release"] = os_release
195
+ logging.info(f"OS release info: {os_release}")
196
+ elif i == 2: # ldd --version (glibc)
197
+ glibc_info = "".join(stdout).strip()
198
+ validation_info["glibc_version"] = glibc_info
199
+ logging.info(f"glibc version: {glibc_info}")
200
+ else:
201
+ logging.warning(
202
+ f"Command {os_commands[i]} failed with exit code {recv_exit_status}"
203
+ )
204
+ if i == 2: # glibc check failed, try alternative
205
+ alt_result = execute_remote_commands(
206
+ server_public_ip,
207
+ username,
208
+ private_key,
209
+ ["getconf GNU_LIBC_VERSION"],
210
+ port,
211
+ )
212
+ if alt_result and alt_result[0][0] == 0:
213
+ glibc_alt = "".join(alt_result[0][1]).strip()
214
+ validation_info["glibc_version"] = glibc_alt
215
+ logging.info(f"glibc version (alternative): {glibc_alt}")
216
+
217
+ # Test custom redis-server binary if provided
218
+ if custom_redis_server_path:
219
+ logging.info(
220
+ f"Testing custom redis-server binary: {custom_redis_server_path}"
221
+ )
222
+
223
+ # Check if the binary exists and is executable
224
+ check_commands = [
225
+ f"test -f {custom_redis_server_path}",
226
+ f"test -x {custom_redis_server_path}",
227
+ f"{custom_redis_server_path} --version",
228
+ ]
229
+
230
+ check_results = execute_remote_commands(
231
+ server_public_ip, username, private_key, check_commands, port
232
+ )
233
+
234
+ for i, (recv_exit_status, stdout, stderr) in enumerate(check_results):
235
+ if recv_exit_status != 0:
236
+ if i == 0:
237
+ logging.error(
238
+ f"Custom redis-server binary not found: {custom_redis_server_path}"
239
+ )
240
+ success = False
241
+ elif i == 1:
242
+ logging.error(
243
+ f"Custom redis-server binary not executable: {custom_redis_server_path}"
244
+ )
245
+ success = False
246
+ elif i == 2:
247
+ logging.error(
248
+ f"Custom redis-server binary --version failed: {stderr}"
249
+ )
250
+ success = False
251
+ break
252
+ elif i == 2: # --version succeeded
253
+ version_output = "".join(stdout).strip()
254
+ validation_info["custom_redis_version"] = version_output
255
+ logging.info(f"Custom redis-server version: {version_output}")
256
+
257
+ except Exception as e:
258
+ logging.error(f"Remote host validation failed with exception: {e}")
259
+ success = False
260
+
261
+ if success:
262
+ logging.info("✅ Remote host validation passed")
263
+ else:
264
+ logging.error("❌ Remote host validation failed")
265
+
266
+ return success, validation_info
267
+
268
+
151
269
  def spin_up_standalone_remote_redis(
152
270
  temporary_dir,
153
271
  server_public_ip,
@@ -290,10 +408,24 @@ def generate_remote_standalone_redis_cmd(
290
408
  modules_configuration_parameters_map,
291
409
  enable_redis_7_config_directives=True,
292
410
  enable_debug_command="yes",
411
+ custom_redis_server_path=None,
412
+ custom_redis_conf_path=None,
293
413
  ):
294
- initial_redis_cmd = "redis-server --save '' --logfile {} --dir {} --daemonize yes --protected-mode no ".format(
295
- logfile, temporary_dir
414
+ # Use custom redis-server binary if provided, otherwise use default
415
+ redis_server_binary = (
416
+ custom_redis_server_path if custom_redis_server_path else "redis-server"
296
417
  )
418
+
419
+ # If custom config file is provided, use it; otherwise use command line parameters
420
+ if custom_redis_conf_path:
421
+ initial_redis_cmd = "{} {} --daemonize yes".format(
422
+ redis_server_binary, custom_redis_conf_path
423
+ )
424
+ logging.info(f"Using custom redis.conf: {custom_redis_conf_path}")
425
+ else:
426
+ initial_redis_cmd = "{} --save '' --logfile {} --dir {} --daemonize yes --protected-mode no ".format(
427
+ redis_server_binary, logfile, temporary_dir
428
+ )
297
429
  if enable_redis_7_config_directives:
298
430
  extra_str = " --enable-debug-command {} ".format(enable_debug_command)
299
431
  initial_redis_cmd = initial_redis_cmd + extra_str
@@ -323,3 +455,373 @@ def generate_remote_standalone_redis_cmd(
323
455
  if remote_module_files is not None:
324
456
  initial_redis_cmd += " " + " ".join(command)
325
457
  return full_logfile, initial_redis_cmd
458
+
459
+
460
+ def execute_install_steps(benchmark_config, server_public_ip, username, private_key, db_ssh_port):
461
+ """
462
+ Execute install_steps from dbconfig and clientconfig sections.
463
+
464
+ Args:
465
+ benchmark_config: The benchmark configuration dictionary
466
+ server_public_ip: IP address of the remote server
467
+ username: SSH username
468
+ private_key: Path to SSH private key
469
+ db_ssh_port: SSH port
470
+ """
471
+ install_commands = []
472
+
473
+ # Extract install_steps from dbconfig
474
+ if "dbconfig" in benchmark_config:
475
+ dbconfig = benchmark_config["dbconfig"]
476
+ if isinstance(dbconfig, list):
477
+ for config_item in dbconfig:
478
+ if "install_steps" in config_item:
479
+ steps = config_item["install_steps"]
480
+ if isinstance(steps, list):
481
+ install_commands.extend(steps)
482
+ logging.info(f"📦 Found {len(steps)} install steps in dbconfig")
483
+ elif isinstance(dbconfig, dict):
484
+ if "install_steps" in dbconfig:
485
+ steps = dbconfig["install_steps"]
486
+ if isinstance(steps, list):
487
+ install_commands.extend(steps)
488
+ logging.info(f"📦 Found {len(steps)} install steps in dbconfig")
489
+
490
+ # Extract install_steps from clientconfig
491
+ if "clientconfig" in benchmark_config:
492
+ clientconfig = benchmark_config["clientconfig"]
493
+ if isinstance(clientconfig, list):
494
+ for config_item in clientconfig:
495
+ if "install_steps" in config_item:
496
+ steps = config_item["install_steps"]
497
+ if isinstance(steps, list):
498
+ install_commands.extend(steps)
499
+ logging.info(f"📦 Found {len(steps)} install steps in clientconfig")
500
+ elif isinstance(clientconfig, dict):
501
+ if "install_steps" in clientconfig:
502
+ steps = clientconfig["install_steps"]
503
+ if isinstance(steps, list):
504
+ install_commands.extend(steps)
505
+ logging.info(f"📦 Found {len(steps)} install steps in clientconfig")
506
+
507
+ # Execute all install commands
508
+ if install_commands:
509
+ logging.info(f"🔧 Executing {len(install_commands)} installation commands...")
510
+ for i, command in enumerate(install_commands, 1):
511
+ logging.info(f"📋 Step {i}/{len(install_commands)}: {command}")
512
+
513
+ install_result = execute_remote_commands(
514
+ server_public_ip, username, private_key, install_commands, db_ssh_port
515
+ )
516
+
517
+ # Check results
518
+ for i, (recv_exit_status, stdout, stderr) in enumerate(install_result):
519
+ if recv_exit_status != 0:
520
+ logging.warning(
521
+ f"⚠️ Install step {i+1} returned exit code {recv_exit_status}"
522
+ )
523
+ logging.warning(f"Command: {install_commands[i]}")
524
+ if stderr:
525
+ logging.warning(f"STDERR: {''.join(stderr).strip()}")
526
+ if stdout:
527
+ logging.warning(f"STDOUT: {''.join(stdout).strip()}")
528
+ else:
529
+ logging.info(f"✅ Install step {i+1} completed successfully")
530
+
531
+ logging.info("🎯 All installation steps completed")
532
+ else:
533
+ logging.info("📦 No install_steps found in configuration")
534
+
535
+
536
+ def spin_test_standalone_redis(
537
+ server_public_ip,
538
+ username,
539
+ private_key,
540
+ db_ssh_port=22,
541
+ redis_port=6379,
542
+ local_module_files=None,
543
+ redis_configuration_parameters=None,
544
+ modules_configuration_parameters_map=None,
545
+ custom_redis_conf_path=None,
546
+ custom_redis_server_path=None,
547
+ benchmark_config=None,
548
+ ):
549
+ """
550
+ Setup standalone Redis server, run INFO SERVER, print output as markdown and exit.
551
+
552
+ Args:
553
+ server_public_ip: IP address of the remote server
554
+ username: SSH username
555
+ private_key: Path to SSH private key
556
+ db_ssh_port: SSH port (default 22)
557
+ redis_port: Redis port (default 6379)
558
+ local_module_files: List of local module files to copy
559
+ redis_configuration_parameters: Dict of Redis configuration parameters
560
+ modules_configuration_parameters_map: Dict of module configuration parameters
561
+ custom_redis_conf_path: Path to custom redis.conf file
562
+ custom_redis_server_path: Path to custom redis-server binary
563
+ """
564
+ logging.info("🚀 Starting spin-test mode...")
565
+
566
+ try:
567
+ # Create temporary directory on remote host
568
+ temporary_dir = "/tmp/redisbench-spin-test"
569
+ create_dir_commands = [f"mkdir -p {temporary_dir}"]
570
+ execute_remote_commands(
571
+ server_public_ip, username, private_key, create_dir_commands, db_ssh_port
572
+ )
573
+
574
+ # Execute install_steps from dbconfig and clientconfig if present
575
+ if benchmark_config is not None:
576
+ execute_install_steps(
577
+ benchmark_config, server_public_ip, username, private_key, db_ssh_port
578
+ )
579
+
580
+ # Ensure Redis server is available (only if not using custom binary)
581
+ if custom_redis_server_path is None:
582
+ ensure_redis_server_available(
583
+ server_public_ip, username, private_key, db_ssh_port
584
+ )
585
+ else:
586
+ logging.info(
587
+ "🔧 Using custom Redis binary - skipping system Redis installation"
588
+ )
589
+
590
+ # Copy custom Redis files if provided
591
+ remote_redis_conf_path = None
592
+ remote_redis_server_path = None
593
+
594
+ if custom_redis_conf_path:
595
+ if not os.path.exists(custom_redis_conf_path):
596
+ logging.error(
597
+ f"❌ Custom redis.conf file not found: {custom_redis_conf_path}"
598
+ )
599
+ return False
600
+
601
+ remote_redis_conf_path = f"{temporary_dir}/redis.conf"
602
+ logging.info(f"📁 Copying custom redis.conf to remote host...")
603
+
604
+ copy_result = copy_file_to_remote_setup(
605
+ server_public_ip,
606
+ username,
607
+ private_key,
608
+ custom_redis_conf_path,
609
+ remote_redis_conf_path,
610
+ None,
611
+ db_ssh_port,
612
+ False, # don't continue on error
613
+ )
614
+
615
+ if not copy_result:
616
+ logging.error("❌ Failed to copy redis.conf to remote host")
617
+ return False
618
+
619
+ if custom_redis_server_path:
620
+ if not os.path.exists(custom_redis_server_path):
621
+ logging.error(
622
+ f"❌ Custom redis-server binary not found: {custom_redis_server_path}"
623
+ )
624
+ return False
625
+
626
+ remote_redis_server_path = f"{temporary_dir}/redis-server"
627
+ logging.info(f"📁 Copying custom redis-server binary to remote host...")
628
+
629
+ copy_result = copy_file_to_remote_setup(
630
+ server_public_ip,
631
+ username,
632
+ private_key,
633
+ custom_redis_server_path,
634
+ remote_redis_server_path,
635
+ None,
636
+ db_ssh_port,
637
+ False, # don't continue on error
638
+ )
639
+
640
+ if not copy_result:
641
+ logging.error("❌ Failed to copy redis-server binary to remote host")
642
+ return False
643
+
644
+ # Make the binary executable
645
+ chmod_commands = [f"chmod +x {remote_redis_server_path}"]
646
+ chmod_results = execute_remote_commands(
647
+ server_public_ip, username, private_key, chmod_commands, db_ssh_port
648
+ )
649
+
650
+ recv_exit_status, stdout, stderr = chmod_results[0]
651
+ if recv_exit_status != 0:
652
+ logging.warning(
653
+ f"⚠️ Failed to make redis-server binary executable: {stderr}"
654
+ )
655
+ else:
656
+ logging.info("✅ Redis-server binary made executable")
657
+
658
+ # Copy modules if provided
659
+ remote_module_files = None
660
+ if local_module_files:
661
+ remote_module_file_dir = f"{temporary_dir}/modules"
662
+ create_module_dir_commands = [f"mkdir -p {remote_module_file_dir}"]
663
+ execute_remote_commands(
664
+ server_public_ip,
665
+ username,
666
+ private_key,
667
+ create_module_dir_commands,
668
+ db_ssh_port,
669
+ )
670
+
671
+ remote_module_files = remote_module_files_cp(
672
+ local_module_files,
673
+ db_ssh_port,
674
+ private_key,
675
+ remote_module_file_dir,
676
+ server_public_ip,
677
+ username,
678
+ continue_on_module_check_error=True,
679
+ )
680
+
681
+ # Generate Redis startup command
682
+ logfile = "redis-spin-test.log"
683
+ _, redis_cmd = generate_remote_standalone_redis_cmd(
684
+ logfile,
685
+ redis_configuration_parameters,
686
+ remote_module_files,
687
+ temporary_dir,
688
+ modules_configuration_parameters_map or {},
689
+ enable_redis_7_config_directives=True,
690
+ enable_debug_command="yes",
691
+ custom_redis_server_path=remote_redis_server_path,
692
+ custom_redis_conf_path=remote_redis_conf_path,
693
+ )
694
+
695
+ # Override port if specified
696
+ if redis_port != 6379:
697
+ redis_cmd += f" --port {redis_port}"
698
+
699
+ logging.info(f"🔧 Starting Redis with command: {redis_cmd}")
700
+
701
+ # Start Redis server
702
+ start_commands = [redis_cmd]
703
+ start_result = execute_remote_commands(
704
+ server_public_ip, username, private_key, start_commands, db_ssh_port
705
+ )
706
+
707
+ # Check if Redis started successfully
708
+ recv_exit_status, stdout, stderr = start_result[0]
709
+ if recv_exit_status != 0:
710
+ logging.error(
711
+ f"❌ Failed to start Redis server. Exit code: {recv_exit_status}"
712
+ )
713
+ logging.error(f"STDOUT: {stdout}")
714
+ logging.error(f"STDERR: {stderr}")
715
+ return False
716
+
717
+ # Wait a moment for Redis to fully start
718
+ import time
719
+
720
+ time.sleep(2)
721
+
722
+ # Collect system information
723
+ logging.info("📊 Collecting system information...")
724
+ system_commands = [
725
+ "uname -a", # System information
726
+ "cat /etc/os-release", # OS release info
727
+ "ldd --version 2>/dev/null || getconf GNU_LIBC_VERSION 2>/dev/null || echo 'glibc version not available'", # glibc version
728
+ "cat /proc/version", # Kernel version
729
+ "cat /proc/cpuinfo | grep 'model name' | head -1", # CPU info
730
+ "free -h", # Memory info
731
+ "df -h /", # Disk space
732
+ ]
733
+
734
+ system_results = execute_remote_commands(
735
+ server_public_ip, username, private_key, system_commands, db_ssh_port
736
+ )
737
+
738
+ # Run INFO SERVER command
739
+ info_commands = [f"redis-cli -p {redis_port} INFO SERVER"]
740
+ info_result = execute_remote_commands(
741
+ server_public_ip, username, private_key, info_commands, db_ssh_port
742
+ )
743
+
744
+ recv_exit_status, stdout, stderr = info_result[0]
745
+ if recv_exit_status != 0:
746
+ logging.error(
747
+ f"❌ Failed to run INFO SERVER. Exit code: {recv_exit_status}"
748
+ )
749
+ logging.error(f"STDOUT: {stdout}")
750
+ logging.error(f"STDERR: {stderr}")
751
+ return False
752
+
753
+ # Format output as markdown
754
+ info_output = "".join(stdout).strip()
755
+
756
+ print("\n" + "=" * 80)
757
+ print("🎯 REDIS SPIN-TEST RESULTS")
758
+ print("=" * 80)
759
+ print()
760
+
761
+ # Display system information
762
+ print("## 🖥️ System Information")
763
+ print()
764
+
765
+ system_labels = [
766
+ "System Info",
767
+ "OS Release",
768
+ "glibc Version",
769
+ "Kernel Version",
770
+ "CPU Model",
771
+ "Memory",
772
+ "Disk Space",
773
+ ]
774
+
775
+ for label, (recv_exit_status, stdout, stderr) in zip(
776
+ system_labels, system_results
777
+ ):
778
+ if recv_exit_status == 0 and stdout:
779
+ output = "".join(stdout).strip()
780
+ if output:
781
+ print(f"**{label}:**")
782
+ print("```")
783
+ print(output)
784
+ print("```")
785
+ print()
786
+ else:
787
+ print(f"**{label}:** ⚠️ Not available")
788
+ print()
789
+
790
+ # Display Redis information
791
+ print("## 🔴 Redis Server Information")
792
+ print()
793
+ print("```")
794
+ print(info_output)
795
+ print("```")
796
+ print()
797
+ print("✅ Spin-test completed successfully!")
798
+ print("=" * 80)
799
+
800
+ # Cleanup: Stop Redis server
801
+ cleanup_commands = [
802
+ f"redis-cli -p {redis_port} shutdown nosave",
803
+ f"rm -rf {temporary_dir}",
804
+ ]
805
+ execute_remote_commands(
806
+ server_public_ip, username, private_key, cleanup_commands, db_ssh_port
807
+ )
808
+
809
+ logging.info("🧹 Cleanup completed")
810
+ return True
811
+
812
+ except Exception as e:
813
+ logging.error(f"❌ Spin-test failed with error: {e}")
814
+
815
+ # Attempt cleanup on error
816
+ try:
817
+ cleanup_commands = [
818
+ f"redis-cli -p {redis_port} shutdown nosave",
819
+ f"rm -rf {temporary_dir}",
820
+ ]
821
+ execute_remote_commands(
822
+ server_public_ip, username, private_key, cleanup_commands, db_ssh_port
823
+ )
824
+ except:
825
+ pass # Ignore cleanup errors
826
+
827
+ return False
@@ -629,6 +629,15 @@ def push_data_to_redistimeseries(rts, time_series_dict: dict, expire_msecs=0):
629
629
  )
630
630
  for timeseries_name, time_series in time_series_dict.items():
631
631
  try:
632
+ arch = "x86_64"
633
+ if "arch" in time_series["labels"]:
634
+ arch = time_series["labels"]["arch"]
635
+ if arch == "aarch64" and "aarch64" not in timeseries_name:
636
+ original_timeseries_name = timeseries_name
637
+ timeseries_name = f"{timeseries_name}/arch/{arch}"
638
+ logging.warning(
639
+ f"overriding key named {original_timeseries_name} given it does not contain arch and it's not x86_64. new key={timeseries_name}"
640
+ )
632
641
  exporter_create_ts(rts, time_series, timeseries_name)
633
642
  for timestamp, value in time_series["data"].items():
634
643
  try:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: redisbench-admin
3
- Version: 0.11.40
3
+ Version: 0.11.42
4
4
  Summary: Redis benchmark run helper. A wrapper around Redis and Redis Modules benchmark tools ( ftsb_redisearch, memtier_benchmark, redis-benchmark, aibench, etc... ).
5
5
  Author: filipecosta90
6
6
  Author-email: filipecosta.90@gmail.com
@@ -3,8 +3,8 @@ redisbench_admin/cli.py,sha256=LAS5qnqScXKhxHYfXWB0mvAYaUYrSurIwadhexEa9g4,7740
3
3
  redisbench_admin/commands/__init__.py,sha256=mzVrEtqefFdopyzR-W6xx3How95dyZfToGKm1-_YzeY,95
4
4
  redisbench_admin/commands/commands.json.py,sha256=mzVrEtqefFdopyzR-W6xx3How95dyZfToGKm1-_YzeY,95
5
5
  redisbench_admin/compare/__init__.py,sha256=DtBXRp0Q01XgCFmY-1OIePMyyYihVNAjZ1Y8zwqSDN0,101
6
- redisbench_admin/compare/args.py,sha256=qyOgo0CBE3NdDRTa5dqgNV_0eZJ0jkGBliGTasHuWls,6256
7
- redisbench_admin/compare/compare.py,sha256=ZE6j5T8SIiyW6mpUCkVWRvo5xT4Tkf-SnOnYSSQ9zt4,103382
6
+ redisbench_admin/compare/args.py,sha256=rOP8td_GYPYsZiYN4olyYmUsku-oizggEZNRTB_fVro,6336
7
+ redisbench_admin/compare/compare.py,sha256=NvC7RbQUJUKlPdJQj9TjUmk2k8UtiA9wnZWNDV7IM_Q,103315
8
8
  redisbench_admin/deploy/__init__.py,sha256=DtBXRp0Q01XgCFmY-1OIePMyyYihVNAjZ1Y8zwqSDN0,101
9
9
  redisbench_admin/deploy/args.py,sha256=neLUcQqI__HkJItkQg2C293hl5g3yHG40t171r7-E5Y,1732
10
10
  redisbench_admin/deploy/deploy.py,sha256=MtfJbsL97DLrbBYut6zRCzyEMebX4xWoZE-m4-JDRB8,3885
@@ -211,7 +211,7 @@ redisbench_admin/run_local/local_db.py,sha256=9vINqKOs-wDMFEuEHT0I8KO9YnEo_h4NWN
211
211
  redisbench_admin/run_local/local_helpers.py,sha256=JyqLW2-Sbm35BXjxxfOB1yK7ADdLfcVrq08NLNdIwac,7026
212
212
  redisbench_admin/run_local/run_local.py,sha256=QHnGfVAaVuct7t0WrWyQpbirC3MWX7fQF5-kXU_pJBs,34834
213
213
  redisbench_admin/run_remote/__init__.py,sha256=DtBXRp0Q01XgCFmY-1OIePMyyYihVNAjZ1Y8zwqSDN0,101
214
- redisbench_admin/run_remote/args.py,sha256=VnZ20gqpk-NMzNxaaUHgedgl3B6fZm3Fewj6cPZ1iCg,4231
214
+ redisbench_admin/run_remote/args.py,sha256=gJux_1udR6d5BUMMnIewl62hS0b2WnQ_7WQF4hElX7c,5051
215
215
  redisbench_admin/run_remote/consts.py,sha256=bCMkwyeBD-EmOpoHKni7LjWy5WuaxGJhGhqpi4AL0RQ,386
216
216
  redisbench_admin/run_remote/log.py,sha256=cD7zfXt0VEmy0b7452HvcAxX_9kVj6Vm213yNdUHP20,95
217
217
  redisbench_admin/run_remote/notifications.py,sha256=-W9fLaftEFNfplBl2clHk37jbYxliDbHftQ62khN31k,2157
@@ -220,23 +220,23 @@ redisbench_admin/run_remote/remote_db.py,sha256=EEDeiOZk-godr5EINscEkOJLGWUN3gFf
220
220
  redisbench_admin/run_remote/remote_env.py,sha256=Ux_0QT1unNRlKl3cakzjG5Px1uuxOOfBoF_pnalx_T8,4936
221
221
  redisbench_admin/run_remote/remote_failures.py,sha256=IOo6DyxarcwwMPCeN4gWB2JrhuC9iBLwq0nCROqr5ak,1567
222
222
  redisbench_admin/run_remote/remote_helpers.py,sha256=skWeGyDJBmyx_UwUekT3N3_nOJvF2-Hvu-E7vKlO9gg,10598
223
- redisbench_admin/run_remote/run_remote.py,sha256=_K7Bx9CWarf6UOUjt9CDKGJBqu-qgLjGYzPs80jOwnU,73789
224
- redisbench_admin/run_remote/standalone.py,sha256=BT_3ojr6w84FZGwTkFxDLnSGMth24FyaoXedKLhf5h4,12629
223
+ redisbench_admin/run_remote/run_remote.py,sha256=7B-x-AI1pVon8ccfRio8q6EXTXaqPPMj_PxytpiICUs,76045
224
+ redisbench_admin/run_remote/standalone.py,sha256=Or2GaSccxEyIl0z833RWi-fylSQ71Z6E1R2vbN0rHMM,31593
225
225
  redisbench_admin/run_remote/terraform.py,sha256=vV3eWXNwj7vsnFNqUgCir5ueZS4VYopEyzWiTtoSq0Q,4018
226
226
  redisbench_admin/utils/__init__.py,sha256=DtBXRp0Q01XgCFmY-1OIePMyyYihVNAjZ1Y8zwqSDN0,101
227
227
  redisbench_admin/utils/benchmark_config.py,sha256=bC2C6rnj89wkkSlOXyyfe0N15unn_M1t1zfskfVkb98,21387
228
228
  redisbench_admin/utils/local.py,sha256=zUvyVI9LZMT3qyxs1pO3mXL6Bt_1z9EZUGppaRcWNRA,3890
229
229
  redisbench_admin/utils/redisearch.py,sha256=lchUEzpt0zB1rHwlDlw9LLifAnxFWcLP-PePw7TjL-0,1602
230
230
  redisbench_admin/utils/redisgraph_benchmark_go.py,sha256=os7EJt6kBxsFJLKkSoANbjMT7-cEq4-Ns-49alk2Tf8,2048
231
- redisbench_admin/utils/remote.py,sha256=qlO49qdJh96rOEXnFMgFcpiwYjmrG0K060bEc3nyHD0,41643
231
+ redisbench_admin/utils/remote.py,sha256=RAQ2VxfmlK7swN7ujCuwSI2soGSycjnxbQw_IrLxIFE,42205
232
232
  redisbench_admin/utils/results.py,sha256=uKk3uNJ--bSXlUj_HGQ2OaV6MVqmXJVM8xTzFV6EOw4,3267
233
233
  redisbench_admin/utils/ssh.py,sha256=QW4AwlocMHJt05QMdN_4f8WeDmxiEwR80ny8VBThq6k,6533
234
234
  redisbench_admin/utils/utils.py,sha256=XVSvo1_DdcYwk2jOxL3VPVPbnDnhGYt8ieYfANo6rTo,15085
235
235
  redisbench_admin/watchdog/__init__.py,sha256=cD7zfXt0VEmy0b7452HvcAxX_9kVj6Vm213yNdUHP20,95
236
236
  redisbench_admin/watchdog/args.py,sha256=nKsG1G6ATOZlAMHMtT9u3kXxduKCbejSZ5x8oB_ynZ8,1312
237
237
  redisbench_admin/watchdog/watchdog.py,sha256=0wWYge3x_OMxWrzazNhJif2NK4tKsI963HVZqjczRag,6189
238
- redisbench_admin-0.11.40.dist-info/LICENSE,sha256=AAMtfs82zOOvmG68vILivm6lxi2rcOlGObmA8jzxQvw,10768
239
- redisbench_admin-0.11.40.dist-info/METADATA,sha256=olR0Y3plqHRTgl01WGkXOkyV5Iz_veIrpEG6vYaQksg,5596
240
- redisbench_admin-0.11.40.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
241
- redisbench_admin-0.11.40.dist-info/entry_points.txt,sha256=UUawXk_AS-PlieKJ1QxPQXGsRLb6OW_F0MtmA1W0KE8,113
242
- redisbench_admin-0.11.40.dist-info/RECORD,,
238
+ redisbench_admin-0.11.42.dist-info/LICENSE,sha256=AAMtfs82zOOvmG68vILivm6lxi2rcOlGObmA8jzxQvw,10768
239
+ redisbench_admin-0.11.42.dist-info/METADATA,sha256=s_waYOA4L1z-YQOS-p7DPaW8QWK2zzr2rsMSEAIVD7Y,5596
240
+ redisbench_admin-0.11.42.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
241
+ redisbench_admin-0.11.42.dist-info/entry_points.txt,sha256=UUawXk_AS-PlieKJ1QxPQXGsRLb6OW_F0MtmA1W0KE8,113
242
+ redisbench_admin-0.11.42.dist-info/RECORD,,