stress-test-kit 0.1.0__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.
@@ -0,0 +1,5 @@
1
+ """
2
+ Stress Test Kit - 本地压测工具
3
+ """
4
+
5
+ __version__ = "0.1.0"
@@ -0,0 +1,5 @@
1
+ """CLI 入口模块"""
2
+ from stress_test_kit.cli import main
3
+
4
+ if __name__ == "__main__":
5
+ main()
stress_test_kit/cli.py ADDED
@@ -0,0 +1,115 @@
1
+ """CLI 入口(类似 locust 命令)"""
2
+ import os
3
+ import click
4
+ import uvicorn
5
+ import webbrowser
6
+ import threading
7
+
8
+
9
+ @click.command()
10
+ @click.option('--port', default=8765, help='Web服务端口(前后端同一端口,不推荐与 --backend-port/--frontend-port 同时使用)')
11
+ @click.option('--backend-port', default=None, type=int, help='后端 API 服务端口(优先级高于 --port)')
12
+ @click.option('--frontend-port', default=None, type=int, help='前端静态服务端口(优先级高于 --port,需与 --backend-port 同时指定)')
13
+ @click.option('--data-dir', default=None, help='数据目录(存放SQLite和文件)')
14
+ @click.option('--no-browser', is_flag=True, help='不自动打开浏览器')
15
+ def main(port: int, backend_port: int, frontend_port: int, data_dir: str, no_browser: bool):
16
+ """启动 Stress Test Kit 本地压测服务"""
17
+ import sys
18
+ from stress_test_kit.process_manager import _is_port_free
19
+
20
+ # 端口配置逻辑
21
+ if backend_port is not None and frontend_port is not None:
22
+ # 前后端分离模式
23
+ actual_backend_port = backend_port
24
+ actual_frontend_port = frontend_port
25
+ frontend_separate = True
26
+ elif backend_port is not None or frontend_port is not None:
27
+ # 只指定了一个,报错
28
+ click.echo("❌ --backend-port 和 --frontend-port 必须同时指定", err=True)
29
+ sys.exit(1)
30
+ else:
31
+ # 使用 --port(前后端同一端口)
32
+ actual_backend_port = port
33
+ actual_frontend_port = None
34
+ frontend_separate = False
35
+
36
+ # 端口占用检查
37
+ if not _is_port_free(actual_backend_port):
38
+ click.echo(f"❌ 后端端口 {actual_backend_port} 已被占用,请先释放该端口或指定其他端口", err=True)
39
+ sys.exit(1)
40
+
41
+ if frontend_separate and not _is_port_free(actual_frontend_port):
42
+ click.echo(f"❌ 前端端口 {actual_frontend_port} 已被占用,请先释放该端口或指定其他端口", err=True)
43
+ sys.exit(1)
44
+
45
+ # 数据目录默认值
46
+ if data_dir is None:
47
+ data_dir = os.path.join(os.path.expanduser("~"), ".stress-test-kit")
48
+ else:
49
+ data_dir = os.path.expanduser(data_dir)
50
+
51
+ # 初始化数据库
52
+ from stress_test_kit.models import init_db
53
+ from stress_test_kit.server import set_data_dir, set_mount_frontend
54
+ from stress_test_kit.sampler import recover_active_samplers, start_periodic_patrol
55
+
56
+ init_db(data_dir)
57
+ set_data_dir(data_dir)
58
+
59
+ # 前后端分离模式下,禁用 FastAPI 挂载静态文件
60
+ if frontend_separate:
61
+ set_mount_frontend(False)
62
+
63
+ # 恢复活跃的采样线程
64
+ recover_active_samplers(data_dir)
65
+
66
+ # 启动定期巡检(每 60 秒检查所有 running 状态的任务)
67
+ start_periodic_patrol(data_dir)
68
+
69
+ click.echo("=" * 60)
70
+ click.echo("🚀 Stress Test Kit 启动中...")
71
+ click.echo("=" * 60)
72
+ click.echo(f"📂 数据目录: {data_dir}")
73
+
74
+ if frontend_separate:
75
+ click.echo(f"🔧 后端 API: http://localhost:{actual_backend_port}")
76
+ click.echo(f"🌐 前端页面: http://localhost:{actual_frontend_port}")
77
+ access_url = f"http://localhost:{actual_frontend_port}"
78
+
79
+ # 启动前端静态文件服务(独立线程)
80
+ def start_frontend_server():
81
+ import http.server
82
+ import socketserver
83
+ import functools
84
+ frontend_dir = os.path.join(os.path.dirname(__file__), "frontend")
85
+ if os.path.exists(frontend_dir):
86
+ os.chdir(frontend_dir)
87
+ handler = functools.partial(http.server.SimpleHTTPRequestHandler, directory=frontend_dir)
88
+ with socketserver.TCPServer(("0.0.0.0", actual_frontend_port), handler) as httpd:
89
+ click.echo(f"✅ 前端服务已启动在端口 {actual_frontend_port}")
90
+ httpd.serve_forever()
91
+ else:
92
+ click.echo(f"⚠️ 前端目录不存在: {frontend_dir},跳过前端服务启动")
93
+
94
+ threading.Thread(target=start_frontend_server, daemon=True).start()
95
+ else:
96
+ click.echo(f"🌐 访问地址: http://localhost:{actual_backend_port}")
97
+ access_url = f"http://localhost:{actual_backend_port}"
98
+
99
+ click.echo("=" * 60)
100
+
101
+ # 自动打开浏览器
102
+ if not no_browser:
103
+ threading.Timer(1.5, lambda: webbrowser.open(access_url)).start()
104
+
105
+ # 启动 FastAPI 服务
106
+ uvicorn.run(
107
+ "stress_test_kit.server:app",
108
+ host="0.0.0.0",
109
+ port=actual_backend_port,
110
+ log_level="info"
111
+ )
112
+
113
+
114
+ if __name__ == "__main__":
115
+ main()