Skip to content
This repository has been archived by the owner on Feb 1, 2024. It is now read-only.

Commit

Permalink
Merge pull request #1777 from open-apparel-registry/feature/jcw/load-…
Browse files Browse the repository at this point in the history
…testing

Update tile load test script and add scripts for hompage load, facility download, and facility POST
  • Loading branch information
jwalgran committed May 20, 2022
2 parents 932ecdb + bbd1dc9 commit a4e6040
Show file tree
Hide file tree
Showing 9 changed files with 87,201 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Changed
- Use autocomplete ordered by name for admin contributors dropdown [#1848](https://github.com/open-apparel-registry/open-apparel-registry/pull/1848)
- Document parallel OGR workflow in the README [#1851](https://github.com/open-apparel-registry/open-apparel-registry/pull/1851)
- Update tile load test script and add scripts for hompage load, facility download, and facility POST [#1777](https://github.com/open-apparel-registry/open-apparel-registry/pull/1777)

### Deprecated

Expand Down
36 changes: 32 additions & 4 deletions load-tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ components necessary to execute a load test are encapsulated in this directory.
- `K6_CLOUD_TOKEN`: An Auth Token for interacting with the k6 Cloud (optional)
- `CACHE_KEY_SUFFIX`: A suffix to append in the path to ensure tile requests miss the cache (optional)
- `VU_MULTIPLER`: An integer number of parallel executions of each batch of requests
- `CLIENT_KEY`: For load tests that fetch data from the API this must be set to a string that is the same as the value in the staging app service environmant
- `FILTERS`: For the tile and facility download load tests this may be set to a string formatted like the query string filter arguments passed to the facilities api (e.g. contributors=1&&countries=CN)
- `TOKEN`: For load tests that POST data the string API token to be included with the POST.

## Running

Below is an example of how to invoke an instance of the load test with Docker
Below is an example of how to invoke an instance of the tile request load test with Docker
Compose:

```console
Expand Down Expand Up @@ -60,8 +63,8 @@ default ✓ [======================================] 10 VUs 01m38.9s/10m0s 10/
ERRO[0101] some thresholds have failed
```

To invoke an instance of the load test running with 10 times the number of
parallel requests and a random cache key suffix to avoid CloudFront
To invoke an instance of the tile request load test running with 10 times the
number of parallel requests and a random cache key suffix to avoid CloudFront

```console
VU_MULTIPLIER=10 \
Expand All @@ -70,11 +73,36 @@ docker-compose -f docker-compose.yml run --rm \
k6 run /scripts/zoom_rio_de_janerio_with_contributor_filter.js
```

To invoke an instance of the load test streaming output to the k6 Cloud:
To invoke an instance of the tile request load test streaming output to the k6 Cloud:

```console
$ export K6_CLOUD_TOKEN=...
$ docker-compose \
-f docker-compose.yml \
run --rm k6 run -o cloud /scripts/zoom_rio_de_janerio_with_contributor_filter.js
```

To invoke the homepage load test with 10 concurrent virtual users each running the test 10 times

```console
$ CLIENT_KEY=... \
docker-compose -f docker-compose.yml \
run --rm k6 run -u 10 -i 100 /scripts/browse_homepage.js
```

To invoke the facility download load test with a custom filter

```console
$ CLIENT_KEY=... FILTERS="contributors=699" \
docker-compose -f docker-compose.yml \
run --rm k6 run /scripts/download_facilities.js
```

To invoke the facility creation load test simulating 5 contributors POSTing 1000
random facilities each

```console
$ TOKEN=... \
docker-compose -f docker-compose.yml \
run --rm k6 run -u 5 -i 5000 /scripts/post_facility.js
```
86,647 changes: 86,647 additions & 0 deletions load-tests/addresses.csv

Large diffs are not rendered by default.

133 changes: 133 additions & 0 deletions load-tests/browse_homepage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { check, sleep, group } from 'k6';
import http from 'k6/http';

export const options = {
userAgent: 'k6LoadTest',
};

const check2xx = res => {
const resArray = Array.isArray(res) ? res : [res];
resArray.forEach(res =>
check(res, {
'is status 2xx': (r) => r.status >= 200 && r.status < 300,
})
);
};

const referer = 'https://staging.openapparel.org/';

// rootUrl should NOT have a trailing slash
const rootUrl = 'https://staging.openapparel.org';

const staticHeaders = {
'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="99", "Google Chrome";v="99"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"macOS"',
referer,
};

const apiHeaders = {
accept: 'application/json, text/plain, */*',
'x-oar-client-key': __ENV.CLIENT_KEY || 'NOT_SPECIFIED',
credentials: 'same-origin',
'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="99", "Google Chrome";v="99"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"macOS"',
referer,
};

const buildGet = (url, headers) => {
return {
method: 'GET',
url,
params: {
headers: headers || staticHeaders,
}
};
};

export default function main() {
let responses;

// Wait up to 5 seconds so that the iterations aren't exactly overlapping
sleep(Math.random() * 5);

group('https://staging.openapparel.org/', function () {
responses = http.batch([
buildGet(`${rootUrl}/web/environment.js`),
buildGet(`${rootUrl}/static/css/2.037bc208.chunk.css`),
buildGet(`${rootUrl}/static/css/main.cfc7f5ef.chunk.css`),
buildGet(`${rootUrl}/static/js/2.27e1f047.chunk.js`),
buildGet(`${rootUrl}/static/js/main.602f4e63.chunk.js`),
]);
check2xx(responses);

// This was inserted by k6.io when converting the recording. We assume
// it sumulates JS parsing
sleep(1.2);

responses = http.batch([
buildGet(`${rootUrl}/static/media/Creative-Commons-Attribution-ShareAlike-40-International-Public.03c38fcb.png`),
]);
check2xx(responses);

responses = http.batch([
buildGet(`${rootUrl}/api/contributors/`, apiHeaders),
buildGet(`${rootUrl}/api/countries/`, apiHeaders),
buildGet(`${rootUrl}/api/contributor-lists/`, apiHeaders),
buildGet(`${rootUrl}/api/api-feature-feature-flags/`, apiHeaders),
]);
check2xx(responses);

responses = http.batch([
buildGet(`${rootUrl}/user-login/`, apiHeaders),
]);
// We do NOT check for a 2xx response here because for an
// unauthenticated user this will return 4xx

// TODO: Consider how to break the tile cache in a way that is a
// reasonable simulation
responses = http.batch([
buildGet(`${rootUrl}/tile/facilitygrid/1647621241-89-aec180a4/2/1/1.pbf`),
buildGet(`${rootUrl}/tile/facilitygrid/1647621241-89-aec180a4/2/2/1.pbf`),
buildGet(`${rootUrl}/tile/facilitygrid/1647621241-89-aec180a4/2/1/0.pbf`),
buildGet(`${rootUrl}/tile/facilitygrid/1647621241-89-aec180a4/2/2/0.pbf`),
buildGet(`${rootUrl}/tile/facilitygrid/1647621241-89-aec180a4/2/1/2.pbf`),
buildGet(`${rootUrl}/tile/facilitygrid/1647621241-89-aec180a4/2/2/2.pbf`),
]);
check2xx(responses);

responses = http.batch([
buildGet(`${rootUrl}/tile/facilitygrid/1647621241-89-aec180a4/2/0/1.pbf`),
buildGet(`${rootUrl}/tile/facilitygrid/1647621241-89-aec180a4/2/3/1.pbf`),
buildGet(`${rootUrl}/tile/facilitygrid/1647621241-89-aec180a4/2/0/0.pbf`),
buildGet(`${rootUrl}/tile/facilitygrid/1647621241-89-aec180a4/2/3/0.pbf`),
buildGet(`${rootUrl}/tile/facilitygrid/1647621241-89-aec180a4/2/0/2.pbf`),
buildGet(`${rootUrl}/tile/facilitygrid/1647621241-89-aec180a4/2/3/2.pbf`),
]);
check2xx(responses);

responses = http.batch([
// TODO There are 2 for contributors in the HAR file made from
// browsing the home page. This should be fixed in the app then
// removed from the load test
buildGet(`${rootUrl}/api/contributors/`, apiHeaders),
buildGet(`${rootUrl}/api/current_tile_cache_key`, apiHeaders),
]);
check2xx(responses);

responses = http.batch([
buildGet(`${rootUrl}/api/facilities/?&pageSize=50`, apiHeaders),
]);
check2xx(responses);

// This was inserted by the HAR conversion
sleep(1.4);

responses = http.batch([
buildGet(`${rootUrl}/favicon/site.webmanifest`),
buildGet(`${rootUrl}/favicon/favicon-32x32.png`),
]);
check2xx(responses);
});
}
3 changes: 3 additions & 0 deletions load-tests/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ services:
environment:
- K6_CLOUD_TOKEN
- CACHE_KEY_SUFFIX
- CLIENT_KEY
- VU_MULTIPLIER
- FILTERS
- TOKEN
volumes:
- ./:/scripts/
command: run /scripts/zoom_rio_de_janerio_with_contributor_filter.js
55 changes: 55 additions & 0 deletions load-tests/download_facilities.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { check, sleep, group } from 'k6';
import http from 'k6/http';

export const options = {
userAgent: 'k6LoadTest',
};

const check2xx = res => {
const resArray = Array.isArray(res) ? res : [res];
resArray.forEach(res =>
check(res, {
'is status 2xx': (r) => r.status >= 200 && r.status < 300,
})
);
};

const referer = 'https://staging.openapparel.org/';

// rootUrl should NOT have a trailing slash
const rootUrl = 'https://staging.openapparel.org';

const apiHeaders = {
accept: 'application/json, text/plain, */*',
'x-oar-client-key': __ENV.CLIENT_KEY || 'NOT_SPECIFIED',
credentials: 'same-origin',
'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="99", "Google Chrome";v="99"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"macOS"',
referer,
};

const buildGet = (url, headers) => {
return {
method: 'GET',
url,
params: {
headers: headers || apiHeaders,
}
};
};

const FILTERS = __ENV.FILTERS || 'contributors=699&detail=true&lists=929';

export default function main() {
let responses;
let next;
responses = http.batch([buildGet(`${rootUrl}/api/facilities/?detail=true&pageSize=10&${FILTERS}`)]);
check2xx(responses);
next = JSON.parse(responses[0].body).next;
while (next) {
responses = http.batch([buildGet(next)]);
check2xx(responses);
next = JSON.parse(responses[0].body).next;
}
}

0 comments on commit a4e6040

Please sign in to comment.