|
| 1 | +import time |
| 2 | +import datetime |
| 3 | +import numpy as np |
| 4 | +import requests |
| 5 | + |
| 6 | +import oracledb |
| 7 | +import psycopg2 |
| 8 | +import pymysql |
| 9 | + |
| 10 | +# Optionally, handle MS SQL if needed |
| 11 | +try: |
| 12 | + import pyodbc |
| 13 | + mssql_ok = True |
| 14 | +except ImportError: |
| 15 | + mssql_ok = False |
| 16 | + |
| 17 | +def run_latency_test( |
| 18 | + dbtype, |
| 19 | + host="", |
| 20 | + port="", |
| 21 | + username="", |
| 22 | + password="", |
| 23 | + database="", |
| 24 | + url="", |
| 25 | + interval=1.0, |
| 26 | + period=10 |
| 27 | +): |
| 28 | + query_times = [] |
| 29 | + result_info = {"success": False, "error": None, "latency_stats": {}, "details": []} |
| 30 | + try: |
| 31 | + end_time = time.perf_counter() + period |
| 32 | + while time.perf_counter() < end_time: |
| 33 | + t0 = time.perf_counter() |
| 34 | + ts = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") |
| 35 | + try: |
| 36 | + if dbtype == "oracle": |
| 37 | + conn = oracledb.connect(user=username, password=password, dsn=host) |
| 38 | + cursor = conn.cursor() |
| 39 | + cursor.execute("select 1 from dual") |
| 40 | + cursor.fetchall() |
| 41 | + cursor.close() |
| 42 | + conn.close() |
| 43 | + elif dbtype == "postgresql": |
| 44 | + conn = psycopg2.connect(host=host, port=port, dbname=database, user=username, password=password) |
| 45 | + cursor = conn.cursor() |
| 46 | + cursor.execute("SELECT 1") |
| 47 | + cursor.fetchall() |
| 48 | + cursor.close() |
| 49 | + conn.close() |
| 50 | + elif dbtype == "mysql": |
| 51 | + conn = pymysql.connect(host=host, port=int(port), user=username, password=password, db=database) |
| 52 | + cursor = conn.cursor() |
| 53 | + cursor.execute("SELECT 1") |
| 54 | + cursor.fetchall() |
| 55 | + cursor.close() |
| 56 | + conn.close() |
| 57 | + elif dbtype == "sqlserver" and mssql_ok: |
| 58 | + conn_str = f"DRIVER={{ODBC Driver 17 for SQL Server}};SERVER={host},{port};DATABASE={database};UID={username};PWD={password}" |
| 59 | + conn = pyodbc.connect(conn_str) |
| 60 | + cursor = conn.cursor() |
| 61 | + cursor.execute("SELECT 1") |
| 62 | + cursor.fetchall() |
| 63 | + cursor.close() |
| 64 | + conn.close() |
| 65 | + elif dbtype == "url": |
| 66 | + response = requests.get(url) |
| 67 | + else: |
| 68 | + raise Exception(f"Unsupported dbtype: {dbtype}") |
| 69 | + success = True |
| 70 | + error = None |
| 71 | + except Exception as ex: |
| 72 | + success = False |
| 73 | + error = str(ex) |
| 74 | + t1 = time.perf_counter() |
| 75 | + query_time = (t1 - t0) * 1000 |
| 76 | + query_times.append(query_time) |
| 77 | + result_info["details"].append({ |
| 78 | + "timestamp": ts, |
| 79 | + "latency_ms": query_time, |
| 80 | + "success": success, |
| 81 | + "error": error |
| 82 | + }) |
| 83 | + time.sleep(interval) |
| 84 | + # Compute p99, p90, avg, stddev, mean on all query_times |
| 85 | + arr = np.array(query_times) |
| 86 | + result_info["latency_stats"] = { |
| 87 | + "p99": float(np.percentile(arr, 99)) if len(arr) else None, |
| 88 | + "p90": float(np.percentile(arr, 90)) if len(arr) else None, |
| 89 | + "avg": float(np.mean(arr)) if len(arr) else None, |
| 90 | + "stddev": float(np.std(arr)) if len(arr) else None, |
| 91 | + "mean": float(np.mean(arr)) if len(arr) else None, |
| 92 | + "runs": len(arr), |
| 93 | + } |
| 94 | + result_info["success"] = all(x["success"] for x in result_info["details"]) |
| 95 | + result_info["error"] = next((x["error"] for x in result_info["details"] if x["error"]), None) |
| 96 | + except Exception as ex: |
| 97 | + result_info["success"] = False |
| 98 | + result_info["error"] = str(ex) |
| 99 | + return result_info |
0 commit comments