-
Notifications
You must be signed in to change notification settings - Fork 12
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
✅ Add perf test #100
Draft
Quentin1006
wants to merge
4
commits into
main
Choose a base branch
from
add-perf-tests
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
✅ Add perf test #100
Changes from 3 commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
name: Docker Image CI | ||
|
||
on: | ||
release: | ||
types: [published] | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Set up QEMU | ||
uses: docker/setup-qemu-action@v3 | ||
- name: Set up Docker Buildx | ||
id: buildx | ||
uses: docker/setup-buildx-action@v3 | ||
- name: Get the version | ||
id: get_version | ||
run: echo ::set-output name=VERSION::$(echo $GITHUB_REF | cut -d / -f 3) | ||
- name: Check out the repo | ||
uses: actions/checkout@v2 | ||
- name: Log in to Docker Hub | ||
uses: docker/login-action@v1 | ||
with: | ||
username: ${{ secrets.DOCKER_USERNAME }} | ||
password: ${{ secrets.DOCKER_PASSWORD }} | ||
- name: Push to Docker Hub | ||
uses: docker/build-push-action@v2 | ||
with: | ||
context: ./test/performance | ||
push: true | ||
tags: bouyguestelecom/a7-perf:${{ steps.get_version.outputs.VERSION }},bouyguestelecom/a7-perf:latest | ||
platforms: linux/amd64,linux/arm64 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
FROM golang:1.21 | ||
|
||
ARG XK6_VERSION=v0.12.2 | ||
|
||
ENV BASE_URL "" | ||
ENV STAGE_DURATION 30 | ||
|
||
ENV AVERAGE_LOAD_ITER_PER_SEC 15 | ||
ENV AVERAGE_LOAD_ITER_VARIATION 5 | ||
ENV AVERAGE_LOAD_DURATION_95 500 | ||
|
||
ENV AUTOSCALING_MAX_ITER_PER_SEC 20 | ||
ENV AUTOSCALING_DURATION_95 500 | ||
|
||
ENV STRESS_LOAD_MIN_ITER_PER_SEC 10 | ||
ENV STRESS_LOAD_MAX_ITER_PER_SEC 50 | ||
ENV STRESS_LOAD_DURATION_95 500 | ||
|
||
WORKDIR /app | ||
|
||
RUN go install go.k6.io/xk6/cmd/xk6@${XK6_VERSION} | ||
RUN xk6 build ${XK6_VERSION} | ||
RUN mv /app/k6 /usr/bin | ||
|
||
COPY common.js autoscaling.js stressload.js average-load.js /app/ | ||
|
||
CMD ["k6", "run", "/app/average-load.js"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
|
||
# Performance Metrics Documentation | ||
|
||
## How to use it | ||
|
||
The default to use it is by running the docker image `bouyguestelecom/a7-perf` | ||
If no command is provided the average load test will be executed. | ||
|
||
There 3 k6 scripts available in the image: | ||
|
||
- `average-load.js` | ||
- `stressload.js` | ||
- `autoscaling.js` | ||
|
||
to run another script you can use the following command (adjust the env variable for your needs): | ||
|
||
```bash | ||
docker run bouyguestelecom/a7-perf k6 run <script_name> | ||
``` | ||
|
||
## Env variables | ||
|
||
| Metric Name | Description | Required | Default | | ||
|--------------------------------------|-----------------------------------------------------------------------------|----------|---------| | ||
| **BASE_URL** | The base URL for the application, used for API calls and resource fetching. | Yes | N/A | | ||
| **STAGE_DURATION** | The total duration of each stage in the performance testing process, measured in seconds. | Yes | N/A | | ||
| **STRESS_LOAD_MIN_ITER_PER_SEC** | The minimum number of iterations per second during stress load testing. | Yes | N/A | | ||
| **STRESS_LOAD_MAX_ITER_PER_SEC** | The maximum number of iterations per second during stress load testing. | Yes | N/A | | ||
| **STRESS_LOAD_DURATION_95** | The 95th percentile duration of stress load tests, indicating the time taken for 95% of the requests. | Yes | N/A | | ||
| **AUTOSCALING_MAX_ITER_PER_SEC** | The maximum iterations per second allowed during autoscaling operations. | Yes | N/A | | ||
| **AUTOSCALING_DURATION_95** | The 95th percentile duration for autoscaling events, reflecting the time taken for 95% of autoscaling actions. | Yes | N/A | | ||
| **AVERAGE_LOAD_ITER_PER_SEC** | The average number of iterations per second during normal load conditions. | Yes | N/A | | ||
| **AVERAGE_LOAD_ITER_VARIATION** | The variation in iterations per second during average load conditions, indicating stability or fluctuations. | Yes | N/A | | ||
| **AVERAGE_LOAD_DURATION_95** | The 95th percentile duration for average load conditions, showing the time taken for 95% of requests under normal load. | Yes | N/A | | ||
| **PREALLOACATED_VUS** | The number of virtual users preallocated for performance testing, used to simulate load conditions. | No | 150 | | ||
| **SKIP_TLS_VERIFY** | A flag to skip TLS verification during API calls, useful for testing in development environments. | No | False | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { _setup, _main, thresholds, PREALLOACATED_VUS, STAGE_DURATION_WITH_UNIT, commonOptions } from './common.js'; | ||
|
||
_checkRequiredEnvVars([ | ||
'BASE_URL', | ||
'STAGE_DURATION', | ||
'AUTOSCALING_MAX_ITER_PER_SEC', | ||
'AUTOSCALING_DURATION_95' | ||
]) | ||
|
||
const AUTOSCALING_MAX_ITER_PER_SEC = __ENV.AUTOSCALING_MAX_ITER_PER_SEC | ||
const AUTOSCALING_DURATION_95 = __ENV.AUTOSCALING_DURATION_95 | ||
|
||
const minTarget = Math.round(AUTOSCALING_MAX_ITER_PER_SEC / 5) | ||
const midTarget = Math.round(AUTOSCALING_MAX_ITER_PER_SEC / 2) | ||
|
||
const autoscalingStages = [ | ||
{ duration: STAGE_DURATION_WITH_UNIT, target: minTarget }, | ||
{ duration: STAGE_DURATION_WITH_UNIT, target: midTarget }, | ||
{ duration: STAGE_DURATION_WITH_UNIT, target: AUTOSCALING_MAX_ITER_PER_SEC }, | ||
{ duration: STAGE_DURATION_WITH_UNIT, target: midTarget }, | ||
{ duration: STAGE_DURATION_WITH_UNIT, target: minTarget }, | ||
|
||
] | ||
|
||
export const options = { | ||
...commonOptions, | ||
scenarios: { | ||
autoscaling: { | ||
exec: 'main', | ||
executor: 'ramping-arrival-rate', | ||
preAllocatedVUs: PREALLOACATED_VUS, | ||
gracefulStop: "0s", | ||
stages: autoscalingStages, | ||
tags: { test_type: 'autoscaling' }, | ||
}, | ||
}, | ||
thresholds: { | ||
...thresholds, | ||
'http_req_duration{test_type:autoscaling}': [`p(95)< ${AUTOSCALING_DURATION_95}`], // 95% of requests should be below 200ms | ||
} | ||
} | ||
|
||
export const setup = _setup | ||
|
||
export const main = _main |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { _setup, _main, commonOptions, thresholds, PREALLOACATED_VUS, STAGE_DURATION_WITH_UNIT, _checkRequiredEnvVars } from './common.js'; | ||
|
||
|
||
_checkRequiredEnvVars([ | ||
'BASE_URL', | ||
'STAGE_DURATION', | ||
'AVERAGE_LOAD_ITER_PER_SEC', | ||
'AVERAGE_LOAD_ITER_VARIATION', | ||
'AVERAGE_LOAD_DURATION_95' | ||
]) | ||
|
||
const AVERAGE_LOAD_ITER_PER_SEC = __ENV.AVERAGE_LOAD_ITER_PER_SEC | ||
const AVERAGE_LOAD_ITER_VARIATION = __ENV.AVERAGE_LOAD_ITER_VARIATION | ||
const AVERAGE_LOAD_DURATION_95 = __ENV.AVERAGE_LOAD_DURATION_95 | ||
|
||
const averageLoadStages = [ | ||
// With this executor it will increase from 0 to `AVERAGE_LOAD_ITER_PER_SEC` iterations/s within the first `STAGE_DURATION_WITH_UNIT` | ||
// Then will go from AVERAGE_LOAD_ITER_VARIATION iter/s to AVERAGE_LOAD_ITER_VARIATION + AVERAGE_LOAD_ITER_PER_SEC iter/s within the next 30secs | ||
// then will stay at 100 iter/s for 30secs | ||
// finally will go from 100 iter/s to 50 iter/s within the next 30secs | ||
// it only reaches the target at the end of the duration | ||
{ duration: STAGE_DURATION_WITH_UNIT, target: AVERAGE_LOAD_ITER_PER_SEC }, | ||
{ duration: STAGE_DURATION_WITH_UNIT, target: Number(AVERAGE_LOAD_ITER_VARIATION) + Number(AVERAGE_LOAD_ITER_PER_SEC) }, | ||
{ duration: STAGE_DURATION_WITH_UNIT, target: Number(AVERAGE_LOAD_ITER_PER_SEC) - Number(AVERAGE_LOAD_ITER_VARIATION) }, | ||
{ duration: STAGE_DURATION_WITH_UNIT, target: AVERAGE_LOAD_ITER_PER_SEC }, | ||
] | ||
|
||
export const options = { | ||
...commonOptions, | ||
scenarios: { | ||
averageLoad: { | ||
exec: 'main', | ||
executor: 'ramping-arrival-rate', | ||
preAllocatedVUs: PREALLOACATED_VUS, | ||
gracefulStop: "0s", | ||
stages: averageLoadStages, | ||
tags: { test_type: 'averageLoad' }, | ||
}, | ||
}, | ||
thresholds: { | ||
...thresholds, | ||
'http_req_duration{test_type:averageLoad}': [`p(95)< ${AVERAGE_LOAD_DURATION_95}`], // 95% of requests should be below 200ms | ||
} | ||
} | ||
|
||
export const setup = _setup | ||
|
||
export const main = _main |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import http from 'k6/http'; | ||
import { check } from 'k6'; | ||
|
||
export const STAGE_DURATION_WITH_UNIT = __ENV.STAGE_DURATION + 's'; | ||
export const PREALLOACATED_VUS = __ENV.PREALLOACATED_VUS ?? 150; | ||
let URL = `${__ENV.BASE_URL}/ACO/[email protected]/build/micro-front-main.js`; | ||
const URL_CATALOG = `${__ENV.BASE_URL}/?catalog` | ||
|
||
// console.log("--------------------") | ||
// console.log({ __ENV }) | ||
// console.log("--------------------") | ||
|
||
|
||
|
||
export const commonOptions = { | ||
insecureSkipTLSVerify: __ENV.SKIP_TLS_VERIFY ?? false, | ||
} | ||
|
||
export const thresholds = { | ||
http_req_failed: ['rate<0.0001'], // http errors should be less than 1% | ||
} | ||
|
||
export const _checkRequiredEnvVars = (requiredEnvVars) => { | ||
for (const envVar of requiredEnvVars) { | ||
if (!__ENV[envVar]) { | ||
throw new Error(`Environment variable ${envVar} is missing`); | ||
} | ||
} | ||
} | ||
|
||
export const _setup = () => { | ||
const res = http.get(URL_CATALOG); | ||
check(res, { 'status was 200': (r) => r.status == 200 }); | ||
// make sure catalog fetch takes less than 10s | ||
check(res, { 'status was 200': (r) => r.timings.duration < 10000 }); | ||
|
||
} | ||
|
||
export const _main = () => { | ||
const res = http.get(URL); | ||
check(res, { 'status was 200': (r) => r.status == 200 }); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
// Discover how the system functions with sudden and massive increases in traffic. | ||
|
||
import http from 'k6/http'; | ||
import { check } from 'k6'; | ||
|
||
/******************** | ||
* Environment variables | ||
* | ||
* @env BASE_URL | ||
* @env STAGE_DURATION | ||
* @env AVERAGE_LOAD_ITER_PER_SEC | ||
* @env AVERAGE_LOAD_ITER_VARIATION | ||
* @env AUTOSCALING_ITER_PER_SEC | ||
* @env STRESS_LOAD_MIN_ITER_PER_SEC | ||
* @env STRESS_LOAD_MAX_ITER_PER_SEC | ||
*/ | ||
|
||
|
||
// const URL_CATALOG = "https://swap-dev.int.nbyt.fr/?catalog" | ||
// const URL = "https://swap-dev.int.nbyt.fr/ihm-bytel/ACAN/ADRESSE-GEOGRAPHIQUE/[email protected]/ADRESSE-GEOGRAPHIQUE-rechercherAdresses-consumer-swagger.json" | ||
Quentin1006 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// const BASE_URL = __ENV.BASE_URL | ||
// const STAGE_DURATION = __ENV.STAGE_DURATION | ||
// const AVERAGE_LOAD_ITER_PER_SEC = __ENV.AVERAGE_LOAD_ITER_PER_SEC | ||
// const AVERAGE_LOAD_ITER_VARIATION = __ENV.AVERAGE_LOAD_ITER_VARIATION | ||
// const AUTOSCALING_ITER_PER_SEC = __ENV.AUTOSCALING_ITER_PER_SEC | ||
// const STRESS_LOAD_MIN_ITER_PER_SEC = __ENV.STRESS_LOAD_MIN_ITER_PER_SEC | ||
// const STRESS_LOAD_MAX_ITER_PER_SEC = __ENV.STRESS_LOAD_MAX_ITER_PER_SEC | ||
|
||
|
||
/** TO SKIP SETTING ALL ENV VARIABLES */ | ||
const BASE_URL = __ENV.BASE_URL ?? 'http://localhost:45537' | ||
const STAGE_DURATION = __ENV.STAGE_DURATION ?? 30; | ||
const AVERAGE_LOAD_ITER_PER_SEC = __ENV.AVERAGE_LOAD_ITER_PER_SEC ?? 10; | ||
const AVERAGE_LOAD_ITER_VARIATION = __ENV.AVERAGE_LOAD_ITER_VARIATION ?? 10; | ||
const AUTOSCALING_ITER_PER_SEC = __ENV.AUTOSCALING_ITER_PER_SEC ?? 10; | ||
const STRESS_LOAD_MIN_ITER_PER_SEC = __ENV.STRESS_LOAD_MIN_ITER_PER_SEC ?? 10; | ||
const STRESS_LOAD_MAX_ITER_PER_SEC = __ENV.STRESS_LOAD_MAX_ITER_PER_SEC ?? 20; | ||
/** END TO SKIP SETTING ALL ENV VARIABLES */ | ||
|
||
if (!__ENV.BASE_URL || !__ENV.STAGE_DURATION || !__ENV.AVERAGE_LOAD_ITER_PER_SEC || !__ENV.AVERAGE_LOAD_ITER_VARIATION || !__ENV.AUTOSCALING_ITER_PER_SEC || !__ENV.STRESS_LOAD_MIN_ITER_PER_SEC || !__ENV.STRESS_LOAD_MAX_ITER_PER_SEC) { | ||
throw new Error('One or more environment variables are not specified'); | ||
} | ||
|
||
const STAGE_DURATION_WITH_UNIT = STAGE_DURATION + 's'; | ||
|
||
|
||
|
||
const averageLoadStages = [ | ||
// With this executor it will increase from 0 to `AVERAGE_LOAD_ITER_PER_SEC` iterations/s within the first `STAGE_DURATION_WITH_UNIT` | ||
// Then will go from AVERAGE_LOAD_ITER_VARIATION iter/s to AVERAGE_LOAD_ITER_VARIATION + AVERAGE_LOAD_ITER_PER_SEC iter/s within the next 30secs | ||
// then will stay at 100 iter/s for 30secs | ||
// finally will go from 100 iter/s to 50 iter/s within the next 30secs | ||
// it only reaches the target at the end of the duration | ||
{ duration: __ENV.STAGE_DURATION_WITH_UNIT, target: __ENV.AVERAGE_LOAD_ITER_PER_SEC }, | ||
{ duration: __ENV.STAGE_DURATION_WITH_UNIT, target: __ENV.AVERAGE_LOAD_ITER_VARIATION + AVERAGE_LOAD_ITER_PER_SEC }, | ||
{ duration: __ENV.STAGE_DURATION_WITH_UNIT, target: __ENV.AVERAGE_LOAD_ITER_PER_SEC - AVERAGE_LOAD_ITER_VARIATION }, | ||
{ duration: __ENV.STAGE_DURATION_WITH_UNIT, target: __ENV.AVERAGE_LOAD_ITER_PER_SEC }, | ||
] | ||
|
||
const autoscalingStages = [ | ||
{ duration: __ENV.STAGE_DURATION_WITH_UNIT, target: 20 }, | ||
{ duration: __ENV.STAGE_DURATION_WITH_UNIT, target: 50 }, | ||
{ duration: __ENV.STAGE_DURATION_WITH_UNIT, target: 100 }, | ||
{ duration: __ENV.STAGE_DURATION_WITH_UNIT, target: 50 }, | ||
{ duration: __ENV.STAGE_DURATION_WITH_UNIT, target: 20 }, | ||
|
||
] | ||
|
||
const stressLoadStages = new Array(Math.round((STRESS_LOAD_MAX_ITER_PER_SEC - STRESS_LOAD_MIN_ITER_PER_SEC)) / 10).fill(0).map((_, i) => { | ||
return { duration: STAGE_DURATION_WITH_UNIT, target: STRESS_LOAD_MIN_ITER_PER_SEC + i * 10 } | ||
}) | ||
|
||
console.log({ stressLoadStages }) | ||
|
||
// const stressLoadStages = [ | ||
// { duration: __ENV.STAGE_DURATION_WITH_UNIT, target: 20 }, | ||
// { duration: __ENV.STAGE_DURATION_WITH_UNIT, target: 30 }, | ||
// { duration: __ENV.STAGE_DURATION_WITH_UNIT, target: 40 }, | ||
// ] | ||
|
||
export const options = { | ||
scenarios: { | ||
// averageLoad: { | ||
// exec: 'main', | ||
// executor: 'ramping-arrival-rate', | ||
// preAllocatedVUs: 100, | ||
// startTime: '0s', | ||
// gracefulStop: "0s", | ||
// stages: averageLoadStages, | ||
// tags: { test_type: 'averageLoad' }, | ||
// }, | ||
// autoscaling: { | ||
// exec: 'main', | ||
// executor: 'ramping-arrival-rate', | ||
// preAllocatedVUs: 150, | ||
// // only way to run scenarios sequentially | ||
// startTime: STAGE_DURATION * averageLoadStages.length + 's', | ||
// gracefulStop: "0s", | ||
// stages: autoscalingStages, | ||
// tags: { test_type: 'autoscaling' }, | ||
// }, | ||
stressLoad: { | ||
executor: 'ramping-arrival-rate', | ||
exec: 'main', | ||
// startTime: STAGE_DURATION * (averageLoadStages.length + autoscalingStages.length) + 's', | ||
preAllocatedVUs: 150, | ||
gracefulStop: "0s", | ||
stages: stressLoadStages, | ||
tags: { test_type: 'stressLoad' }, | ||
}, | ||
|
||
}, | ||
thresholds: { | ||
http_req_failed: ['rate<0.0001'], // http errors should be less than 1% | ||
http_req_duration: ['p(95)<200'], // 95% of requests should be below 200ms | ||
'http_req_duration{test_type:stressLoad}': ['p(95)<1000'], // 95% of requests should be below 200ms | ||
}, | ||
}; | ||
|
||
export function _setup() { | ||
const res = http.get(URL_CATALOG); | ||
check(res, { 'status was 200': (r) => r.status == 200 }); | ||
// make sure catalog fetch takes less than 10s | ||
check(res, { 'status was 200': (r) => r.timings.duration < 10000 }); | ||
|
||
} | ||
|
||
export function _main() { | ||
const res = http.get(URL); | ||
check(res, { 'status was 200': (r) => r.status == 200 }); | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
retirer le fichier