Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into issues/2955
Browse files Browse the repository at this point in the history
  • Loading branch information
tyge68 committed Nov 24, 2024
2 parents 11cd620 + 94acf20 commit 341e248
Show file tree
Hide file tree
Showing 55 changed files with 675 additions and 1,842 deletions.
1 change: 0 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,6 @@ jobs:
# -------------------------

publish:
name: Publish prerelease on merge commit to master
needs: [tox_tests, lint_typecheck_test_webui, test_docker_image, build_package]
if: github.repository_owner == 'locustio' && ( github.ref == 'refs/heads/master' || startsWith(github.event.ref, 'refs/tags') )
runs-on: ubuntu-latest
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.3.7 # Pin the same version in the pyproject.toml file
rev: v0.7.3 # Pin the same version in the pyproject.toml file
hooks:
# Run the linter.
- id: ruff
Expand Down
18 changes: 17 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"gevent": true
},
{
"name": "Run locust",
"name": "Run current locust scenario headless",
"type": "python",
"request": "launch",
"module": "locust",
Expand All @@ -22,6 +22,22 @@
],
"console": "integratedTerminal",
"gevent": true
},
{
"name": "Run current locust scenario, autostart",
"type": "python",
"request": "launch",
"module": "locust",
"args": [
"-f",
"${file}",
"--users=5",
"--autostart",
"--print-stats",
"-L=ERROR"
],
"console": "integratedTerminal",
"gevent": true
}
]
}
1,680 changes: 65 additions & 1,615 deletions CHANGELOG.md

Large diffs are not rendered by default.

21 changes: 20 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,26 @@ Locust makes it easy to run load tests distributed over multiple machines. It is

Locust has a user friendly web interface that shows the progress of your test in real-time. You can even change the load while the test is running. It can also be run without the UI, making it easy to use for CI/CD testing.

<img src="docs/images/bottlenecked_server.png" alt="Locust UI charts" height="100" width="200"/> <img src="docs/images/webui-running-statistics.png" alt="Locust UI stats" height="100" width="200"/> <img src="docs/images/locust_workers.png" alt="Locust UI workers" height="100" width="200"/> <img src="docs/images/webui-splash-screenshot.png" alt="Locust UI start test" height="100" width="200"/>
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/locustio/locust/refs/heads/master/docs/images/bottlenecked-server-light.png" alt="Locust UI charts" height="100" width="200"/>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/locustio/locust/refs/heads/master/docs/images/bottlenecked-server-dark.png" alt="Locust UI charts" height="100" width="200"/>
<img src="https://raw.githubusercontent.com/locustio/locust/refs/heads/master/docs/images/bottlenecked-server-light.png" alt="Locust UI charts" height="100" width="200"/>
</picture>
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/locustio/locust/refs/heads/master/docs/images/webui-running-statistics-light.png" alt="Locust UI stats" height="100" width="200"/>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/locustio/locust/refs/heads/master/docs/images/webui-running-statistics-dark.png" alt="Locust UI stats" height="100" width="200"/>
<img src="https://raw.githubusercontent.com/locustio/locust/refs/heads/master/docs/images/webui-running-statistics-light.png" alt="Locust UI stats" height="100" width="200"/>
</picture>
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/locustio/locust/refs/heads/master/docs/images/locust-workers-light.png" alt="Locust UI workers" height="100" width="200"/>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/locustio/locust/refs/heads/master/docs/images/locust-workers-dark.png" alt="Locust UI workers" height="100" width="200"/>
<img src="https://raw.githubusercontent.com/locustio/locust/refs/heads/master/docs/images/locust-workers-light.png" alt="Locust UI workers" height="100" width="200"/>
</picture>
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/locustio/locust/refs/heads/master/docs/images/webui-splash-light.png" alt="Locust UI start test" height="100" width="200"/>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/locustio/locust/refs/heads/master/docs/images/webui-splash-dark.png" alt="Locust UI start test" height="100" width="200"/>
<img src="https://raw.githubusercontent.com/locustio/locust/refs/heads/master/docs/images/webui-splash-light.png" alt="Locust UI start test" height="100" width="200"/>
</picture>

#### Can test any system

Expand Down
17 changes: 17 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,23 @@ Changelog Highlights

For full details of the Locust changelog, please see https://github.com/locustio/locust/blob/master/CHANGELOG.md

2.32.3
======
* Add option for Extra Options to be Required https://github.com/locustio/locust/pull/2981
* Use debug log level for first 5s of waiting for workers to be ready https://github.com/locustio/locust/pull/2982
* Ensure we never use old version of setuptools https://github.com/locustio/locust/pull/2988

2.32.2
======
* Better html report file names https://github.com/locustio/locust/pull/2947
* Fix Incorrectly Updating Stat History https://github.com/locustio/locust/pull/2972
* Various WebUI fixes (most only relevant for https://locust.cloud)

2.32.1
======
* Various WebUI fixes (most only relevant for https://locust.cloud)
* LocustBadStatusCode without url param in fasthttp https://github.com/locustio/locust/pull/2944

2.32.0
======
* Explicitly support Python 3.13 https://github.com/locustio/locust/pull/2939
Expand Down
16 changes: 16 additions & 0 deletions docs/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,22 @@ You can specify an additional file using the ``--config`` flag.
$ locust --config custom_config.conf
Here's a minimalistic example of the configuration file supported by Locust:

Have a look later in this article for :ref:`All available configuration options`

locust.conf
--------------

.. code-block:: ini
locustfile = locust_files/my_locust_file.py
headless = true
host = https://target-system
run-time = 1m
spawn-rate =
users = 1
Here's a quick example of the configuration files supported by Locust:

locust.conf
Expand Down
2 changes: 1 addition & 1 deletion docs/custom-load-shape.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ This shape class will increase user count in blocks of 100 and then stop the loa
if run_time < self.time_limit:
# User count rounded to nearest hundred.
user_count = round(run_time, -2)
return (user_count, spawn_rate)
return (user_count, self.spawn_rate)
return None
Expand Down
13 changes: 10 additions & 3 deletions docs/developing-locust.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ If you install `pre-commit <https://pre-commit.com/>`_, linting and format check

Before you open a pull request, make sure all the tests work. And if you are adding a feature, make sure it is documented (in ``docs/*.rst``).

If you're in a hurry or don't have access to a development environment, you can simply use `Codespaces <https://github.com/features/codespaces>`_, the github cloud development environment. On your fork page, just click on *Code* then on *Create codespace on <branch name>*, and voila, your ready to code and test.

Testing your changes
====================

Expand All @@ -51,6 +53,11 @@ To only run a specific suite or specific test you can call `pytest <https://docs
$ pytest locust/test/test_main.py::DistributedIntegrationTests::test_distributed_tags
Debugging
=========

See: :ref:`running-in-debugger`.

Formatting and linting
======================

Expand Down Expand Up @@ -131,7 +138,7 @@ Yarn
$ yarn --version
- Next in web, install all dependencies
- Next, install all dependencies

.. code-block:: console
Expand All @@ -142,9 +149,9 @@ Yarn
Developing
----------

To develop the frontend, run ``yarn dev``. This will start the Vite dev server and allow for viewing and editing the frontend, without needing to a run a locust web server
To develop while running a locust instance, run ``yarn watch``. This will output the static files to the ``dist`` directory. Vite will automatically detect any changed files and re-build as needed. Simply refresh the page to view the changes

To develop while running a locust instance, run ``yarn dev:watch``. This will output the static files to the ``dist`` directory. Vite will automatically detect any changed files and re-build as needed. Simply refresh the page to view the changes
In certain situations (usually when styling), you may want to develop the frontend without running a locust instance. Running ``yarn dev`` will start the Vite dev server and allow for viewing your changes.

To compile the webui, run ``yarn build``

Expand Down
7 changes: 5 additions & 2 deletions docs/extending-locust.rst
Original file line number Diff line number Diff line change
Expand Up @@ -154,14 +154,17 @@ to the ``login_manager``. The ``user_loader`` should return ``None`` to deny aut
authentication to the app should be granted.

To display errors on the login page, such as an incorrect username / password combination, you may store the ``auth_error``
on the session object: ``session["auth_error"] = "Incorrect username or password"``.
on the session object: ``session["auth_error"] = "Incorrect username or password"``. If you have non-erroneous information
you would like to display to the user, you can opt instead to set ``auth_info`` on the session object:
``session["auth_info"] = "Successfully created new user!"``

A full example can be seen `in the auth example <https://github.com/locustio/locust/tree/master/examples/web_ui_auth/basic.py>`_.

In certain situations you may wish to further extend the fields present in the auth form. To achieve this, pass a ``custom_form`` dict
to the ``environment.web_ui.auth_args``. In this case, the fields will be represented by a list of ``inputs``, the callback url is
configured by the ``custom_form.callback_url``, and the submit button may optionally be configured using the ``custom_form.submit_button_text``.
The fields in the auth form may be a text, select, checkbox, or secret password field.
The fields in the auth form may be a text, select, checkbox, or secret password field. You may additionally override the HTML input type for
specific field validation (e.g. type=email).

For a full example see `configuring the custom_form in the auth example <https://github.com/locustio/locust/tree/master/examples/web_ui_auth/custom_form.py>`_.

Expand Down
Binary file added docs/images/bottlenecked-server-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/bottlenecked-server-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed docs/images/bottlenecked_server.png
Binary file not shown.
Binary file added docs/images/locust-workers-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/locust-workers-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed docs/images/locust_workers.png
Binary file not shown.
Binary file added docs/images/webui-running-statistics-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/webui-running-statistics-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed docs/images/webui-running-statistics.png
Binary file not shown.
Binary file added docs/images/webui-splash-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/webui-splash-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed docs/images/webui-splash-screenshot.png
Binary file not shown.
2 changes: 1 addition & 1 deletion docs/increasing-request-rate.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Load generation performance

If Locust prints a warning about high CPU usage (``WARNING/root: CPU usage above 90%! ...``) try the following:

- Run Locust `distributed <https://docs.locust.io/en/stable/running-locust-distributed.html>`__ to utilize multiple cores & multiple machines
- Run Locust `distributed <https://docs.locust.io/en/stable/running-distributed.html>`__ to utilize multiple cores & multiple machines
- Try switching to `FastHttpUser <https://docs.locust.io/en/stable/increase-performance.html#increase-performance>`__ to reduce CPU usage
- Check to see that there are no strange/infinite loops in your code

Expand Down
12 changes: 11 additions & 1 deletion docs/running-in-debugger.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,17 @@ It implicitly registers an event handler for the :ref:`request <extending_locust
You can configure exactly what is printed by specifying parameters to :py:func:`run_single_user <locust.debug.run_single_user>`.

Make sure you have enabled gevent in your debugger settings. In VS Code's ``launch.json`` it looks like this:
Make sure you have enabled gevent in your debugger settings.

Debugging Locust is quite easy with Vscode:

- Place breakpoints
- Select a python file or a scenario (ex: ```examples/basic.py``)
- Check that the Poetry virtualenv is correctly detected (bottom right)
- Open the action *Debug using launch.json*. You will have the choice between debugging the python file, the scenario with WebUI or in headless mode
- It could be rerun with the F5 shortkey

VS Code's ``launch.json`` looks like this:

.. literalinclude:: ../.vscode/launch.json
:language: json
Expand Down
4 changes: 4 additions & 0 deletions examples/add_command_line_argument.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ def _(parser):
parser.add_argument("--my-ui-invisible-argument", include_in_web_ui=False, default="I am invisible")
# Set `is_secret` to True if you want the text input to be password masked in the web UI
parser.add_argument("--my-ui-password-argument", is_secret=True, default="I am a secret")
# Use a boolean default value if you want the input to be a checkmark
parser.add_argument("--my-ui-boolean-argument", default=True)
# Set `is_required` to mark a form field as required
parser.add_argument("--my-ui-required-argument", is_required=True, default="I am required")


@events.test_start.add_listener
Expand Down
13 changes: 6 additions & 7 deletions examples/web_ui_auth/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,21 @@ def get_id(self):
return self.username


auth_blueprint = Blueprint("auth", "web_ui_auth")


def load_user(username):
return AuthUser(username)


@events.init.add_listener
def locust_init(environment, **_kwargs):
if environment.web_ui:
auth_blueprint = Blueprint("auth", "web_ui_auth", url_prefix=environment.parsed_options.web_base_path)

environment.web_ui.login_manager.user_loader(load_user)

environment.web_ui.app.config["SECRET_KEY"] = os.getenv("FLASK_SECRET_KEY")

environment.web_ui.auth_args = {
"username_password_callback": "/login_submit",
"username_password_callback": f"{environment.parsed_options.web_base_path}/login_submit",
"auth_providers": [
{
"label": "Github",
Expand All @@ -61,7 +60,7 @@ def google_login():
session["username"] = username
login_user(AuthUser("username"))

return redirect(url_for("index"))
return redirect(url_for("locust.index"))

@auth_blueprint.route("/login_submit", methods=["POST"])
def login_submit():
Expand All @@ -72,10 +71,10 @@ def login_submit():
if password:
login_user(AuthUser(username))

return redirect(url_for("index"))
return redirect(url_for("locust.index"))

session["auth_error"] = "Invalid username or password"

return redirect(url_for("login"))
return redirect(url_for("locust.login"))

environment.web_ui.app.register_blueprint(auth_blueprint)
18 changes: 11 additions & 7 deletions examples/web_ui_auth/custom_form.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,15 @@ def get_id(self):
return self.username


auth_blueprint = Blueprint("auth", "web_ui_auth")


def load_user(user_id):
return AuthUser(user_id)


@events.init.add_listener
def locust_init(environment, **_kwargs):
if environment.web_ui:
auth_blueprint = Blueprint("auth", "web_ui_auth", url_prefix=environment.parsed_options.web_base_path)

environment.web_ui.login_manager.user_loader(load_user)

environment.web_ui.app.config["SECRET_KEY"] = os.getenv("FLASK_SECRET_KEY")
Expand All @@ -54,6 +53,11 @@ def locust_init(environment, **_kwargs):
{
"label": "Username",
"name": "username",
# make field required
"is_required": True,
# override input type for HTML validation
# applies if !is_secret and !choices, and default_value is string | None
"type": "email",
},
# boolean checkmark field
{"label": "Admin", "name": "is_admin", "default_value": False},
Expand All @@ -70,7 +74,7 @@ def locust_init(environment, **_kwargs):
"is_secret": True,
},
],
"callback_url": "/login_submit",
"callback_url": f"{environment.parsed_options.web_base_path}/login_submit",
"submit_button_text": "Submit",
},
}
Expand All @@ -86,7 +90,7 @@ def login_submit():
if password != confirm_password:
session["auth_error"] = "Passwords do not match!"

return redirect(url_for("login"))
return redirect(url_for("locust.login"))

# Implement real password verification here
if password:
Expand All @@ -98,10 +102,10 @@ def login_submit():

login_user(AuthUser(username))

return redirect(url_for("index"))
return redirect(url_for("locust.index"))

session["auth_error"] = "Invalid username or password"

return redirect(url_for("login"))
return redirect(url_for("locust.login"))

environment.web_ui.app.register_blueprint(auth_blueprint)
Loading

0 comments on commit 341e248

Please sign in to comment.