Skip to content

Commit d58e63e

Browse files
committed
docs: rebuild docs and READMEs in WebRunner-style chapter layout
Reorganise the Sphinx manual into a 10-chapter structure that mirrors the WebRunner reference layout (Getting Started, Core API, Actions, User Templates, Reporting, Orchestration, Recording & Data, Tooling, Integrations, Reference) and add per-feature pages for everything shipped on the recent feature wave: - New English + Traditional Chinese pages for architecture, start_test / prepare_env, locust environment, action executor, parameter resolver, scenario modes, assertions, HTTP / WebSocket / gRPC / MQTT / socket users, metrics exporters, test record store, distributed master/worker, HAR import, SQLite persistence, MCP server, project scaffolding, exception hierarchy, and the API reference index. - Refresh installation, getting_started, cli, socket_server, generate_report, and gui pages so they cover the new extras, the CLI subcommand surface, the hardened control socket, all six report formats, and the live stats panel + JA/KO translations. - Drop the stale scheduler doc directories (LoadDensity has no scheduler; the page never matched real executor commands). - Upgrade conf.py to enable autodoc / autosummary / autosectionlabel / napoleon / mermaid, lazy-mock the optional runtime deps, and bring copyright forward; add sphinxcontrib-mermaid to docs/requirements. Rewrite the three READMEs (root, Traditional Chinese, Simplified Chinese) into the WebRunner-style layout: badge row, language switcher, full Table of Contents, Highlights, Installation (with extras matrix), Architecture diagram, Quick Start, Core API, Action Executor, User Templates per protocol, Parameter Resolver, Scenario Modes, Assertions & Extractors, Reports, Observability, Distributed runners, HAR record/replay, SQLite persistence, MCP server, Hardened Control Socket, GUI, CLI Usage, Test Record, Exception Handling, Logging, Supported Platforms, License.
1 parent c58fbb3 commit d58e63e

64 files changed

Lines changed: 5445 additions & 2174 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 505 additions & 241 deletions
Large diffs are not rendered by default.

README/README_zh-CN.md

Lines changed: 478 additions & 246 deletions
Large diffs are not rendered by default.

README/README_zh-TW.md

Lines changed: 483 additions & 251 deletions
Large diffs are not rendered by default.

docs/requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
sphinx-rtd-theme
1+
sphinx-rtd-theme
2+
sphinxcontrib-mermaid
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
Action Executor
2+
===============
3+
4+
Overview
5+
--------
6+
7+
The action executor maps command strings to callable functions. Action
8+
scripts are JSON lists, so the same script can be hand-authored,
9+
generated by HAR import, scheduled by an MCP tool, or sent over the
10+
control socket.
11+
12+
Every shipped command starts with the ``LD_`` prefix; safe Python
13+
built-ins (``print``, ``len``, ``range``…) are also available, but
14+
``eval``, ``exec``, ``compile``, ``__import__``, ``breakpoint``,
15+
``open``, and ``input`` are explicitly blocked.
16+
17+
Action format
18+
-------------
19+
20+
.. code-block:: python
21+
22+
["command_name"] # No parameters
23+
["command_name", {"key": "value"}] # Keyword arguments
24+
["command_name", [arg1, arg2]] # Positional arguments
25+
26+
The top-level document is either:
27+
28+
.. code-block:: json
29+
30+
{"load_density": [["LD_start_test", {...}], ...]}
31+
32+
or a bare list of actions.
33+
34+
Quick example
35+
-------------
36+
37+
.. code-block:: python
38+
39+
from je_load_density import execute_action
40+
41+
execute_action({"load_density": [
42+
["LD_register_variables", {"variables": {"base": "https://api.example.com"}}],
43+
["LD_start_test", {
44+
"user_detail_dict": {"user": "fast_http_user"},
45+
"user_count": 20,
46+
"spawn_rate": 10,
47+
"test_time": 30,
48+
"tasks": [{"method": "get", "request_url": "${var.base}/health"}],
49+
}],
50+
["LD_generate_summary_report", {"report_name": "smoke"}],
51+
]})
52+
53+
LD_* commands
54+
-------------
55+
56+
The executor exposes the following commands. Each is implemented in the
57+
matching module under ``je_load_density``.
58+
59+
**Core:**
60+
61+
.. list-table::
62+
:header-rows: 1
63+
:widths: 35 65
64+
65+
* - Command
66+
- Summary
67+
* - ``LD_start_test``
68+
- Run a Locust load test (HTTP / FastHttp / WebSocket / gRPC /
69+
MQTT / Socket).
70+
* - ``LD_execute_action``
71+
- Execute a nested action list.
72+
* - ``LD_execute_files``
73+
- Execute every action JSON file in a list.
74+
* - ``LD_add_package_to_executor``
75+
- Register a Python package's functions into the executor.
76+
* - ``LD_start_socket_server``
77+
- Start the hardened TCP control plane.
78+
79+
**Reports:**
80+
81+
.. list-table::
82+
:header-rows: 1
83+
:widths: 35 65
84+
85+
* - Command
86+
- Summary
87+
* - ``LD_generate_html`` / ``LD_generate_html_report``
88+
- HTML report generators.
89+
* - ``LD_generate_json`` / ``LD_generate_json_report``
90+
- JSON report generators.
91+
* - ``LD_generate_xml`` / ``LD_generate_xml_report``
92+
- XML report generators.
93+
* - ``LD_generate_csv_report``
94+
- One-row-per-request CSV export.
95+
* - ``LD_generate_junit_report``
96+
- JUnit XML for CI consumers.
97+
* - ``LD_generate_summary_report``
98+
- JSON summary with per-name p50/p90/p95/p99 latencies.
99+
* - ``LD_summary``
100+
- In-memory dict of the same summary.
101+
102+
**Test record persistence:**
103+
104+
.. list-table::
105+
:header-rows: 1
106+
:widths: 35 65
107+
108+
* - Command
109+
- Summary
110+
* - ``LD_persist_records``
111+
- Save the in-memory records to a SQLite database.
112+
* - ``LD_list_runs``
113+
- List recent runs in a database.
114+
* - ``LD_fetch_run_records``
115+
- Load every record for one run.
116+
* - ``LD_clear_records``
117+
- Drop the in-memory record list.
118+
119+
**Parameter resolver:**
120+
121+
.. list-table::
122+
:header-rows: 1
123+
:widths: 35 65
124+
125+
* - Command
126+
- Summary
127+
* - ``LD_register_variable`` / ``LD_register_variables``
128+
- Register one or many ``${var.x}`` values.
129+
* - ``LD_register_csv_source`` / ``LD_register_csv_sources``
130+
- Bind a CSV file to a ``${csv.name.col}`` source.
131+
* - ``LD_clear_resolver``
132+
- Reset every registered variable / source.
133+
134+
**Recording / replay:**
135+
136+
.. list-table::
137+
:header-rows: 1
138+
:widths: 35 65
139+
140+
* - Command
141+
- Summary
142+
* - ``LD_load_har``
143+
- Read a HAR JSON file from disk.
144+
* - ``LD_har_to_tasks``
145+
- Convert a HAR document into a list of LoadDensity tasks.
146+
* - ``LD_har_to_action_json``
147+
- Convert a HAR document into a runnable action JSON.
148+
149+
**Metrics exporters:**
150+
151+
.. list-table::
152+
:header-rows: 1
153+
:widths: 35 65
154+
155+
* - Command
156+
- Summary
157+
* - ``LD_start_prometheus_exporter`` / ``LD_stop_prometheus_exporter``
158+
- Toggle the Prometheus HTTP endpoint.
159+
* - ``LD_start_influxdb_sink`` / ``LD_stop_influxdb_sink``
160+
- Toggle the InfluxDB UDP / HTTP sink.
161+
* - ``LD_start_opentelemetry_exporter`` / ``LD_stop_opentelemetry_exporter``
162+
- Toggle the OTLP gRPC exporter.
163+
164+
Adding custom commands
165+
----------------------
166+
167+
.. code-block:: python
168+
169+
from je_load_density import add_command_to_executor
170+
171+
def slack_notify(message: str) -> None:
172+
...
173+
174+
add_command_to_executor({"LD_slack_notify": slack_notify})
175+
176+
Once registered, the new command is callable from any action JSON.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
API Reference
2+
=============
3+
4+
The auto-generated Python reference is regenerated by Sphinx
5+
``autosummary`` on every build.
6+
7+
.. autosummary::
8+
:toctree: _autosummary
9+
:recursive:
10+
11+
je_load_density
12+
je_load_density.utils.executor.action_executor
13+
je_load_density.utils.parameterization.parameter_resolver
14+
je_load_density.utils.recording.har_importer
15+
je_load_density.utils.metrics.prometheus_exporter
16+
je_load_density.utils.metrics.influxdb_sink
17+
je_load_density.utils.metrics.opentelemetry_exporter
18+
je_load_density.utils.test_record.test_record_class
19+
je_load_density.utils.test_record.sqlite_persistence
20+
je_load_density.utils.generate_report.generate_html_report
21+
je_load_density.utils.generate_report.generate_json_report
22+
je_load_density.utils.generate_report.generate_xml_report
23+
je_load_density.utils.generate_report.generate_csv_report
24+
je_load_density.utils.generate_report.generate_junit_report
25+
je_load_density.utils.generate_report.generate_summary_report
26+
je_load_density.utils.socket_server.load_density_socket_server
27+
je_load_density.wrapper.create_locust_env.create_locust_env
28+
je_load_density.wrapper.start_wrapper.start_test
29+
je_load_density.wrapper.user_template.request_executor
30+
je_load_density.wrapper.user_template.scenario_runner
31+
je_load_density.wrapper.user_template.http_user_template
32+
je_load_density.wrapper.user_template.fast_http_user_template
33+
je_load_density.wrapper.user_template.websocket_user_template
34+
je_load_density.wrapper.user_template.grpc_user_template
35+
je_load_density.wrapper.user_template.mqtt_user_template
36+
je_load_density.wrapper.user_template.socket_user_template
37+
je_load_density.mcp_server.server
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
Architecture
2+
============
3+
4+
Overview
5+
--------
6+
7+
LoadDensity is a thin facade over Locust that adds a JSON-driven action
8+
executor, a multi-protocol user template registry, scenario flow, data
9+
parameterisation, observability sinks, and an MCP control surface.
10+
11+
The dependency direction always points from the action layer down to
12+
Locust, never the other way around — your action JSON defines what to
13+
do, the executor maps each command to a Python callable, and Locust
14+
runs the resulting load.
15+
16+
Layered view
17+
------------
18+
19+
.. mermaid::
20+
21+
flowchart TB
22+
cli[CLI / MCP / GUI / Socket Server] --> exec[Action Executor]
23+
exec --> start[start_test]
24+
start --> proxy[locust_wrapper_proxy]
25+
proxy --> userhttp[HTTP / FastHttp Wrapper]
26+
proxy --> userws[WebSocket Wrapper]
27+
proxy --> usergrpc[gRPC Wrapper]
28+
proxy --> usermqtt[MQTT Wrapper]
29+
proxy --> usersock[Raw TCP/UDP Wrapper]
30+
userhttp & userws & usergrpc & usermqtt & usersock --> hooks[Locust events]
31+
hooks --> records[test_record_instance]
32+
hooks --> exporters[Prometheus / Influx / OTel]
33+
records --> reports[HTML / JSON / XML / CSV / JUnit / Summary]
34+
records --> sqlite[SQLite persistence]
35+
36+
Module map
37+
----------
38+
39+
.. list-table::
40+
:header-rows: 1
41+
:widths: 35 65
42+
43+
* - Module
44+
- Purpose
45+
* - ``je_load_density.utils.executor``
46+
- ``Executor`` class, dispatch table, ``execute_action`` /
47+
``execute_files`` entrypoints.
48+
* - ``je_load_density.utils.parameterization``
49+
- ``ParameterResolver`` for ``${var.x}`` / ``${env.X}`` /
50+
``${csv.s.col}`` / ``${faker.method}`` / built-in helpers.
51+
* - ``je_load_density.utils.recording``
52+
- HAR ingestion → action JSON.
53+
* - ``je_load_density.utils.metrics``
54+
- Prometheus exporter, InfluxDB sink, OpenTelemetry exporter.
55+
* - ``je_load_density.utils.test_record``
56+
- In-memory record list plus optional SQLite sink.
57+
* - ``je_load_density.utils.generate_report``
58+
- HTML / JSON / XML / CSV / JUnit / summary generators.
59+
* - ``je_load_density.utils.socket_server``
60+
- Length-framed TCP control plane with optional TLS and token.
61+
* - ``je_load_density.wrapper.proxy``
62+
- Per-protocol proxy holding the configured tasks for each user
63+
template.
64+
* - ``je_load_density.wrapper.user_template``
65+
- Locust user classes for HTTP, FastHttp, WebSocket, gRPC, MQTT,
66+
and raw socket.
67+
* - ``je_load_density.wrapper.start_wrapper``
68+
- ``start_test`` dispatcher that picks a user template and forwards
69+
to ``prepare_env``.
70+
* - ``je_load_density.wrapper.create_locust_env``
71+
- ``prepare_env`` / ``create_env`` building a Locust environment in
72+
local, master, or worker mode.
73+
* - ``je_load_density.mcp_server``
74+
- MCP server exposing 11 tools so Claude can drive LoadDensity.
75+
* - ``je_load_density.gui``
76+
- Optional PySide6 widgets (form controls + live stats panel).
77+
78+
Action lifecycle
79+
----------------
80+
81+
#. Caller submits an action JSON via the CLI, MCP tool, socket server,
82+
or direct ``execute_action(...)`` call.
83+
#. ``Executor.execute_action`` dispatches each step against
84+
``event_dict`` (``LD_*`` commands plus safe builtins).
85+
#. When the step is ``LD_start_test``, the dispatcher selects a user
86+
template (``http_user``, ``fast_http_user``, ``websocket_user``,
87+
``grpc_user``, ``mqtt_user``, ``socket_user``), seeds the parameter
88+
resolver from any ``variables`` / ``csv_sources``, and calls
89+
``prepare_env``.
90+
#. ``prepare_env`` builds a Locust ``Environment`` in local, master, or
91+
worker mode and starts the run.
92+
#. Each user runs ``run_scenario`` (or the protocol equivalent) per
93+
tick, fires Locust events, and feeds ``test_record_instance``.
94+
#. Reports, metrics exporters, and SQLite persistence consume the
95+
accumulated records.
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
Assertions & Extractors
2+
=======================
3+
4+
Overview
5+
--------
6+
7+
HTTP and FastHttp tasks accept ``assertions`` and ``extract`` blocks
8+
that run under Locust's ``catch_response``. Failed assertions mark the
9+
request as a Locust failure and surface in every report.
10+
11+
Assertions
12+
----------
13+
14+
.. list-table::
15+
:header-rows: 1
16+
:widths: 25 75
17+
18+
* - ``type``
19+
- Behaviour
20+
* - ``status_code``
21+
- ``int(response.status_code) == int(value)``.
22+
* - ``contains``
23+
- ``str(value) in response.text``.
24+
* - ``not_contains``
25+
- ``str(value) not in response.text``.
26+
* - ``json_path``
27+
- Resolves ``response.json()`` along ``path`` (dot-separated; list
28+
indices supported) and compares to ``value``.
29+
* - ``header``
30+
- ``response.headers[name] == value``.
31+
32+
Example
33+
~~~~~~~
34+
35+
.. code-block:: json
36+
37+
{
38+
"method": "get",
39+
"request_url": "${var.base}/health",
40+
"assertions": [
41+
{"type": "status_code", "value": 200},
42+
{"type": "json_path", "path": "status", "value": "ok"},
43+
{"type": "header", "name": "X-Service", "value": "checkout"}
44+
]
45+
}
46+
47+
Extractors
48+
----------
49+
50+
.. list-table::
51+
:header-rows: 1
52+
:widths: 25 75
53+
54+
* - ``from``
55+
- Source
56+
* - ``json_path``
57+
- Same dotted path syntax as the ``json_path`` assertion.
58+
* - ``header``
59+
- ``response.headers[name]``.
60+
* - ``status_code``
61+
- ``response.status_code``.
62+
63+
Extracted values are written into the parameter resolver under the
64+
chosen ``var`` name; subsequent tasks reference them as ``${var.NAME}``.
65+
66+
.. code-block:: json
67+
68+
{
69+
"method": "post",
70+
"request_url": "${var.base}/login",
71+
"json": {"email": "u@example.com", "password": "secret"},
72+
"extract": [
73+
{"var": "auth_token", "from": "json_path", "path": "data.token"},
74+
{"var": "request_id", "from": "header", "name": "X-Request-Id"}
75+
]
76+
}

0 commit comments

Comments
 (0)