Giter Club home page Giter Club logo

invokust's Introduction

invokust

A tool for running Locust load tests from within Python without the need to use the locust command line. This gives more flexibility for automation such as QA/CI/CD tests and also makes it possible to run locust on AWS Lambda for ultimate scalability.

Installation

Install via pip:

pip3 install invokust

Examples

Running a load test using a locust file:

import invokust

settings = invokust.create_settings(
    locustfile='locustfile_example.py',
    host='http://www.iana.org',
    num_users=1,
    spawn_rate=1,
    run_time='3m'
    )

loadtest = invokust.LocustLoadTest(settings)
loadtest.run()
loadtest.stats()
"{'requests': {'GET_/': {'request_type': 'GET', 'num_requests': 923, 'min_response_time': 113.54585000000128, 'median_response_time': 120.0, 'avg_response_time': 145.68631223510297, 'max_response_time': 331.89674199999786, 'response_times': {270.0: 2, 120.0: 479, 150.0: 17, 200.0: 83, 210.0: 80, 160.0: 20, 190.0: 55, 220.0: 9, 130.0: 30, 170.0: 22, 230.0: 5, 110.0: 69, 140.0: 19, 180.0: 27, 240.0: 2, 320.0: 3, 330.0: 1}, 'response_time_percentiles': {55: 120.0, 65: 150.0, 75: 190.0, 85: 200.0, 95: 210.0}, 'total_rps': 5.136500841568583, 'total_rpm': 308.190050494115}, 'GET_/about': {'request_type': 'GET', 'num_requests': 308, 'min_response_time': 113.23035299999873, 'median_response_time': 120.0, 'avg_response_time': 146.04534828246747, 'max_response_time': 290.40608500000076, 'response_times': {120.0: 147, 200.0: 36, 190.0: 25, 110.0: 27, 160.0: 12, 150.0: 6, 180.0: 13, 210.0: 12, 170.0: 13, 220.0: 2, 130.0: 8, 140.0: 6, 290.0: 1}, 'response_time_percentiles': {55: 120.0, 65: 160.0, 75: 180.0, 85: 200.0, 95: 200.0}, 'total_rps': 1.7140219492991589, 'total_rpm': 102.84131695794953}}, 'failures': {}, 'num_requests': 1231, 'num_requests_fail': 0, 'start_time': 1608207776.312684, 'end_time': 1608207956.070369}"

Running a load test without locust file:

import invokust

from locust import HttpUser, between, task

class WebsiteUser(HttpUser):
    wait_time = between(1, 3)

    @task()
    def get_home_page(self):
        '''
        Gets /
        '''
        self.client.get("/")

settings = invokust.create_settings(
    classes=[WebsiteUser],
    host='http://www.iana.org',
    num_users=1,
    spawn_rate=1,
    run_time='3m'
)

loadtest = invokust.LocustLoadTest(settings)
loadtest.run()
loadtest.stats()
"{'requests': {'GET_/': {'request_type': 'GET', 'num_requests': 71, 'min_response_time': 138.60819600000696, 'median_response_time': 360.0, 'avg_response_time': 327.0060322394364, 'max_response_time': 603.2539320000012, 'response_times': {590.0: 1, 210.0: 3, 370.0: 2, 230.0: 5, 200.0: 2, 490.0: 2, 420.0: 4, 480.0: 1, 190.0: 5, 180.0: 6, 400.0: 3, 270.0: 1, 260.0: 3, 280.0: 2, 360.0: 4, 470.0: 2, 460.0: 3, 350.0: 1, 250.0: 1, 380.0: 4, 410.0: 2, 140.0: 1, 440.0: 1, 600.0: 1, 390.0: 2, 450.0: 1, 430.0: 3, 290.0: 1, 240.0: 2, 340.0: 1, 220.0: 1}, 'response_time_percentiles': {55: 370.0, 65: 390.0, 75: 420.0, 85: 450.0, 95: 490.0}, 'total_rps': 0.4443058717398536, 'total_rpm': 26.658352304391215}}, 'failures': {'GET_/': {'method': 'GET', 'name': '/', 'error': "ConnectionError(ProtocolError('Connection aborted.', RemoteDisconnected('Remote end closed connection without response')))", 'occurrences': 1}}, 'num_requests': 71, 'num_requests_fail': 1, 'start_time': 1608208114.321394, 'end_time': 1608208276.0525749}"

Running Locust on AWS Lambda

Lambda logoLocust logo

AWS Lambda is a great tool for load testing as it is very cheap (or free) and highly scalable.

There are many load testing tools such as ab and wrk. Then there are other cloud based load testing options such as BlazeMeter or Loader and some more DIY solutions that use AWS Lambda too such as Goad or serverless-artillery. But these all have the same drawback: They are too simplistic. They can perform simple GET or POST requests but can't accurately emulate more complex behaviour. e.g. browsing a website, selecting random items, filling a shopping cart and checking out. But with Locust this is possible.

Included is an example function for running Locust on AWS Lambda, lambda_locust.py.

Creating a Lambda function

The process for running a locust test on Lambda involves creating a zip file of the locust load test, creating a Lambda function and then triggering the function.

Install invokust (and its dependencies) python packages locally:

pip3 install invokust --target=python-packages

Or if running on a Mac (python packages need to be compiled for 64 bit Linux) you can use docker:

docker run -it --volume=$PWD:/temp python:3.7 bash -c "pip install /temp --target=/temp/python-packages"

Create the zip file:

zip -q -r lambda_locust.zip lambda_locust.py locustfile_example.py python-packages

Then create the Lambda function using using the AWS CLI:

aws lambda create-function --function-name lambda_locust --timeout 300 --runtime python3.7 --role arn:aws:iam::9999999999:role/lambda_basic_execution --handler lambda_locust.handler --zip-file fileb://lambda_locust.zip

Or Terraform and the example main.tf file:

terraform apply
...

Invoking the function

The Locust settings can be passed to the Lambda function or can be set from environment variables. The environment variables are:

  • LOCUST_LOCUSTFILE: Locust file to use for the load test
  • LOCUST_CLASSES: Names of locust classes to use for the load test (instead of a locustfile). If more than one, separate with comma.
  • LOCUST_HOST: The host to run the load test against
  • LOCUST_NUM_CLIENTS: Number of clients to simulate
  • LOCUST_HATCH_RATE: Number of clients per second to start
  • LOCUST_RUN_TIME: The time the test should run for
  • LOCUST_LOGLEVEL: Level of logging

AWS CLI example with Locust settings in a payload:

aws lambda invoke --function-name lambda_locust --invocation-type RequestResponse --payload '{"locustfile": "locustfile_example.py", "host":"http://www.iana.org", "num_users": "1", "spawn_rate": "1", "run_time":"3m"}' --cli-binary-format raw-in-base64-out output.txt
{
    "StatusCode": 200
}
cat output.txt
"{\"success\": {\"GET_/\": {\"request_type\": \"GET\", \"num_requests\": 20, \"min_response_time\": 86, \"median_response_time\": 93 ...

Python boto3 example:

import json
from boto3.session import Session
from botocore.client import Config

session = Session()
config = Config(connect_timeout=10, read_timeout=310)
client = session.client('lambda', config=config)

lambda_payload = {
    'locustfile': 'locustfile_example.py',
    'host': 'https://example.com',
    'num_users': '1',
    'spawn_rate': 1,
    'run_time':'3m'
}

response = client.invoke(FunctionName='lambda_locust', Payload=json.dumps(lambda_payload))
json.loads(response['Payload'].read())
'{"success": {"GET_/": {"request_type": "GET", "num_requests": 20, "min_response_time": 87, "median_response_time": 99, "avg_response_time": 97.35 ...

Running a real load test

Lambda function execution time is limited to a maximum of 15 minutes. To run a real load test the function will need to be invoked repeatedly and likely in parallel to generate enough load. To manage this there is a class called LambdaLoadTest that can manage invoking the function in parallel loops and collecting the statistics.

import logging
from invokust.aws_lambda import LambdaLoadTest

logging.basicConfig(level=logging.INFO)

lambda_payload = {
    'locustfile': 'locustfile_example.py',
    'host': 'https://example.com',
    'num_users': 1,
    'spawn_rate': 1,
    'run_time':'3m'
}

load_test = LambdaLoadTest(
  lambda_function_name='lambda_locust',
  threads=2,
  ramp_time=0,
  time_limit=30,
  lambda_payload=lambda_payload
)

load_test.run()
print(load_test.get_summary_stats())

The output:

INFO:root:
Starting load test...
Function name: lambda_locust
Ramp time: 0s
Threads: 2
Lambda payload: {'locustfile': 'locustfile_example.py', 'host': 'https://example.com', 'num_users': '1', 'spawn_rate': 1, 'run_time': '3m'}
Start ramping down after: 30s
INFO:root:thread started
INFO:root:Invoking lambda...
INFO:root:threads: 1, rpm: 0, time elapsed: 0s, total requests from finished threads: 0, request fail ratio: 0, invocation error ratio: 0
INFO:root:threads: 1, rpm: 0, time elapsed: 3s, total requests from finished threads: 0, request fail ratio: 0, invocation error ratio: 0
INFO:root:thread started
INFO:root:Invoking lambda...
INFO:root:threads: 2, rpm: 0, time elapsed: 6s, total requests from finished threads: 0, request fail ratio: 0, invocation error ratio: 0
INFO:root:threads: 2, rpm: 0, time elapsed: 9s, total requests from finished threads: 0, request fail ratio: 0, invocation error ratio: 0
INFO:root:threads: 2, rpm: 0, time elapsed: 12s, total requests from finished threads: 0, request fail ratio: 0, invocation error ratio: 0
INFO:root:threads: 2, rpm: 0, time elapsed: 15s, total requests from finished threads: 0, request fail ratio: 0, invocation error ratio: 0
INFO:root:threads: 2, rpm: 0, time elapsed: 18s, total requests from finished threads: 0, request fail ratio: 0, invocation error ratio: 0
INFO:root:threads: 2, rpm: 0, time elapsed: 21s, total requests from finished threads: 0, request fail ratio: 0, invocation error ratio: 0
INFO:root:threads: 2, rpm: 0, time elapsed: 24s, total requests from finished threads: 0, request fail ratio: 0, invocation error ratio: 0
INFO:root:threads: 2, rpm: 0, time elapsed: 27s, total requests from finished threads: 0, request fail ratio: 0, invocation error ratio: 0
INFO:root:threads: 2, rpm: 0, time elapsed: 30s, total requests from finished threads: 0, request fail ratio: 0, invocation error ratio: 0
INFO:root:threads: 2, rpm: 0, time elapsed: 33s, total requests from finished threads: 0, request fail ratio: 0, invocation error ratio: 0
INFO:root:Time limit reached. Starting ramp down...
INFO:root:Waiting for all Lambdas to return. This may take up to 3m.
INFO:invokust.aws_lambda.lambda_load_test:Lambda invocation complete. Requests (errors): 1867 (0), execution time: 180066ms, sleeping: 0s
INFO:root:thread finished
INFO:invokust.aws_lambda.lambda_load_test:Lambda invocation complete. Requests (errors): 1884 (0), execution time: 180065ms, sleeping: 0s
INFO:root:thread finished
{'lambda_invocation_count': 2, 'total_lambda_execution_time': 360131, 'requests_total': 3751, 'request_fail_ratio': 0.0, 'invocation_error_ratio': 0.0}

There is also an example CLI tool for running a load test, invokr.py:

$ ./invokr.py --function_name=lambda_locust --locust_file=locustfile_example.py --locust_host=https://example.com --threads=1 --time_limit=15 --locust_users=2
2017-05-22 20:16:22,432 INFO   MainThread
Starting load test
Function: lambda_locust
Ramp time: 0
Threads: 1
Lambda payload: {'locustfile': 'locustfile_example.py', 'host': 'https://example.com', 'num_users': 2, 'spawn_rate': 10, 'run_time': '15s'}

[2020-06-28 19:58:22,103] pudli/INFO/root: thread started
[2020-06-28 19:58:22,107] pudli/INFO/root: threads: 1, rpm: 0, run_time: 0, requests_total: 0, request_fail_ratio: 0, invocation_error_ratio: 0
[2020-06-28 19:58:25,108] pudli/INFO/root: threads: 1, rpm: 0, run_time: 3, requests_total: 0, request_fail_ratio: 0, invocation_error_ratio: 0
[2020-06-28 19:58:28,109] pudli/INFO/root: threads: 1, rpm: 0, run_time: 6, requests_total: 0, request_fail_ratio: 0, invocation_error_ratio: 0
[2020-06-28 19:58:31,110] pudli/INFO/root: threads: 1, rpm: 0, run_time: 9, requests_total: 0, request_fail_ratio: 0, invocation_error_ratio: 0
[2020-06-28 19:58:34,112] pudli/INFO/root: threads: 1, rpm: 0, run_time: 12, requests_total: 0, request_fail_ratio: 0, invocation_error_ratio: 0
[2020-06-28 19:58:37,113] pudli/INFO/root: threads: 1, rpm: 0, run_time: 15, requests_total: 0, request_fail_ratio: 0, invocation_error_ratio: 0
[2020-06-28 19:58:39,001] pudli/INFO/invokust.aws_lambda.lambda_load_test: Invocation complete. Requests (errors): 224 (120), execution time: 15066, sleeping: 0
[2020-06-28 19:58:40,116] pudli/INFO/root: threads: 1, rpm: 795, run_time: 18, requests_total: 224, request_fail_ratio: 0.5357142857142857, invocation_error_ratio: 0.0
[2020-06-28 19:58:40,117] pudli/ERROR/root: Error limit reached, invocation error ratio: 0.0, request fail ratio: 0.5357142857142857
[2020-06-28 19:58:40,117] pudli/INFO/root: Waiting for threads to exit...
[2020-06-28 19:58:54,086] pudli/INFO/invokust.aws_lambda.lambda_load_test: Invocation complete. Requests (errors): 242 (131), execution time: 15052, sleeping: 0
[2020-06-28 19:58:54,086] pudli/INFO/root: thread finished
[2020-06-28 19:58:54,142] pudli/INFO/root: Aggregated results: {"requests": {"GET_/": {"median_response_time": 92.0, "total_rps": 7.18569301694931, "avg_response_time": 91.08271769409947, "max_response_time": 114.66264724731445, "min_response_time": 84.4886302947998, "response_times": {"histogram": [85, 45, 4, 6, 7, 47, 11, 0, 0, 10], "bins": [84.0, 86.6, 89.2, 91.8, 94.4, 97.0, 99.6, 102.2, 104.8, 107.4, 110.0]}, "total_rpm": 431.1415810169586, "num_requests": 215}, "POST_/post": {"median_response_time": 150.0, "total_rps": 8.38878329746517, "avg_response_time": 157.73737294831653, "max_response_time": 1087.4686241149902, "min_response_time": 142.15636253356934, "response_times": {"histogram": [247, 0, 0, 1, 2, 0, 0, 0, 0, 1], "bins": [140.0, 236.0, 332.0, 428.0, 524.0, 620.0, 716.0, 812.0, 908.0, 1004.0, 1100.0]}, "total_rpm": 503.32699784791026, "num_requests": 251}}, "failures": {"POST_/post": {"method": "POST", "name": "/post", "error": "HTTPError('404 Client Error: Not Found for url: https://example.com/post',)", "occurrences": 251}}, "num_requests": 466, "num_requests_fail": 251, "total_lambda_execution_time": 30118, "lambda_invocations": 2, "approximate_cost": 6.3008e-05, "request_fail_ratio": 0.5386266094420601, "invocation_error_ratio": 0.0, "locust_settings": {"locustfile": "locustfile_example.py", "host": "https://example.com", "num_users": 2, "spawn_rate": 10, "run_time": "15s"}, "lambda_function_name": "lambda_locust", "threads": 1, "ramp_time": 0, "time_limit": 15}
[2020-06-28 19:58:54,142] pudli/INFO/root: ===========================================================================================================================
[2020-06-28 19:58:54,143] pudli/INFO/root: TYPE    NAME                                                #REQUESTS    MEDIAN   AVERAGE       MIN       MAX  #REQS/SEC
Scratch
[2020-06-28 19:58:54,143] pudli/INFO/root: ===========================================================================================================================
[2020-06-28 19:58:54,143] pudli/INFO/root: GET     /                                                         215      92.0     91.08     84.49    114.66       7.19
[2020-06-28 19:58:54,144] pudli/INFO/root: POST    /post                                                     251     150.0    157.74    142.16   1087.47       8.39
[2020-06-28 19:58:54,144] pudli/INFO/root: Exiting...

Occasional errors

  • ERROR : xxxxx-3f19-11e7-a1d1-xxxxxxx Process exited before completing request"
    • SOLUTION: Double the size of the memory for the function.

invokust's People

Contributors

csillab avatar dependabot[bot] avatar emintham avatar futuresharks avatar hughzurname avatar kj2797 avatar ktrueda avatar luzfcb avatar m1strall avatar mumerali avatar niraj-fonseka avatar roelschr avatar rondineli avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

invokust's Issues

Updating Locsut version

Hi, thank you for this framework. I was wondering if you can update the version of locsut please? Thank you!

AWS deployment fails

Hi mates,

Following the readme tutorial to deploy on AWS lambda I got the following error when I'm trying to invoke

[ERROR] 2020-07-14T18:04:00.80Z bf187cde-4c12-46ed-b185-b0be7fe04c1f Locust exception TypeError("create_settings() got an unexpected keyword argument 'num_requests'")

Any idea?

Implementation of the called lambda when running parallel load test

I'm trying to understand the example provided at the bottom of the Readme about running the load test in parallel.

Unfortunately I do not fully grasp how the called lambda_locust function should look like.

def handler(event=None):
 # create settings from payload 
 settings = invokust.create_settings(event )
 loadtest = invokust.LocustLoadTest(settings)
 loadtest.run()

Should it just accept the JSON payload and run a standard load test ? Or do I have to change the settings according to the number of threads passed to the LambdaLoadTest class?

Why are these settings not to be changed?

# Default settings that are not to be changed
    settings.no_web = True
    settings.master = False
    settings.show_task_ratio_json = False
    settings.list_commands = False
    settings.loglevel = 'INFO'
    settings.slave = False
    settings.only_summary = True
    settings.logfile = None
    settings.show_task_ratio = False
    settings.print_stats = False

In particular it would be useful to be able to deploy AWS lambda slaves all communicating with a master host.

Num of request being made doesnt match with the settings.

Hi,

I was running my invokust with the below settings,

settings = invokust.create_settings(
    classes=[WebsiteUser],
    host='https://google.com',
    num_clients=1,
    hatch_rate=1,
    run_time='10s'
)

WIth the above settings i should see 10 requests being made, as the hatch_rate is 1 and time limit is 10s.

But i see 51 requests being made in this 10s duration.

{
  "requests": {
    "GET_/": {
      "request_type": "GET",
      "num_requests": 51,
      "min_response_time": 139.55307006835938,
      "median_response_time": 180,

No results when using LambdaLoadTest

Hi,

I'm using the following code to trigger the load test:

import logging
import os
import json
from invokust.aws_lambda import LambdaLoadTest, results_aggregator

if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO)
    run_time = os.environ.get("LOCUST_RUN_TIME")
    threads = max(1, int(os.environ.get("LOCUST_NUM_USERS")) / 10)
    load_test = LambdaLoadTest(
        lambda_function_name="load-test",
        threads=threads,
        ramp_time=0,
        time_limit=30,
        lambda_payload={"run_time": run_time}
    )
    load_test.run()
    logging.info(load_test.get_summary_stats())
    logging.info(json.dumps(results_aggregator(load_test.get_locust_results()), indent=4))

load-test lambda is very simple (128MB memory and timeout of 15mins), hitting one endpoint every 5s.

For 10m and 5 users and I get:

[2021-10-06 13:21:43,035] cedb38dd3bda/INFO/root: Waiting for all Lambdas to return. This may take up to 10m.
[2021-10-06 13:37:23,942] cedb38dd3bda/CRITICAL/root: Lambda invocation failed: ConnectionClosedError('Connection was closed before we received a valid response from endpoint URL: "https://lambda.eu-central-1.amazonaws.com/2015-03-31/functions/load-test/invocations".')
[2021-10-06 13:37:25,950] cedb38dd3bda/INFO/root: thread finished
[2021-10-06 13:37:26,037] cedb38dd3bda/INFO/root: {'lambda_invocation_count': 0, 'total_lambda_execution_time': 0, 'requests_total': 0, 'request_fail_ratio': 0, 'invocation_error_ratio': 0}
[2021-10-06 13:37:26,041] cedb38dd3bda/INFO/root: {
    "requests": {},
    "failures": {},
    "num_requests": 0,
    "num_requests_fail": 0,
    "total_lambda_execution_time": 0,
    "lambda_invocations": 0,
    "approximate_cost": 0.0
}

Semantic versioning

Would you consider adopting semantic versioning?

I have seen your the release version was bumped up from 0.61 to 0.7 yesterday.

Chronologically 0.7 is newer than 0.61, but mathematically isn't. While I understand the logic behind it, it will cause problems with dependency management.

I'd like to specify the requirements as invokust>=0.7, this would not change as 0.61 is larger as pip interprets it.

version 0.75 missing for Pypi

HI, are you planning to publish 0.75 to Pypi?
Currently, it seems that only the 0.73 is published, the 0.73 is linked to an old version of locust.
Thank you

AttributeError: 'StatsError' object has no attribute 'to_dict'

Running into an error AttributeError: 'StatsError' object has no attribute 'to_dict' when there are failures present in the load test. Coming from locust_stats = loadtest.stats() Any ideas? Thanks!

def lambda_handler(event, context=None):
    try:
        if event:
            settings = create_settings(**event)
        else:
            settings = create_settings(from_environment=True)

        loadtest = LocustLoadTest(settings)
        loadtest.run()
    except Exception as e:
        logging.error("Locust exception {0}".format(repr(e)))

    else:
        locust_stats = loadtest.stats()
        lambda_runtime_info = get_lambda_runtime_info(context)
        loadtest_results = locust_stats.copy()
        loadtest_results.update(lambda_runtime_info)
        json_results = json.dumps(loadtest_results)

        logging.info(json_results)
        return json_results

Version parity with Locust 0.11?

It now runs with locust 0.9, but locust 0.11 is already out and it does not work with it.
Is it possible to bring it to support locust 0.11?

LoadTestShape

Can you run a LoadTestShape class in lambda? Specifically a case for ramping up and ramping down users at different stages?

Locust exception ImportError("cannot import name 'User'",)

Locust exception ImportError("cannot import name 'User'",)
END RequestId: 0fec6b92-8c39-42a7-8c14-16629a464c67

NOTE: when i used the import with HttpUser, it gives the same error.
I'm trying to use the invokust with AWS Lambda, but no luck so far, below are the steps that i followed,

  • installing invokust in to the python target folder (sudo pip3 install invokust --target=python-packages)
  • Created the locustfile and lambda_locust(handler).
  • Created a zip with all 3 files (zip -q -r lambda_locust.zip lambda_locust.py princess_locustfile.py python-packages )
  • Created the lambda
  • and invoked from the console.

segmentation fault (core dumped)

Hi, I followed the instructions under Running Locust on AWS Lambda but all I get is this error when I run invokr.py:

[2022-01-05 07:33:57,245] LM-C02C775WMD6R/ERROR/invokust.aws_lambda.lambda_load_test: error Unhandled: b'{"errorMessage":"RequestId: bb804730-df31-47d0-bc5f-ac734d0aa70e Error: Runtime exited with error: signal: segmentation fault (core dumped)","errorType":"Runtime.ExitError"}'

Any pointers what I might be doing wrong? I'm building the Lambda package on MacOS Big Sur using these commands:

docker run -it --volume=$PWD:/temp python:3.6 bash -c "pip install /temp --target=/temp/python-packages"
zip -q -r lambda_locust.zip lambda_locust.py locustfile_example.py python-packages
aws lambda create-function --function-name lambda_locust --timeout 300 --runtime python3.6 --role arn:aws:iam::XXXXXX --handler lambda_locust.handler --zip-file fileb://lambda_locust.zip

Does add_listener work?

@events.init.add_listener
def on_locust_init(environment, **_kwargs):

invokust is a breakthrough.
But, I couldn't get add_listner to work.

Negative execution time

Hi,

I'm testing invokust locally with localstack, and haven't deployed to AWS yet.
Everything works well, but I'm getting a negative execution time.

This is a test result; the key total_lambda_execution_time is assigned to this negative value: -582398. It should probably be 15.6032865047 (1663692383.5552292 - 1663692367.9519427), which is consistent with the duration I set for this test (15s).

{
  "summary_stats":{
    "lambda_invocation_count":1,
    "total_lambda_execution_time":-582398,
    "requests_total":1392,
    "request_fail_ratio":0.0,
    "invocation_error_ratio":0.0
  },
  "results":[
    {
      "requests":{
        "GET_/":{
          "request_type":"GET",
          "num_requests":1392,
          "min_response_time":716.8549480848014,
          "median_response_time":2300.0,
          "avg_response_time":3316.3983788552537,
          "max_response_time":14563.939598971047,
          "response_times":{...},
          "response_time_percentiles":{...},
          "total_rps":93.70657030509588,
          "total_rpm":5622.3942183057525
        }
      },
      "failures":{},
      "num_requests":1392,
      "num_requests_fail":0,
      "start_time":1663692367.9519427,
      "end_time":1663692383.5552292,
      "remaining_time":882398,
      "function_name":"locust-function",
      "function_version":"$LATEST",
      "invoked_function_arn":"arn:aws:lambda:us-east-2:000000000000:function:locust-function",
      "memory_limit":"1536",
      "aws_request_id":"2483a0c5-3c47-150a-6b27-c9535e8eeacb",
      "log_group_name":"/aws/lambda/locust-function",
      "log_stream_name":"2022/09/20/[$LATEST]4aff2d740c665b04f425e1c3239ea985"
    }
  ]
}

This is the code I'm using to launch the test:

        load_test: LambdaLoadTest = LambdaLoadTest(
            lambda_function_name=locust_lambda_name,
            threads=threads,
            ramp_time=0,
            time_limit=duration,
            lambda_payload={
                "locust_modules": modules,
                "host": host,
                "num_users": users,
                "spawn_rate": spawn_rate,
                "run_time": f"{duration}s",
            },
        )
        load_test.run()
        result: TestResult = TestResult(
            summary_stats=load_test.get_summary_stats(),
            results=load_test.get_locust_results(),
        )

Error invoking lambda following quickstart

Running py3.8, I was able to create a lambda not not invoke it

Getting usage errrors locally

`
aws lambda invoke --function-name lambda_locust --invocation-type RequestResponse --payload '{"locustfile": "my_locustfile.py", "host":"https://miamioh-gradify.com", "num_requests":"20", "num_clients": "1", "hatch_rate": "1", "run_time":"3m"}' output.txt

Unknown options: num_requests:20,, num_clients:, 1,, hatch_rate:, 1,, run_time:3m}', output.txt, host:https://miamioh-gradify.com,`

Same via aws-shell

Tried creating test in Lambda Console.

{
"locustfile": "my_locustfile.py",
"host": "https://miamioh-gradify.com",
"num_requests": "20",
"num_clients": "1",
"hatch_rate": "1",
"run_time": "3m"
}

but got
{
"errorMessage": "Unable to import module 'lambda_locust': No module named 'gevent.__hub_local'",
"errorType": "Runtime.ImportModuleError"
}

AWS Lambda deployment with function layer

Hi,

I created a lambda python function with a lambda runtime environment set to python 3.6. I made a python 3.6 layer where I installed invokust and added it to the lambda function.

The code in my lambda function is:

import json
from invokust.aws_lambda import get_lambda_runtime_info

def lambda_handler(event, context):
# TODO implement
return {
'statusCode': 200,
'body': json.dumps('Hello from Lambda!')
}

When I execute it, I get the following error:

Response
{
"errorMessage": "module initialization error"
}

If I remove the invokust import, everything works fine. Does anybody have an idea how to fix this?

The command used to create the zip package for the lambda layer is: pip3 install --platform manylinux2014_x86_64 --target=python --implementation cp --python 3.6 --only-binary=:all: --upgrade invokust

After that, I zipped the python folder and uploaded it as a lambda layer.

gevent error when attempting to invoke lambda

Hi,

I'm working my way through the instructions in the README for running the sample code on AWS Lambda. I've worked my way through a variety of errors, but have bumped up on one that has me stymied. I'm hoping you can help.

I'm working on a MacBook Pro, running Catalina (10.15.7), so I'm using docker to compile the python package, as described in the README:

docker run -it --volume=$PWD:/temp python:3.6 bash -c "pip install /temp --target=/temp/python-packages"

Then I'm zipping and creating the lambda, no problem.

zip -q -r lambda_locust.zip lambda_locust.py locustfile_example.py python-packages

aws --profile sandbox lambda create-function --function-name lambda_locust --timeout 300 --memory-size 256 --runtime python3.6 --role arn:aws:iam::039069484348:role/service-role/sdg-test-function-role-54kv5be3 --handler lambda_locust.handler --zip-file fileb://lambda_locust.zip

As an aside, you have a note in your TODO.md about Process exited before completing request errors. I was getting that too, but I fixed it by doubling the memory size. Also, that role in my create-function command is a basic lambda execution role.

Finally, invoking the lambda gets me this:

(invokust) SGALLIVER-MBP:invokust sgalliver$ aws --profile sandbox lambda invoke --function-name lambda_locust --invocation-type RequestResponse --payload '{"locustfile": "locustfile_example.py", "host":"http://www.google.com", "num_users": "1", "spawn_rate": "1", "run_time":"1m"}' output.txt --log-type Tail --query 'LogResult' --output text | base64 -d
START RequestId: c8d8bbbf-4e5c-4f20-bd56-f00c3bf000eb Version: $LATEST
[2021-01-13 17:47:35,008] 169.254.244.125/ERROR/root: Locust exception ImportError("/lib64/libc.so.6: version `GLIBC_2.28' not found (required by python-packages/gevent/libuv/_corecffi.abi3.so)",)
END RequestId: c8d8bbbf-4e5c-4f20-bd56-f00c3bf000eb
REPORT RequestId: c8d8bbbf-4e5c-4f20-bd56-f00c3bf000eb	Duration: 3.73 ms	Billed Duration: 4 ms	Memory Size: 256 MB	Max Memory Used: 121 MB	Init Duration: 1272.77 ms

Any clues about that import error? I did some poking around and it appears that gevent needs to be compiled on an Amazon Linux instance. I suppose I could go spin up an EC2 instance, but I figured the README would have mentioned it if that were necessary. So I thought I'd ask if you have hit this error and how you solved it, before I go running down the EC2 rabbithole.

Many thanks!

Use invokust with odoo

Hey Guys,
I have a question regarding your Locust-wrapper. Is it possible to load test Odoo applications over jsonrpc ?
I currently have the problem that my Locust tests are running but not returning any test results on my CLI. If someone knows something about this just hit me up!

module 'invokust' has no attribute 'create_settings'

Hi, I am trying to run the invokust file locally, but I encounter the module 'invokust' has no attribute 'create_settings' error on the settings = invokust.create_settings( line.
I am using the second example in the readme against my own endpoints. Am I not able to run this locally on a windows machine?

import invokust

from locust import HttpLocust, TaskSet, task

class Task(TaskSet):
    @task()
    def get_home_page(self):
        '''
        Gets /
        '''
        self.client.get("/")

class WebsiteUser(HttpLocust):
    task_set = Task

settings = invokust.create_settings(
    classes=[WebsiteUser],
    host='http://example.com',
    num_requests=10,
    num_clients=1,
    hatch_rate=1
    )

loadtest = invokust.LocustLoadTest(settings)
loadtest.run()
loadtest.stats()

Unable to use invokust. locust version == 1.3.0, locustio==0.13.5, invokust==0.73

I have a following directory structure.

Screenshot 2020-12-11 at 10 33 25 PM

myapp.py is a simple flask application running locally
locustfile.py is my locust file
run_locust.py is where i have put the invokust code.

All 3 files attached.
Files.zip

When i run run_locust.py like this:

python run_locust.py, I keep getting this error

/Users/kapilmathur/virtual_envs/audit_trail_auto/bin/python3.8 /Users/kapilmathur/repos/Load-tools/Load-test/run_locust.py
Traceback (most recent call last):
  File "/Users/kapilmathur/repos/Load-tools/Load-test/run_locust.py", line 8, in <module>
    settings = create_settings(
  File "/Users/kapilmathur/virtual_envs/audit_trail_auto/lib/python3.8/site-packages/invokust/settings.py", line 68, in create_settings
    docstring, classes = load_locustfile(settings.locustfile)
ValueError: too many values to unpack (expected 2)

Process finished with exit code 1

Can you plz help with the issue and tell me if i am using it correctly. is there some version dependency/conflict I am hitting ?

Gevent dependency error when running through AWS

I get this error believe whenever I try to run on zipped dependencies on AWS.

{
"errorMessage": "Unable to import module 'lambda_locust': No module named 'gevent.__hub_local'",
"errorType": "Runtime.ImportModuleError"
}

Packaging code with with in Makefile:
PYTHON_VERSION=3.7
ZIP_PATH=$(abspath ./build.zip)

zip:
$(eval VENV=$(shell pipenv --venv))
cd ${VENV}/lib/python${PYTHON_VERSION}/site-packages/ && zip -r ${ZIP_FILE} .
zip -r ${ZIP_PATH} . -x .git

I've gotten my handler paired down to only printing the event, but it fails at importing dependencies:

import sys
import os
sys.path.insert(0, "python-packages")
import logging
import json

from invokust.aws_lambda import get_lambda_runtime_info
from invokust import LocustLoadTest, create_settings

logging.basicConfig(level=logging.INFO)

def handler(event=None, context=None):
print(str(event))
# try:
# if event:
# settings = create_settings(**event)
# else:
# settings = create_settings(from_environment=True)
#
# loadtest = LocustLoadTest(settings)
# loadtest.run()
#
# except Exception as e:
# logging.error("Locust exception {0}".format(repr(e)))
#
# else:
# locust_stats = loadtest.stats()
# lambda_runtime_info = get_lambda_runtime_info(context)
# loadtest_results = locust_stats.copy()
# loadtest_results.update(lambda_runtime_info)
# json_results = json.dumps(loadtest_results)
#
# logging.info(json_results)
# return json_results

Can you output CSV or HTML reports?

We've just successfully run our first load test with invokust.
Just wondering if there is a way in the config to output CSV or locust HTML reports?

Change license to be compatible with Locust

Hi.

I really like the approach you've taken here.
Would you be willing to change the license to a license that is compatible with locustio?

As it stands it's not possible to use this code as the basis of something that I can submit as a PR to locust with.

Thanks

Unable to import module 'lambda_locust': No module named 'greenlet'

Running the default example results in
Unable to import module 'lambda_locust': No module named 'greenlet'

I have the standard example files (host changed) and have ran
pip3 install invokust --target=python-packages
and zipped them all together

I've included a tree of the files it downloads which end up in the zip.

file.txt

Any idea on how to solve this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.