-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added a random-traffic-generator for the Python Sample App (#31)
*Description of changes:* Added a random-traffic-generator for the Python Sample App. More details can be found in the README under `aws-otel-python-instrumentation/sample-applications/vehicle-dealership-sample-app/random-traffic-generator`. The traffic generator generates the following traffic: 1. Every minute, sends a single POST request to the VehicleInventoryApp and sends a single GET request. 2. Every hour, sends a burst of requests: 5 POST requests to the VehicleInventoryApp and 5 GET requests. 3. Every 5 minutes, sleeps for random amount of time between 30-60 seconds and then sends a GET request to the VehicleInventoryApp with a random throttle param between 5-20 seconds. The backend reads that throttle param and simulates throttling for that amount of time before responding to the request. 4. Every 5 minutes, sleeps for random amount of time between 30-60 seconds and then sends a GET request to the VehicleInventoryApp with an invalid car id to trigger 404 error. 5. Every 5 minutes, sleeps for random amount of time between 30-60 seconds and then sends a GET request to the ImageServiceApp with a non existent image name to trigger 500 error due to S3 Error: "An error occurred (NoSuchKey) when calling the GetObject operation: The specified key does not exist." By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.
- Loading branch information
1 parent
353770b
commit 0934954
Showing
11 changed files
with
368 additions
and
5 deletions.
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
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
1 change: 1 addition & 0 deletions
1
sample-applications/vehicle-dealership-sample-app/random-traffic-generator/.gitignore
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 @@ | ||
node_modules |
26 changes: 26 additions & 0 deletions
26
sample-applications/vehicle-dealership-sample-app/random-traffic-generator/Dockerfile
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,26 @@ | ||
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
# SPDX-License-Identifier: Apache-2.0 | ||
# Use the official lightweight Node.js 16 image. | ||
# https://hub.docker.com/_/node | ||
FROM node:16-slim | ||
|
||
# Create and change to the app directory. | ||
WORKDIR /usr/src/app | ||
|
||
# Copy application dependency manifests to the container image. | ||
# A wildcard is used to ensure copying both package.json AND package-lock.json (if available). | ||
# Copying this first prevents re-running npm install on every code change. | ||
COPY package*.json ./ | ||
|
||
# Install production dependencies. | ||
# If you have native dependencies, you'll need additional tools. | ||
# For a full list of package.json changes, see: | ||
# https://github.com/nodejs/docker-node/blob/main/docs/BestPractices.md | ||
RUN npm install --only=production | ||
|
||
# Copy local code to the container image. | ||
COPY . . | ||
|
||
# Run the web service on container startup. | ||
CMD [ "node", "index.js" ] | ||
|
21 changes: 21 additions & 0 deletions
21
...e-applications/vehicle-dealership-sample-app/random-traffic-generator/README.md
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,21 @@ | ||
# Random Traffic Generator | ||
The traffic generator generates the following traffic: | ||
1. Every minute, sends a single POST request to the VehicleInventoryApp and sends a single GET request. | ||
2. Every hour, sends a burst of requests: 5 POST requests to the VehicleInventoryApp and 5 GET requests. | ||
3. Every 5 minutes, sleeps for random amount of time between 30-60 seconds and then sends a GET request to the VehicleInventoryApp with a random throttle param between 5-20 seconds. The backend reads that throttle param and simulates throttling for that amount of time before responding to the request. | ||
4. Every 5 minutes, sleeps for random amount of time between 30-60 seconds and then sends a GET request to the VehicleInventoryApp with an invalid car id to trigger 404 error. | ||
5. Every 5 minutes, sleeps for random amount of time between 30-60 seconds and then sends a GET request to the ImageServiceApp with a non existent image name to trigger 500 error due to S3 Error: "An error occurred (NoSuchKey) when calling the GetObject operation: The specified key does not exist." | ||
|
||
## Running locally | ||
1. Run `npm install` | ||
2. Run locally: | ||
- If you are running against you application locally, just run `node index.js`. The default endpoint is `0.0.0.0:8000` for the ImageServiceApp and `0.0.0.0:8001` for VehicleInventoryApp. | ||
- If you want to run against the application on EKS, before running the `node index.js`, run `export <EKS_URL>`. | ||
|
||
## Deploying to EKS | ||
Run `bash build.sh <account_id> <region>`. This does the following: | ||
1. This will retrieve the endpoint from EKS ingress-nginx pod | ||
2. Build docker image of the traffic | ||
3. Push the docker image to ECR | ||
4. Deploy the image to EKS | ||
|
22 changes: 22 additions & 0 deletions
22
sample-applications/vehicle-dealership-sample-app/random-traffic-generator/build.sh
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,22 @@ | ||
#!/usr/bin/env bash | ||
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
# SPDX-License-Identifier: Apache-2.0 | ||
account=$1 | ||
region=$2 | ||
|
||
# Save the endpoint URL to a variable | ||
endpoint=$(kubectl get svc -n ingress-nginx | grep "ingress-nginx" | awk '{print $4}') | ||
|
||
# Print the endpoint | ||
echo "Endpoint: $endpoint" | ||
|
||
export REPOSITORY_PREFIX=${account}.dkr.ecr.${region}.amazonaws.com | ||
aws ecr get-login-password --region ${region} | docker login --username AWS --password-stdin ${REPOSITORY_PREFIX} | ||
aws ecr create-repository --repository-name random-traffic-generator --region ${region} || true | ||
docker build -t random-traffic-generator:latest . | ||
docker tag random-traffic-generator:latest ${REPOSITORY_PREFIX}/random-traffic-generator:latest | ||
docker push ${REPOSITORY_PREFIX}/random-traffic-generator:latest | ||
|
||
sed -e 's#\${REPOSITORY_PREFIX}'"#${REPOSITORY_PREFIX}#g" -e 's#\${URL}'"#$endpoint#g" deployment.yaml | kubectl apply -f - | ||
|
||
|
25 changes: 25 additions & 0 deletions
25
sample-applications/vehicle-dealership-sample-app/random-traffic-generator/deployment.yaml
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,25 @@ | ||
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
# SPDX-License-Identifier: Apache-2.0 | ||
apiVersion: apps/v1 | ||
kind: Deployment | ||
metadata: | ||
name: random-traffic-generator | ||
labels: | ||
app: random-traffic-generator | ||
spec: | ||
replicas: 1 | ||
selector: | ||
matchLabels: | ||
app: random-traffic-generator | ||
template: | ||
metadata: | ||
labels: | ||
app: random-traffic-generator | ||
spec: | ||
containers: | ||
- name: random-traffic-generator | ||
image: ${REPOSITORY_PREFIX}/random-traffic-generator:latest | ||
env: | ||
- name: URL | ||
value: "${URL}" | ||
|
102 changes: 102 additions & 0 deletions
102
sample-applications/vehicle-dealership-sample-app/random-traffic-generator/index.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,102 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
const axios = require('axios'); | ||
const cron = require('node-cron'); | ||
|
||
const vehicleURL = process.env.URL ? `${process.env.URL}/vehicle-inventory` : 'http://0.0.0.0:8001/vehicle-inventory' | ||
|
||
function getRandomNumber(min, max) { | ||
return Math.floor(Math.random() * (max - min + 1)) + min; | ||
} | ||
|
||
|
||
function sleep(ms) { | ||
return new Promise(resolve => setTimeout(resolve, ms)); | ||
} | ||
|
||
console.log(vehicleURL) | ||
|
||
// sends two requests every minute, 1 POST request and 1 GET request | ||
const postGetCarsTrafficTask = cron.schedule('* * * * *', async () => { | ||
console.log('add 1 car every 1 minutes'); | ||
const carData = {"make": "BMW", "model": "M340", "year": 2022, "image_name": "newCar.jpg"} | ||
axios.post(`http://${vehicleURL}/`, carData, { timeout: 10000 }) | ||
.catch(err => { | ||
console.error(err.response && err.response.data); | ||
}); | ||
|
||
// gets image from image service through the vehicle service | ||
axios.get(`http://${vehicleURL}/1/image`, { timeout: 10000 }) | ||
.catch(err => { | ||
console.error(`${err.response}, ${err.response.data}`); | ||
}); // Catch and log errors | ||
|
||
axios.get(`http://${vehicleURL}/1`, { timeout: 10000 }) | ||
.catch(err => { | ||
console.error(err.response && err.response.data); | ||
}); // Catch and log errors | ||
}, { scheduled: false }); | ||
postGetCarsTrafficTask.start(); | ||
|
||
// sends a burst of traffic sending 10 requests every 15 mins: | ||
// 5 POST requests and 5 GET requests. | ||
const postGetCarsTrafficBurstTask = cron.schedule('*/15 * * * *', async () => { | ||
console.log('add 5 cars within 1 minutes'); | ||
const carData = {"make": "BMW", "model": "M340", "year": 2022, "image_name": "newCar.jpg"} | ||
for (let i = 0; i < 5; i++) { | ||
axios.post(`http://${vehicleURL}/`, carData, { timeout: 10000 }) | ||
.catch(err => { | ||
console.error(err.response && err.response.data); | ||
}); // Catch and log errors | ||
|
||
// gets image from image service through the vehicle service | ||
axios.get(`http://${vehicleURL}/1/image`, { timeout: 10000 }) | ||
.catch(err => { | ||
console.error(err.response && err.response.data); | ||
}); // Catch and log errors | ||
} | ||
}, { scheduled: false }); | ||
postGetCarsTrafficBurstTask.start(); | ||
|
||
// sends a GET request with custom throttle parameter in the body that mimics being throttled. The throttle time | ||
// is going to be random between 2 - 5 secs. | ||
const getCarThrottle = cron.schedule('*/5 * * * *', async () => { | ||
sleepSecs = getRandomNumber(30,60); | ||
console.log(`sleep ${sleepSecs} seconds`); | ||
await sleep(sleepSecs*1000); | ||
throttleSecs = getRandomNumber(2,5); | ||
console.log(`request will be throttled for ${throttleSecs} seconds`) | ||
axios.get(`http://${vehicleURL}/1`, {params: {"throttle": throttleSecs}}, { timeout: 10000 }) | ||
.catch(err => { | ||
console.error(err.response && err.response.data); | ||
}); // Catch and log errors | ||
}, { scheduled: false }); | ||
getCarThrottle.start(); | ||
|
||
// sends an invalid GET request with a non existent car id to trigger 404 error | ||
const getInvalidRequest = cron.schedule('*/5 * * * *', async () => { | ||
sleepSecs = getRandomNumber(30,120); | ||
console.log(`sleep ${sleepSecs} seconds`); | ||
await sleep(sleepSecs*1000); | ||
console.log("getting non existent car to trigger 404"); | ||
axios.get(`http://${vehicleURL}/123456789`, { timeout: 10000 }) | ||
.catch(err => { | ||
console.error(err.response && err.response.data); | ||
}); // Catch and log errors | ||
}, { scheduled: false }); | ||
getInvalidRequest.start(); | ||
|
||
// sends an invalid GET request with a non existent image name to trigger 500 error due to S3 Error: | ||
// "An error occurred (NoSuchKey) when calling the GetObject operation: The specified key does not exist." | ||
// The vehicle service will then return 404. | ||
const getNonExistentImage = cron.schedule('*/5 * * * *', async () => { | ||
sleepSecs = getRandomNumber(30,120); | ||
console.log(`sleep ${sleepSecs} seconds`); | ||
await sleep(sleepSecs*1000); | ||
console.log('get an non existent image to trigger aws error'); | ||
axios.get(`http://${vehicleURL}/image/doesnotexist.jpeg`) | ||
.catch(err => { | ||
console.error(err.response && err.response.data); | ||
}); // Catch and log errors | ||
}, { scheduled: false }); | ||
getNonExistentImage.start(); |
126 changes: 126 additions & 0 deletions
126
sample-applications/vehicle-dealership-sample-app/random-traffic-generator/package-lock.json
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.