-
Notifications
You must be signed in to change notification settings - Fork 33
How to Run Load and Regression Locust Tests
Follow this runbook to run the regression and load test suites either locally or against a particular BFD Server host.
Note that these steps are for running locust locally; this is not usually necessary, as we have a Jenkins job for running both the server load and regression suites:
https://jenkins-east.cloud.cms.gov/bfd/job/bfd-run-server-load/build?delay=0sec
Using the tag parameter, tests can be included or excluded to create a desired suite. Adjusting the parameters here can be used to tune the test to the usecase desired. (Adding no tag params in the boxes will run against all test cases.)
Note that when using the above jobs, it's a good idea to build the image for them first to capture any changes since the last build. This is not done automatically as part of the Jenkins run job:
https://jenkins-east.cloud.cms.gov/bfd/job/bfd-server-load-build/
https://jenkins-east.cloud.cms.gov/bfd/job/bfd-server-regression-build/
If you still want/need to run locust locally (say for development purposes or watching the runtime) follow the instructions below:
-
How to Run the Regression and Load Test Suites
- Glossary
- FAQ
- Prerequisites
-
Instructions
- How to Run the Regression Suite Locally Against a Local BFD Server
- How to Run the Regression Suite Locally Against any BFD Server SDLC Environment
- How to Run the Regression Suite On a Detached Instance Against any BFD Server SDLC Environment
- How to Run a Scaling Load Test Using the
bfd-run-server-load
Jenkins Job - How to Run a Static Load Test Using the
bfd-run-server-load
Jenkins Job
Term | Definition |
---|---|
Locust | A load testing library that allows for performance tests to be written in Python |
I specified --host
with a valid URL like so example.com
, but my tests aren't running. What am I doing wrong?
Firstly, --host
is a default Locust argument that is a bit of a misnomer; valid
--host
values must include the protocol (i.e. https
), hostname (i.e. example.com
) and,
optionally, the port in the following format: PROTOCOL://HOSTNAME:PORT
. Be aware that Locust
does not trim trailing slashes after the PORT
; however, we have implemented a check for trailing
slashes in --host
and remove them ourselves. So, it is recommended that --host
does not include
any trailing characters after PORT
as well.
- A global installation of Python 3
- An installation of the AWS CLI that is configured properly for access to the BFD/CMS AWS account
- An installation of
jq
- A tool for creating virtual environments (
virtualenv
s) such asvirtualenv
orpew
- This runbook will assume you are using
pew
as it is fairly simple to work with and has a relatively intuitive UX
- This runbook will assume you are using
- Access to AWS
- Access to the CMS VPN
Note: This runbook assumes you have cloned the
beneficiary-fhir-data
repository locally and are relatively comfortable with the command-line (CLI).
Note: These steps assume you have followed the top-level README.md's steps for running BFD locally (including running the database using PostgreSQL in Docker).
Additionally, it is highly recommended to read the entirety of the
locust_test
README.md
before continuing.
-
Navigate to the root of the
beneficiary-fhir-data
repository in any terminal application -
From the root of the
beneficiary-fhir-data
repository, setBFD_ROOT
to the current working directory:BFD_ROOT=$(pwd)
-
Navigate to
apps/utils/locust_tests
:cd $BFD_ROOT/apps/utils/locust_tests
-
If not already created, create a new virtual environment for
locust_tests
:pew new -p 3.8 -a . -r requirements.txt py3.8__locust_tests
- This will create a new virtual environment using Python 3.8 named
py3.8__locust_tests
and will automatically install the necessary Python dependencies to run the various Locust test suites in thelocust_tests
directory. It will also associate this new virtual environment to the$BFD_ROOT/apps/utils/locust_tests
directory
- This will create a new virtual environment using Python 3.8 named
-
Open a new subshell that uses the
py3.8__locust_tests
virtual environment:pew workon py3.8__locust_tests
-
Set
CLIENT_CERT_PATH
to the unsecured certificate available in the repository:CLIENT_CERT_PATH=$BFD_ROOT/apps/bfd-server/dev/ssl-stores/client-unsecured.pem
-
Set
DATABASE_CONSTR
to the database connection string pointing to your locally running PostgreSQL instance:DATABASE_CONSTR="postgres://bfd:InsecureLocalDev@localhost:5432/fhirdb"
- Running the above command assumes you have followed the README.md's "Native Setup" section and are running your local PostgreSQL instance in a Docker container with the defaults provided in that section. If you are not, you will need to change the connection string above to point to your local BFD database instance
-
Run the Locust tests using
locust
. Replace<NUM_USERS>
with the number of simulated users (amount of load) to run with,<SPAWN_RATE>
with the rate at which you would like the simulated users to spawn per-second, and<RUNTIME>
with the amount of time you would like to run the performance tests for once all users have spawned (you can specify runtime like "10m30s" or "30s"):locust -f v2/regression_suite.py \ --users=<NUM_USERS> \ --host="localhost:$BFD_PORT" \ --spawn-rate=<SPAWN_RATE> \ --spawned-runtime="<RUNTIME>" \ --client-cert-path="$CLIENT_CERT_PATH" \ --database-connection-string="$DATABASE_CONSTR" --headless
-
Once the regression tests have ended, Locust will print a summary table with the performance statistics of the previous run for each endpoint as well as an aggregated total of all endpoint performance
Note: These steps assume you will be testing against the
TEST
environment, but you are able to test against all SDLC environments following these instructions.Additionally, it is highly recommended to read the entirety of the
locust_test
README.md
before continuing.
-
Set
BFD_ENV
to the environment you want to test:BFD_ENV="test"
- Other valid values are
"prod-sbx"
and"prod"
, however it is unlikely you will need to run the regression suite manually against environments other thanTEST
- Other valid values are
-
Navigate to the root of the
beneficiary-fhir-data
repository in any terminal application -
From the root of the
beneficiary-fhir-data
repository, setBFD_ROOT
to the current working directory:BFD_ROOT=$(pwd)
-
Navigate to
apps/utils/locust_tests
:cd $BFD_ROOT/apps/utils/locust_tests
-
If not already created, create a new virtual environment for
locust_tests
:pew new -p 3.8 -a . -r requirements.txt py3.8__locust_tests
- This will create a new virtual environment using Python 3.8 named
py3.8__locust_tests
and will automatically install the necessary Python dependencies to run the various Locust test suites in thelocust_tests
directory. It will also associate this new virtual environment to the$BFD_ROOT/apps/utils/locust_tests
directory
- This will create a new virtual environment using Python 3.8 named
-
Open a new subshell that uses the
py3.8__locust_tests
virtual environment:pew workon py3.8__locust_tests
-
Ensure your AWS credentials are valid
-
Ensure you are connected to the CMS VPN
-
Download and decrypt the testing certificate from SSM and store it to a local file:
aws ssm get-parameter --name "/bfd/$BFD_ENV/server/sensitive/test_client_key" \ --region "us-east-1" \ --with-decryption | jq -r '.Parameter.Value' > $HOME/bfd-test-cert.pem aws ssm get-parameter --name "/bfd/$BFD_ENV/server/sensitive/test_client_cert" \ --region "us-east-1" \ --with-decryption | jq -r '.Parameter.Value' >> $HOME/bfd-test-cert.pem
- Running the above commands assume you have appropriate permissions to read and decrypt sensitive SSM parameters in the environment under test
-
Set
CLIENT_CERT_PATH
to the downloaded testing certificate from the previous step:CLIENT_CERT_PATH=$HOME/bfd-test-cert.pem
-
Set
DATABASE_CONSTR
to the database connection string for the reader endpoint of the environment under test:DB_CLUSTER_ID=$(aws ssm get-parameter --name "/bfd/$BFD_ENV/common/nonsensitive/rds_cluster_identifier" \ --region "us-east-1" | jq -r '.Parameter.Value') DB_USERNAME=$(aws ssm get-parameter --name "/bfd/$BFD_ENV/server/sensitive/data_server_db_username" \ --with-decryption \ --region "us-east-1" | jq -r '.Parameter.Value') DB_RAW_PASSWORD=$(aws ssm get-parameter --name "/bfd/$BFD_ENV/server/sensitive/data_server_db_password" \ --with-decryption \ --region "us-east-1" | jq -r '.Parameter.Value') DB_PASSWORD=$(printf %s "$DB_RAW_PASSWORD" | jq -sRr @uri) DB_READER_URI=$(aws rds describe-db-clusters --db-cluster-identifier "$DB_CLUSTER_ID" \ --region "us-east-1" | jq -r '.DBClusters[0].ReaderEndpoint') DATABASE_CONSTR="postgres://$DB_USERNAME:$DB_PASSWORD@$DB_READER_URI:5432/fhirdb"
- Running the above commands assume you have appropriate permissions to read and decrypt sensitive SSM parameters in the environment under test
-
Run the Locust tests using
locust
. Replace<NUM_USERS>
with the number of simulated users (amount of load) to run with,<SPAWN_RATE>
with the rate at which you would like the simulated users to spawn per-second, and<RUNTIME>
with the amount of time you would like to run the performance tests for once all users have spawned (you can specify runtime like "10m30s" or "30s"):locust -f v2/regression_suite.py \ --users=<NUM_USERS> \ --host="https://$BFD_ENV.bfd.cms.gov" \ --spawn-rate=<SPAWN_RATE> \ --spawned-runtime="<RUNTIME>" \ --client-cert-path="$CLIENT_CERT_PATH" \ --database-connection-string="$DATABASE_CONSTR" --headless
- Note that
--host
can be anything (including the IP address of another instance that you would like to target specifically). However, if you are targeting a particular environment, you should stick with only testing instances under that environment (or the default provided here)
- Note that
-
Once the regression tests have ended, Locust will print a summary table with the performance statistics of the previous run for each endpoint as well as an aggregated total of all endpoint performance
-
Delete the
bfd-test-cert.pem
:rm -f $CLIENT_CERT_PATH
Note: These steps assume you will be testing against the
TEST
environment, but you are able to test against all SDLC environments following these instructions.Additionally, it is highly recommended to read the entirety of the
locust_test
README.md
before continuing.
-
First, detach an instance from the desired environment under test's auto-scaling group:
- Go to the AWS website and sign-in
- Click Services > EC2
- Click Auto scaling groups
- Click an active group corresponding to the desired environment under test within this list
- I.e. if
TEST
is the desired environment, click onbfd-test-fhir...
- I.e. if
- In the Details area below the node you clicked, click the Instance Management tab
- Pick one of the instances here using the checkbox on the left
- In the actions dropdown, click Detach
- In the popup, check the Add a new instance to the Auto Scaling group to balance the load checkbox to add a new instance in its place
- Confirm the detachment by clicking Detach instance
- In the list, the detached instance will still exist in the group; open the detached instance in a new tab to keep track of it
- Go to Services > EC2 and click Instances
- Find the detached instance by comparing its ID in the tab you opened against the ID in the list
- Click the Edit button near the ID of the detached instance and rename it something that indicates your name so the instance is marked as yours for others information
- Click on the newly-created Instance ID to open a details page
- Copy the private IP address from "Private IPv4 addresses"
-
Ensure you are connected to the CMS VPN
-
SSH into the detached instance using the private IP address copied from the previous step:
ssh -i <YOUR PRIVATE KEY HERE> <YOUR USER HERE>@<DETACHED IP ADDRESS HERE>
-
Become the
root
user on the detached instance:sudo su
- As the
root
user you are able to do many dangerous things, especially if you are connected to a detached instance fromPROD-SBX
orPROD
. Be very careful while logged-in as theroot
user!
- As the
-
Set
BFD_ENV
to the environment under test:BFD_ENV="test"
-
Navigate to the root of the
beneficiary-fhir-data
repository in any terminal application- For detached instances, this will be at
/beneficiary-fhir-data
- For detached instances, this will be at
-
From the root of the
beneficiary-fhir-data
repository, setBFD_ROOT
to the current working directory:BFD_ROOT=$(pwd)
-
Navigate to
apps/utils/locust_tests
:cd $BFD_ROOT/apps/utils/locust_tests
-
Install the Python dependencies necessary to run the regression suite:
pip3 install -r requirements.txt
- The instance comes with an installation of Python 3, and since we will be destroying the instance after running the regression suite we do not need to use virtual environments
-
Download and decrypt the testing certificate from SSM and store it to a local file:
aws ssm get-parameter --name "/bfd/$BFD_ENV/server/sensitive/test_client_key" \ --region "us-east-1" \ --with-decryption | jq -r '.Parameter.Value' > $BFD_ROOT/bfd-test-cert.pem aws ssm get-parameter --name "/bfd/$BFD_ENV/server/sensitive/test_client_cert" \ --region "us-east-1" \ --with-decryption | jq -r '.Parameter.Value' >> $BFD_ROOT/bfd-test-cert.pem
-
Running the above commands assume you have appropriate permissions to read and decrypt sensitive SSM parameters in the environment under test
-
Set
CLIENT_CERT_PATH
to the testing certificate from the previous step:CLIENT_CERT_PATH=$BFD_ROOT/bfd-test-cert.pem
-
Set
DATABASE_CONSTR
to the database connection string for the reader endpoint of the environment under test:DB_CLUSTER_ID=$(aws ssm get-parameter --name "/bfd/$BFD_ENV/common/nonsensitive/rds_cluster_identifier" \ --region "us-east-1" | jq -r '.Parameter.Value') DB_USERNAME=$(aws ssm get-parameter --name "/bfd/$BFD_ENV/server/sensitive/data_server_db_username" \ --with-decryption \ --region "us-east-1" | jq -r '.Parameter.Value') DB_RAW_PASSWORD=$(aws ssm get-parameter --name "/bfd/$BFD_ENV/server/sensitive/data_server_db_password" \ --with-decryption \ --region "us-east-1" | jq -r '.Parameter.Value') DB_PASSWORD=$(printf %s "$DB_RAW_PASSWORD" | jq -sRr @uri) DB_READER_URI=$(aws rds describe-db-clusters --db-cluster-identifier "$DB_CLUSTER_ID" \ --region "us-east-1" | jq -r '.DBClusters[0].ReaderEndpoint') DATABASE_CONSTR="postgres://$DB_USERNAME:$DB_PASSWORD@$DB_READER_URI:5432/fhirdb"
- Running the above commands assume you have appropriate permissions to read and decrypt sensitive SSM parameters in the environment under test
-
Run the Locust tests using
locust
. Replace<NUM_USERS>
with the number of simulated users (amount of load) to run with,<SPAWN_RATE>
with the rate at which you would like the simulated users to spawn per-second, and<RUNTIME>
with the amount of time you would like to run the performance tests for once all users have spawned (you can specify runtime like "10m30s" or "30s"):locust -f v2/regression_suite.py \ --users=<NUM_USERS> \ --host="https://$BFD_ENV.bfd.cms.gov" \ --spawn-rate=<SPAWN_RATE> \ --spawned-runtime="<RUNTIME>" \ --client-cert-path="$CLIENT_CERT_PATH" \ --database-connection-string="$DATABASE_CONSTR" --headless
- Note that
--host
can be anything (including the IP address of another instance that you would like to target specifically). However, if you are targeting a particular environment and have detached an instance from that environment's ASG, you should stick with only testing instances under that environment (or the default provided here)
- Note that
-
Once the regression tests have ended, Locust will print a summary table with the performance statistics of the previous run for each endpoint as well as an aggregated total of all endpoint performance
-
Delete the
bfd-test-cert.pem
:rm -f $CLIENT_CERT_PATH
-
In your web browser, navigate back to AWS and sign-in (if necessary)
-
Navigate to Services > EC2
-
Navigate to Instances in the navigation bar on the left side
-
Find the detached instance by searching for its name or Instance ID
-
Select the checkbox to the left of the name of the detached instance
-
Click on the "Instance state" dropdown in the top right of the screen
-
Select "Terminate instance" and accept any dialogs that appear
-
Ensure you are connected to the CMS VPN
-
Navigate to the Jenkins CloudBees instance in your web browser and sign-in
-
From the main page, select "bfd". A list of jobs should load
-
From this list of jobs, click on "bfd-run-server-load". A new page should load showing the "Stage View" and a list of actions on the left side of the screen
-
Click on "Build with Parameters" on the left side of the screen. A new page should load showing a variety of input fields
-
Choose the desired SDLC environment to load test from the "ENVIRONMENT" dropdown list
-
Adjust the default parameters according to the desired load test. For this particular case, it is assumed the desired load test is to continuously ramp-up load until a scaling event occurs and so the defaults can be used
-
Click "Build" at the bottom of the page. The page from Step #4 should load again, however an in-progress build should appear in the "Build History" list on the left side of the screen
-
Click on the build number of the in-progress build. A new page should load showing an overview of the current build
-
Click on "Console Output" on the left side of the screen. A new page should load showing realtime log output from the job
-
Monitor the log output until the following prompt appears in the output:
Once the run is finished, click either Abort or Proceed to cleanup the test Proceed or Abort
-
Scroll up in the log output and find the line starting with:
aws_instance.this[0]: Creation complete after...
-
Note the instance ID within square brackets -- use this later to follow the log output from the controller in CloudWatch
-
In your web browser, navigate to AWS and sign-in (if necessary)
-
Navigate to Services > CloudWatch
-
Navigate to "Log groups" by clicking on the link in the navigation tree
-
Search for "server-load-controller.log" and select the corresponding log group in the SDLC environment currently under test
-
Refresh the log group until a log stream with the name of the instance ID noted down in Step 13 appears
-
Open the log stream corresponding to the instance ID noted down in Step 13
-
Monitor the log continuously by clicking "Resume" at the bottom of the log output. The log should automatically update in realtime as the load test runs. You may need to continuously scroll to view the log
-
Wait until the load tests finish running. If at anytime something goes wrong, return to the running Jenkins job and click either the "Proceed" or "Abort" prompt in the log output to immediately end the test and start cleaning up
-
Once Locust prints the summary table and has finished, indicated by the "Locust master process has stopped" message, return to the Jenkins job and click "Proceed". This will cleanup the test, destroying the controller instance and stopping any orphaned Lambda nodes
-
View the stats of the run under the following log groups (the log stream corresponding to the current run will be named according to the instance ID noted down in Step 13). Note "{ENVIRONMENT}" should be replaced with the environment under test (i.e. "test"):
- /bfd/{ENVIRONMENT}/bfd-server-load/load_exceptions.csv
- /bfd/{ENVIRONMENT}/bfd-server-load/load_failures.csv
- /bfd/{ENVIRONMENT}/bfd-server-load/load_stats.csv
- /bfd/{ENVIRONMENT}/bfd-server-load/load_stats_history.csv
-
Ensure you are connected to the CMS VPN
-
Navigate to the Jenkins CloudBees instance in your web browser and sign-in
-
From the main page, select "bfd". A list of jobs should load
-
From this list of jobs, click on "bfd-run-server-load". A new page should load showing the "Stage View" and a list of actions on the left side of the screen
-
Click on "Build with Parameters" on the left side of the screen. A new page should load showing a variety of input fields
-
Choose the desired SDLC environment to load test from the "ENVIRONMENT" dropdown list
-
Adjust the default parameters according to the desired load test. For this particular case, the default values will need to be changed:
- Set
LOCUST_TAGS
to the space-delimited list of locust tasks to run if they are annotated with ANY of the given @tag(s). Will run all tasks if not given - Set
LOCUST_EXCLUDE_TAGS
to the space-delimited list of locust tasks to exclude with ANY of the given @tag(s) - Set
INITIAL_WORKER_NODES
to the number of worker nodes/Lambdas desired in total - Set
MAX_SPAWNED_NODES
equal toINITIAL_WORKER_NODES
- Set
MAX_SPAWNED_USERS
to the desired number of simulated users in total - Note that a ratio of 10 simulated users to 1 worker node should be followed for best performance
- Set
USER_SPAWN_RATE
equal toMAX_SPAWNED_USERS
if no ramp-up is desired - Unselect
STOP_ON_SCALING
if the load test should not stop when a scaling event is encountered -- for a static test, this should probably be false - Deselect
STOP_ON_NODE_LIMIT
to ensure that the load test does not end immediately due to the node limit being hit
- Set
-
Click "Build" at the bottom of the page. The page from Step #4 should load again, however an in-progress build should appear in the "Build History" list on the left side of the screen
-
Click on the build number of the in-progress build. A new page should load showing an overview of the current build
-
Click on "Console Output" on the left side of the screen. A new page should load showing realtime log output from the job
-
Monitor the log output until the following prompt appears in the output:
Once the run is finished, click either Abort or Proceed to cleanup the test Proceed or Abort
-
Scroll up in the log output and find the line starting with:
aws_instance.this[0]: Creation complete after...
-
Note the instance ID within square brackets -- use this later to follow the log output from the controller in CloudWatch
-
In your web browser, navigate to AWS and sign-in (if necessary)
-
Navigate to Services > CloudWatch
-
Navigate to "Log groups" by clicking on the link in the navigation tree
-
Search for "server-load-controller.log" and select the corresponding log group in the SDLC environment currently under test
-
Refresh the log group until a log stream with the name of the instance ID noted down in Step 13 appears
-
Open the log stream corresponding to the instance ID noted down in Step 13
-
Monitor the log continuously by clicking "Resume" at the bottom of the log output. The log should automatically update in realtime as the load test runs. You may need to continuously scroll to view the log
-
Wait until the load tests finish running. If at anytime something goes wrong, return to the running Jenkins job and click either the "Proceed" or "Abort" prompt in the log output to immediately end the test and start cleaning up
-
Once Locust prints the summary table and has finished, indicated by the "Locust master process has stopped" message, return to the Jenkins job and click "Proceed". This will cleanup the test, destroying the controller instance and stopping any orphaned Lambda nodes
-
View the stats of the run under the following log groups (the log stream corresponding to the current run will be named according to the instance ID noted down in Step 13). Note "{ENVIRONMENT}" should be replaced with the environment under test (i.e. "test"):
- /bfd/{ENVIRONMENT}/bfd-server-load/load_exceptions.csv
- /bfd/{ENVIRONMENT}/bfd-server-load/load_failures.csv
- /bfd/{ENVIRONMENT}/bfd-server-load/load_stats.csv
- /bfd/{ENVIRONMENT}/bfd-server-load/load_stats_history.csv
- Home
- For BFD Users
- Making Requests to BFD
- API Changelog
- Migrating to V2 FAQ
- Synthetic and Synthea Data
- BFD SAMHSA Filtering