Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Locust test #257

Merged
merged 28 commits into from May 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
161ce39
Add: Locust test with arbitrary jac code.
Gorgeous-Patrick May 4, 2022
41c3596
Add: Functioning locust test file.
Gorgeous-Patrick May 6, 2022
aea900b
Add: Try to login before creating users.
Gorgeous-Patrick May 6, 2022
4fe251d
Modify: MVP Locust Test.
Gorgeous-Patrick May 10, 2022
a2c2380
Add: MVP locust test containerized
Gorgeous-Patrick May 10, 2022
1ebed35
Add: Text-segmenter action loaded
Gorgeous-Patrick May 10, 2022
5f49aab
Modify: Readme
Gorgeous-Patrick May 10, 2022
ce9f664
Modify: separate user create and the usual test program.
Gorgeous-Patrick May 12, 2022
b7470b2
Modify: Separated the test program configuration into json files.
Gorgeous-Patrick May 12, 2022
19fac51
Modify: Simplify the output.
Gorgeous-Patrick May 12, 2022
dcc95e7
Merge branch 'main' into LocustTest
Gorgeous-Patrick May 12, 2022
3ab2106
Modify: working sample code with a not working local action load now.
Gorgeous-Patrick May 13, 2022
3bbead5
Fix: the biencoder test program.
Gorgeous-Patrick May 15, 2022
8638743
Modify: the overall folder structre, deleted useless files.
Gorgeous-Patrick May 15, 2022
10e57d9
Modify: Further clarify the structure.
Gorgeous-Patrick May 15, 2022
3c6b8c4
Format: the locust test.
Gorgeous-Patrick May 16, 2022
6e83e39
Add: Minimal Viable Dockerfile
Gorgeous-Patrick May 16, 2022
e33e5f8
Add: a simple python to setup the docker containers.
Gorgeous-Patrick May 16, 2022
f648f47
Add: Multiple concurrent tests.
Gorgeous-Patrick May 16, 2022
8836952
Add: Retrieved all the necessary data.
Gorgeous-Patrick May 16, 2022
783f94b
Modify: separate test and sentinel
Gorgeous-Patrick May 16, 2022
e6b0ff0
Modify: Combined the prepare with the addjac.py
Gorgeous-Patrick May 16, 2022
6852643
Modify: Set the on exit kill function
Gorgeous-Patrick May 16, 2022
f3f9f44
format
Gorgeous-Patrick May 16, 2022
0ed37be
Modify: README
Gorgeous-Patrick May 17, 2022
e473c40
Remove: Useless files
Gorgeous-Patrick May 17, 2022
e9f5c44
Typo: 4 Locust CSV
Gorgeous-Patrick May 17, 2022
37ed869
Some updates and improvements
ypkang May 19, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions support/locust/.gitignore
@@ -0,0 +1,2 @@
__pycache__
results/
8 changes: 8 additions & 0 deletions support/locust/Dockerfile
@@ -0,0 +1,8 @@
FROM python:latest
WORKDIR /locust
EXPOSE 8089
COPY . /locust/src
COPY sample_code /locust/sample_code
RUN pip3 install locust
RUN mkdir /locust/csv
CMD locust -f /locust/src/addjac.py --headless -u $LOCUST_USER_NUMBER -r $LOCUST_SPAWN_RATE -H $LOCUST_HOST --run-time $LOCUST_DURATION --csv=csv/data
76 changes: 76 additions & 0 deletions support/locust/README.md
@@ -0,0 +1,76 @@
# Locust Load Test for JASECI
Locust is an easy-to-use, distributed, user load testing tool. It is intended for load-testing web sites (or other systems) and figuring out how many concurrent users a system can handle.

## Run Locust natively

### Install Locust
```console
pip install locust
```
### Configure the test
Create test users. This following script will prompt you for the jaseci server URL and number of test users you wish to create.
```bash
python create_users.py
```
Then create a folder in `sample_code/`. Set up a file `config.json` in the folder. Here is an example:
```json
{
"walkers" : ["init"],
"src" : "walker.jac",
"remote_actions" : ["http://flair-ner:80/"],
"local_actions" : []
}
```

`walkers` is a list of walkers that you want to call (in sequence). `src` the name of the file that contains your code. `remote_actions` should contain a list of URLs of your remote services. `local_actions` should contain a list of names of your modules.

### Run the test
The program reads the environment variable `LOCUST_TEST_SRC` for the location of the test configuration and `LOCUST_HOST` for the jaseci server URL.
```bash
LOCUST_HOST='JASECI_URL' LOCUST_TEST_SRC='sample_code/<YOUR TEST>' locust -f run_jac.py
```

Go to the link specified in console, e.x http://0.0.0.0:8089 and specify the desired number of users for the load test and initiate the test. You can also change the server URL in the web UI.

## Run Locust with docker

### Set up the environment
Install docker
```bash
pip install docker
```
Build the custom docker image
```bash
docker build -t locust-jac-test .
```
**Note** If you are testing a localhost jaseci, please make sure that your Jaseci service is exposed to `0.0.0.0` since we are going to access the service from docker, not local. To achieve that, run
```bash
kubectl port-forward <JASECI POD NAME> 8888:80 --address="0.0.0.0"
```
### Configure the tests

**Note** Please make sure that you have configured the tests properly as we did in the previous section.

Since we are not going to open a Web UI this time, we need some more information. Please give all the information in `test.json`. Here is an example
```json
{
"hostName": "http://172.17.0.1:8888",
"testName": "simple",
"testSRC": "sample_code/simple",
"userNum": 5,
"spawnRate": 1,
"duration": "10s"
}
```
`hostName` gives the URL of the host. Note that `localhost` on the host computer is mapped to `172.17.0.1` inside docker containers. `testName` is a simple name for the test. It will be included in the name of the container and the result that we retrieve. `testSRC` specifies the path to the specific test configuration. `userNum` specifies the number of users that we need to spawn in this test. `spawnRate` specfies the speed that we spawn the users (How many users created in one second). `duration` sets the time length of the test.

### Run the test
To run the test
```bash
python start_docker.py
```
All the tests will be created inside a separate docker container. The containers are named `Locust_<TESTNAME>`. All the tests should be run in parallel. When all the tests are done, the python script automatically removes and kills all the containers.

### Retrieve the test data

All available data are retrieved after you ran the script. They should be available under `results/<testName>/`. `logs.txt` is the log of the test. `data.tar` file should contain four CSV files. They are directly from locust.
20 changes: 20 additions & 0 deletions support/locust/create_users.py
@@ -0,0 +1,20 @@
import requests
import utils

targetServer = input("Target Server: ")
UserNum = int(input("Number of Users: "))

# Create all the users
for i in range(UserNum):
username = utils.gen_username(i)
password = utils.gen_password(i)
data = {
"email": username,
"password": password,
"is_activated": True,
"is_superuser": True,
}
URL = targetServer + "/user/create/"
print(data)
response = requests.post(URL, data=data)
print(response.text)
60 changes: 60 additions & 0 deletions support/locust/prepare.py
@@ -0,0 +1,60 @@
import requests
import utils
import os


TEST_PATH = os.environ.get("LOCUST_TEST_SRC", "")
HOST = os.environ.get("LOCUST_HOST", "http://localhost:8888")

# Log in as user 0, return the token
def login():
userName = utils.gen_username(0)
password = utils.gen_password(0)
response = requests.post(
HOST + "/user/token/", json={"email": userName, "password": password}
)
return response.json()["token"]


# register sentinel, return the jid
def registerSentinel(token: str):
req = {
"name": "jac_prog",
"code": utils.get_code(utils.load_config(TEST_PATH)["src"]),
}
response = requests.post(
HOST + "/js/sentinel_register",
headers={"authorization": f"Token {token}"},
json=req,
)
return response.json()[0]["jid"]


def setSentinelGlobal(token: str, snt: str):
response = requests.post(
HOST + "/js_admin/global_sentinel_set",
headers={"authorization": f"Token {token}"},
json={"snt": snt},
)


def load_actions(token: str):
for action in utils.load_config(TEST_PATH)["remote_actions"]:
response = requests.post(
HOST + "/js_admin/actions_load_remote",
headers={"authorization": f"Token {token}"},
json={"url": action},
)
for action in utils.load_config(TEST_PATH)["local_actions"]:
response = requests.post(
HOST + "/js_admin/actions_load_local",
headers={"authorization": f"Token {token}"},
json={"file": action},
)

response = requests.post(
HOST + "/js_admin/actions_list",
headers={"authorization": f"Token {token}"},
)

# print(response.text)
73 changes: 73 additions & 0 deletions support/locust/run_jac.py
@@ -0,0 +1,73 @@
from locust import task, HttpUser, SequentialTaskSet, constant, HttpUser
import os
from utils import gen_username, gen_password, load_config
import prepare

TEST_PATH = os.environ.get("LOCUST_TEST_SRC", "")
SNT = ""


def format_output(userName: str, output: str):
print(f"{userName}: {output}")


UserID = 0
actionLoaded = False


def print_response(response):
failure = False
if response.status_code != 200 and response.status_code != 201:
failure = True
success = response.json().get("success", False)
if not success:
failure = True
if failure:
print(response.text)


class SeqTask(SequentialTaskSet):
def on_start(self):
self.userName = "Not_exist" # Initialize
self.password = "Not_exist"
self.zsb_token = "None"
self.zsb_jid = "None"
global UserID
self.userName, self.password = gen_username(UserID), gen_password(UserID)
self.userID = UserID
UserID += 1

@task
def generate_userToken(self):
response = self.client.post(
"/user/token/", json={"email": self.userName, "password": self.password}
)
format_output(self.userName, response.text)
json_var = response.json()
self.user_token = json_var["token"]

@task
def walker_run(self):
for walkerName in load_config(TEST_PATH)["walkers"]:
req = {"name": walkerName, "snt": SNT}
# print(f"Walker {walkerName} running.")
response = self.client.post(
"/js/walker_run",
headers={"authorization": f"Token {self.user_token}"},
json=req,
)
print(f"Walker {walkerName} finished. {response.text}")
# print(f"Walker {walkerName} Output: {response.json()}")


class addJac(HttpUser):
host = "http://127.0.0.1:8888"
tasks = [SeqTask]
wait_time = constant(2)


token = prepare.login()
SNT = prepare.registerSentinel(token)
prepare.load_actions(token)
prepare.setSentinelGlobal(token, SNT)
print(SNT)
6 changes: 6 additions & 0 deletions support/locust/sample_code/bi_enc_test/config.json
@@ -0,0 +1,6 @@
{
"walkers" : ["init"],
"src" : "walker.jac",
"remote_actions" : ["http://bi-enc:80/"],
"local_actions" : []
}
6 changes: 6 additions & 0 deletions support/locust/sample_code/bi_enc_test/walker.jac
@@ -0,0 +1,6 @@
walker init {
can bi_enc.infer;
root {
report bi_enc.infer(contexts = ["I like the restaurant near my house!"], candidates = ["University", "restaurant", "school", "computer"], context_type = "text", candidate_type = "text");
}
}
7 changes: 7 additions & 0 deletions support/locust/sample_code/flair_test/config.json
@@ -0,0 +1,7 @@

{
"walkers" : ["init"],
"src" : "walker.jac",
"remote_actions" : ["http://flair-ner:80/"],
"local_actions" : []
}
6 changes: 6 additions & 0 deletions support/locust/sample_code/flair_test/walker.jac
@@ -0,0 +1,6 @@
walker init {
can ent_ext.entity_detection;
root {
report ent_ext.entity_detection(text = "Hello, I am from the University of Michigan!", ner_labels = ["University", "detection", "US", "Jaseci"])['entities'];
}
}
7 changes: 7 additions & 0 deletions support/locust/sample_code/flair_test_local/config.json
@@ -0,0 +1,7 @@

{
"walkers" : ["init"],
"src" : "walker.jac",
"remote_actions" : [],
"local_actions" : ["/jaseci/jaseci_kit/jaseci_kit/modules/entity_extraction/entity_extraction.py"]
}
6 changes: 6 additions & 0 deletions support/locust/sample_code/flair_test_local/walker.jac
@@ -0,0 +1,6 @@
walker init {
can ent_ext.entity_detection;
root {
report ent_ext.entity_detection(text = "Hello, I am from the University of Michigan!", ner_labels = ["University", "detection", "US", "Jaseci"])['entities'];
}
}
6 changes: 6 additions & 0 deletions support/locust/sample_code/simple/config.json
@@ -0,0 +1,6 @@
{
"walkers" : ["init"],
"remote_actions" : [],
"local_actions" : [],
"src" : "walker.jac"
}
6 changes: 6 additions & 0 deletions support/locust/sample_code/simple/walker.jac
@@ -0,0 +1,6 @@
walker init {
root {
std.out("Hello, this is from the root");
report "Test SUCCESS";
}
}