docs/changelog.rst
#################### Changelog Highlights ####################
For full details of changes, please see https://github.com/locustio/locust/releases or https://github.com/locustio/locust/blob/master/CHANGELOG.md
(skipped because of failed publishing)
/stats/requests endpoint when there are >500 unique request names https://github.com/locustio/locust/pull/3136locust --cloud https://github.com/locustio/locust/pull/3097Locust Cloud <https://www.locust.cloud>_ features https://github.com/locustio/locust/pull/3032custom_messages concurrently (https://github.com/locustio/locust/pull/2650)test_stopping, triggered just before stopping the test https://github.com/locustio/locust/pull/2033quit, to enable getting the locust process exit code https://github.com/locustio/locust/pull/2049requests) (https://github.com/locustio/locust/pull/1858)This has allowed us to fix some issues with incorrect/skewed User type selection and undesired stepping of ramp up. The issues were especially visible when running many workers and/or using LoadShape:s. This change also allows redistribution of Users if a worker disconnects during a test. This is a major change internally in Locust so please let us know if you encounter any problems (particularly regarding ramp up pace, User distribution, CPU usage on master, etc)
user_classes_count from heartbeat payload (2.0.0b4) https://github.com/locustio/locust/pull/1825Some of these are not really that significant and may be removed from this list at a later time, once 2.0 has stabilised.
Bug fixes:
python:3.8 image instead of python:3.8-alpine. This should
make it easier to install other python packages when extending the locust docker image.Environment.process_exit_code <locust.env.Environment.process_exit_code>.. _changelog-1-0:
This version contains some breaking changes.
We've renamed the Locust and HttpLocust classes to User and HttpUser. The locust attribute on
:py:class:TaskSet <locust.TaskSet> instances has been renamed to :py:attr:user <locust.TaskSet.user>.
The parameter for setting number of users has also been changed, from -c / --clients to -u / --users.
User classIt's now possible to declare tasks directly under a User class like this:
.. code-block:: python
class WebUser(User):
@task
def some_task(self):
pass
In tasks declared under a User class (e.g. some_task in the example above), self refers to the User
instance, as one would expect. For tasks defined under a :py:class:TaskSet <locust.TaskSet> class, self
would refer to the TaskSet instance.
The task_set attribute on the User class (previously Locust class) has been removed. To declare a
User class with a single TaskSet one would now use the :py:attr:tasks <locust.User.tasks>
attribute instead:
.. code-block:: python
class MyTaskSet(TaskSet):
...
class WebUser(User):
tasks = [MyTaskSet]
A new :ref:tag feature <tagging-tasks> has been added that makes it possible to include/exclude tasks during
a test run.
Tasks can be tagged using the :py:func:@tag <locust.tag> decorator:
.. code-block:: python
class WebUser(User):
@task
@tag("tag1", "tag2")
def my_task(self):
...
And tasks can then be specified/excluded using the --tags/-T and --exclude-tags/-E command line arguments.
The following changes has been made to the configuration environment variables
LOCUST_MASTER has been renamed to LOCUST_MODE_MASTER (in order to make it less likely to get variable name collisions
when running Locust in Kubernetes/K8s which automatically adds environment variables depending on service/pod names).LOCUST_SLAVE has been renamed to LOCUST_MODE_WORKER.LOCUST_MASTER_PORT has been renamed to LOCUST_MASTER_NODE_PORT.LOCUST_MASTER_HOST has been renamed to LOCUST_MASTER_NODE_HOST.CSVFILEBASE has been renamed to LOCUST_CSV.See the :ref:configuration documentation for a full list of available :ref:environment variables <environment-variables>.
The master/slave terminology has been changed to master/worker. Therefore the command line arguments --slave and
--expect-slaves has been renamed to --worker and --expect-workers.
The option for running Locust without the Web UI has been renamed from --no-web to --headless.
Removed Locust.setup, Locust.teardown, TaskSet.setup and TaskSet.teardown hooks. If you want to
run code at the start or end of a test, you should instead use the :py:attr:test_start <locust.event.Events.test_start>
and :py:attr:test_stop <locust.event.Events.test_stop> events:
.. code-block:: python
from locust import events
@events.test_start.add_listener
def on_test_start(**kw):
print("test is starting")
@events.test_stop.add_listener
def on_test_start(**kw):
print("test is stopping")
TaskSequence and @seq_task has been replaced with :ref:SequentialTaskSet <sequential-taskset>.
A User count column has been added to the history stats CSV file. The column order and column names has been changed.
The official docker image no longer uses a shell script with a bunch of special environment variables to configure how
how locust is started. Instead, the locust command is now set as ENTRYPOINT of the docker image. See
:ref:running-in-docker for more info.
Command line option --csv-base-name has been removed, since it was just an alias for --csv.
The way Locust handles logging has been changed. We no longer wrap stdout (and stderr) to automatically make print
statements go into the log. print() statements now only goes to stdout. To add custom entries to the log, one
should now use the Python logging module:
.. code-block:: python
import logging
logging.info("custom logging message)
For more info see :ref:logging
--web-auth command line argument.--tls-cert
and --tls-key command line arguments.--config command line option for specifying a :ref:configuration file <configuration-file> pathLocust as a python lib <use-as-lib>.response.failure() or response.success() multiple times when using
the catch_response=True in the HTTP clients. Only the last call to success/failure will count.--help output has been improved by grouping related options together.Various minor fixes, mainly regarding FastHttpLocust.
Identical to previous version, but now built & deployed to Pypi using Travis.
--stop-timeout is not respected when changing number of running Users in distributed mode - https://github.com/locustio/locust/issues/1162New API for specifying wait time - https://github.com/locustio/locust/pull/1118
Example of the new API::
from locust import HttpLocust, between
class User(HttpLocust):
# wait between 5 and 30 seconds
wait_time = between(5, 30)
There are three built in :ref:wait time functions <wait_time_functions>: :py:func:between <locust.wait_time.between>,
:py:func:constant <locust.wait_time.constant> and :py:func:constant_pacing <locust.wait_time.constant_pacing>.
FastHttpLocust: Accept self signed SSL certificates, ignore host checks. Improved response code handling
Add current working dir to sys.path - https://github.com/locustio/locust/pull/484
Web UI improvements: Added 90th percentile to table, failure per seconds as a series in the chart
Ability to specify host in web ui
Added response_length to request_failure event - https://github.com/locustio/locust/pull/1144
Added p99.9 and p99.99 to request stats distribution csv - https://github.com/locustio/locust/pull/1125
Various other bug fixes and improvements.
--skip-log-setup to disable Locust's default logging setup.--stop-timeout to allow tasks to finish running their iteration before stoppingFastHttpLocust class that uses a faster HTTP client, which should be 5-6 times faster
than the normal :code:HttpLocust class. For more info see the documentation on :ref:increasing performance <increase-performance>.--exit-code-on-error parameter.--no-reset-stats has been deprecated (since it's now the default behavior),
and instead a new :code:--reset-stats option has been added.--no-reset-stats option for controlling if the statistics should be reset once
the hatching is completePreviously, the Locust class instantiated a :py:class:HttpSession <locust.clients.HttpSession>
under the client attribute that was used to make HTTP requests. This functionality has
now been moved into the :py:class:HttpLocust <locust.core.HttpLocust> class, in an
effort to make it more obvious how one can use Locust to
:doc:load test non-HTTP systems <testing-other-systems>.
To make existing locust scripts compatible with the new version you should make your locust classes inherit from HttpLocust instead of the base Locust class.
Locust now uses msgpack <http://msgpack.org/>_ for serializing data that is sent between
a master node and its slaves. This addresses a possible attack that can be used to execute
code remote, if one has access to the internal locust ports that are used for master-slave
communication. The reason for this exploit was due to the fact that pickle was used.
.. warning::
Anyone who uses an older version should make sure that their Locust machines are not publicly
accessible on port 5557 and 5558. Also, one should never run Locust as root.
Anyone who uses the :py:class:report_to_master <locust.events.report_to_master> and
:py:class:slave_report <locust.events.slave_report> events, needs to make sure that
any data that is attached to the slave reports is serializable by msgpack.
Locust updated requests <http://python-requests.org/>_ to the latest major release.
.. note::
Requests 1.0 introduced some major API changes (and 2.0 just a few). Please check if you
are using any internal features and check the documentation:
Migrating to 1.x <http://docs.python-requests.org/en/latest/api/#migrating-to-1-x>_ and
Migrationg to 2.x <http://docs.python-requests.org/en/latest/api/#migrating-to-2-x>_
gevent 1.0 has now been released and Locust has been updated accordingly.
Refactored :py:class:RequestStats.
StatsEntry which represents a single stats entry (URL).Previously the :py:class:RequestStats was actually doing two different things:
Now RequestStats should be instantiated and holds the global stats, as well as a dict of StatsEntry instances which holds the stats for single stats entries (URLs)
Previously one could specify avg_wait to :py:class:TaskSet and :py:class:Locust that Locust would try to strive to. However this can be sufficiently accomplished by using min_wait and max_wait for most use-cases. Therefore we've decided to remove the avg_wait as its use-case is not clear or just too narrow to be in the Locust core.
Previously one could tell Locust, using the --ramp option, to try to find a stable client count that the target host could handle, but it's been broken and undocumented for quite a while so we've decided to remove it from the locust core and perhaps have it reappear as a plugin in the future.
When :doc:extending-locust by listening to :ref:events, the listener functions should now expect
the arguments to be passed in as keyword arguments. It's also highly recommended to add an extra
wildcard keyword arguments to listener functions, since they're then less likely to break if extra
arguments are added to that event in some future version. For example::
from locust import events
def on_request(request_type, name, response_time, response_length, **kw):
print "Got request!"
locust.events.request_success += on_request
The method and path arguments to :py:obj:request_success <locust.events.request_success> and
:py:obj:request_failure <locust.events.request_failure> are now called request_type and name,
since it's less HTTP specific.
parent <locust.core.TaskSet.parent> attribute to TaskSet class that
refers to the parent TaskSet, or Locust, instance. Contributed by Aaron Daubman... warning::
This version comes with non backward compatible changes to the API.
Anyone who is currently using existing locust scripts and want to upgrade to 0.6
should read through these changes.
SubLocust <locust.core.SubLocust> replaced by :py:class:TaskSet <locust.core.TaskSet> and :py:class:Locust <locust.core.Locust> class behavior changed:py:class:Locust <locust.core.Locust> classes does no longer control task scheduling and execution.
Therefore, you no longer define tasks within Locust classes, instead the Locust class has a
:py:attr:task_set <locust.core.Locust.task_set> attribute which should point to a
:py:class:TaskSet <locust.core.TaskSet> class. Tasks should now be defined in TaskSet
classes, in the same way that was previously done in Locust and SubLocust classes. TaskSets can be
nested just like SubLocust classes could.
So the following code for 0.5.1::
class User(Locust):
min_wait = 10000
max_wait = 120000
@task(10)
def index(self):
self.client.get("/")
@task(2)
class AboutPage(SubLocust):
min_wait = 10000
max_wait = 120000
def on_init(self):
self.client.get("/about/")
@task
def team_page(self):
self.client.get("/about/team/")
@task
def press_page(self):
self.client.get("/about/press/")
@task
def stop(self):
self.interrupt()
Should now be written like::
class BrowsePage(TaskSet):
@task(10)
def index(self):
self.client.get("/")
@task(2)
class AboutPage(TaskSet):
def on_init(self):
self.client.get("/about/")
@task
def team_page(self):
self.client.get("/about/team/")
@task
def press_page(self):
self.client.get("/about/press/")
@task
def stop(self):
self.interrupt()
class User(Locust):
min_wait = 10000
max_wait = 120000
task_set = BrowsePage
Each TaskSet instance gets a :py:attr:locust <locust.core.TaskSet.locust> attribute, which refers to the
Locust class.
Locust's own HttpBrowser class (which was typically accessed through self.client from within a locust class) has been replaced by a thin wrapper around the requests library (http://python-requests.org). This comes with a number of advantages. Users can now take advantage of a well documented, well written, fully fledged library for making HTTP requests. However, it also comes with some small API changes which will require users to update their existing load testing scripts.
Gzip encoding turned on by default ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The HTTP client now sends headers for accepting gzip encoding by default. The --gzip command line argument has been removed and if someone want to disable the Accept-Encoding that the HTTP client uses, or any other HTTP headers you can do::
class MyWebUser(Locust):
def on_start(self):
self.client.headers = {"Accept-Encoding":""}
Improved HTTP client ^^^^^^^^^^^^^^^^^^^^
Because of the switch to using python-requests in the HTTP client, the API for the client has also gotten a few changes.
Additionally to the :py:meth:get <locust.clients.HttpSession.get>, :py:meth:post <locust.clients.HttpSession.post>,
:py:meth:put <locust.clients.HttpSession.put>, :py:meth:delete <locust.clients.HttpSession.delete> and
:py:meth:head <locust.clients.HttpSession.head> methods, the :py:class:HttpSession <locust.clients.HttpSession> class
now also has :py:meth:patch <locust.clients.HttpSession.patch> and :py:meth:options <locust.clients.HttpSession.options> methods.
All arguments to the HTTP request methods, except for url and data should now be specified as keyword arguments. For example, previously one could specify headers using::
client.get("/path", {"User-Agent":"locust"}) # this will no longer work
And should now be specified like::
client.get("/path", headers={"User-Agent":"locust"})
In general the whole HTTP client is now more powerful since it leverages on python-requests. Features that we're
now able to use in Locust includes file upload, SSL, connection keep-alive, and more.
See the python-requests documentation <http://python-requests.org>_ for more details.
The new :py:class:HttpSession <locust.clients.HttpSession> class' methods now return python-request
:py:class:Response <requests.Response> objects. This means that accessing the content of the response
is no longer made using the data attribute, but instead the content attribute. The HTTP response
code is now accessed through the status_code attribute, instead of the code attribute.
HttpSession methods' catch_response argument improved and allow_http_error argument removed ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When doing HTTP requests using the catch_response argument, the context manager that is returned now
provides two functions, :py:meth:success <locust.clients.ResponseContextManager.success> and
:py:meth:failure <locust.clients.ResponseContextManager.failure> that can be used to manually control
what the request should be reported as in Locust's statistics.
.. autoclass:: locust.clients.ResponseContextManager :members: success, failure :noindex:
The allow_http_error argument of the HTTP client's methods has been removed. Instead one can use the catch_response argument to get a context manager, which can be used together with a with statement.
The following code in the previous Locust version::
client.get("/does/not/exist", allow_http_error=True)
Can instead now be written like::
with client.get("/does/not/exist", catch_response=True) as response:
response.success()
locust.core.Locust.schedule_task can now take
arguments and keyword arguments (available in self.args and self.kwargs).locust.core.Locust.schedule_task. Previously all extra arguments that
was given to the method was passed on to the task when it was called. It no longer accepts extra arguments.
Instead, it takes an args argument (list) and a kwargs argument (dict) which are be passed to the task when
it's called.request_success <locust.events.request_success> event hook has been changed.
Previously it took an HTTP Response instance as argument, but this has been changed to take the
content-length of the response instead. This makes it easier to write custom clients for Locust.locust.events.request_success and :func:locust.events.request_failure now gets the HTTP method as the first argument.Removed --show-task-ratio-confluence and added a --show-task-ratio-json option instead. The --show-task-ratio-json will output JSON data containing the task execution ratio for the locust "brain".
The HTTP method used when a client requests a URL is now displayed in the web UI
Some fixes and improvements in the stats exporting:
A file name is now set (using content-disposition header) when downloading stats.
The order of the column headers for request stats was wrong.
Thanks Benjamin W. Smith, Jussi Kuosa and Samuele Pedroni!