Skip to content

Commit

Permalink
docs: Add FastAPI Example to Python Examples Folder (#443)
Browse files Browse the repository at this point in the history
* Update to version 0.4.0
* Add fastapi to subdirectory
  • Loading branch information
Rperry2174 committed Oct 7, 2021
1 parent 9f7e83f commit 1292277
Show file tree
Hide file tree
Showing 31 changed files with 218 additions and 21 deletions.
21 changes: 1 addition & 20 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
# Examples

We set up these examples to help you try out Pyroscope. You'll need `docker` + `docker-compose` to run them:

```shell
cd python
docker-compose up --build
```

These are very simple projects where the application is basically one `while true` loop and inside that loop it calls a slow function and a fast function. Slow function takes about 75% of the time and the fast one takes about 25%. See [debug_python_with_pyroscope.md](https://github.com/pyroscope-io/pyroscope/blob/main/examples/debug_python_with_pyroscope.md) for a full example of how improving one function can decrease overall CPU utilization and ultimately save cut server costs by 66%!

Choose a language folder to select an example for your language of choice

# How Pyroscope works
Pyroscope identifies performance issues in your application by continuously profiling the code.
Expand All @@ -24,13 +15,3 @@ There are two main components that allow Pyroscope to run smoothly and quickly:
## Pyroscope agent
Every .01 seconds, the Pyroscope agent wraps around your Python, Ruby, or Go application to poll the stacktrace and calculate which function is consuming your CPU resources.
![pyroscope_diagram_with_logo](../.github/markdown-images/deployment.svg)

## Pyroscope Server
Pyroscope records and aggregates what your application has been doing, then sends that data to the Pyroscope server over port `:4040`([BadgerDB](https://github.com/dgraph-io/badger)) to be processed, aggregated, and stored for speedy queries of any time range, including:
- [x] all of 2020
- [x] that one day last month when that weird thing happened
- [x] that time you deployed on a Friday and messed up everything without knowing why
- [x] A random 10 seconds you are only querying to see if Pyroscope is legit

Check out our [Demo Page](https://demo.pyroscope.io/) and select any time range to see how quickly Pyroscope works!
![image](https://user-images.githubusercontent.com/23323466/104861560-2ebfaa00-58e5-11eb-862e-3481f294cbcf.png)
15 changes: 15 additions & 0 deletions examples/python/fastapi/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM python:3.9

# RUN pip3 install pipenv
# COPY Pipfile ./Pipfile
# COPY Pipfile.lock ./Pipfile.lock
# RUN pipenv install

RUN pip3 install fastapi pyroscope-io==0.4.0 uvicorn[standard]

ENV FLASK_ENV=development
ENV PYTHONUNBUFFERED=1

COPY lib ./lib
CMD [ "uvicorn", "lib.server:app", "--host", "0.0.0.0", "--port", "5000"]

File renamed without changes.
13 changes: 13 additions & 0 deletions examples/python/fastapi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## Fastapi Example

To run the example run the following commands:
```
# Pull latest pyroscope image:
docker pull pyroscope/pyroscope:latest
# Run the example project:
docker-compose up --build
# Reset the database (if needed):
# docker-compose down
```
File renamed without changes.
File renamed without changes.
File renamed without changes.
4 changes: 4 additions & 0 deletions examples/python/fastapi/lib/bike/bike.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from lib.utility.utility import find_nearest_vehicle

def order_bike(search_radius):
find_nearest_vehicle(search_radius, "bike")
File renamed without changes.
4 changes: 4 additions & 0 deletions examples/python/fastapi/lib/car/car.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from lib.utility.utility import find_nearest_vehicle

def order_car(search_radius):
find_nearest_vehicle(search_radius, "car")
File renamed without changes.
4 changes: 4 additions & 0 deletions examples/python/fastapi/lib/scooter/scooter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from lib.utility.utility import find_nearest_vehicle

def order_scooter(search_radius):
find_nearest_vehicle(search_radius, "scooter")
48 changes: 48 additions & 0 deletions examples/python/fastapi/lib/server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import os
import time
import pyroscope
# from flask import Flask
from fastapi import FastAPI
from lib.bike.bike import order_bike
from lib.car.car import order_car
from lib.scooter.scooter import order_scooter

pyroscope.configure(
app_name = "ride-sharing-app",
server_address = "http://pyroscope:4040",
tags = {
"region": f'{os.getenv("REGION")}',
}
)


app = FastAPI()

@app.get("/")
def read_root():
return {"Hello": "World"}

@app.get("/bike")
def bike():
order_bike(0.2)
return "<p>Bike ordered</p>"


@app.get("/scooter")
def scooter():
order_scooter(0.3)
return "<p>Scooter ordered</p>"


@app.get("/car")
def car():
order_car(0.4)
return "<p>Car ordered</p>"


@app.get("/")
def environment():
result = "<h1>environment vars:</h1>"
for key, value in os.environ.items():
result +=f"<p>{key}={value}</p>"
return result
File renamed without changes.
40 changes: 40 additions & 0 deletions examples/python/fastapi/lib/utility/utility.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import time
import pyroscope
import os
from datetime import datetime

# How much time mutex_lock() takes relative to search_radius()
MUTEX_LOCK_MULTIPLIER = 2

# How much time check_driver_availability() takes relative to search_radius()
DRIVER_AVAILABILITY_MULTIPLIER = 0.5

def mutex_lock(n):
i = 0
start_time = time.time()
while time.time() - start_time < n * MUTEX_LOCK_MULTIPLIER:
i += 1

def check_driver_availability(n):
i = 0
start_time = time.time()
while time.time() - start_time < n * DRIVER_AVAILABILITY_MULTIPLIER:
i += 1

# Every 4 minutes this will artificially create make requests in us-west-1 region slow
# this is just for demonstration purposes to show how performance impacts show up in the
# flamegraph

force_mutex_lock = datetime.today().minute * 4 % 8 == 0
if os.getenv("REGION") == "us-west-1" and force_mutex_lock:
mutex_lock(n)


def find_nearest_vehicle(n, vehicle):
with pyroscope.tag_wrapper({ "vehicle": vehicle}):
i = 0
start_time = time.time()
while time.time() - start_time < n:
i += 1
if vehicle == "car":
check_driver_availability(n)
26 changes: 26 additions & 0 deletions examples/python/fastapi/load-generator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import random
import requests
import time

HOSTS = [
'us-east-1',
'us-west-1',
'eu-west-1',
]

VEHICLES = [
'bike',
'scooter',
'car',
]

if __name__ == "__main__":
print(f"starting load generator")
time.sleep(3)
while True:
host = HOSTS[random.randint(0, len(HOSTS) - 1)]
vehicle = VEHICLES[random.randint(0, len(VEHICLES) - 1)]
print(f"requesting {vehicle} from {host}")
resp = requests.get(f'http://{host}:5000/{vehicle}')
print(f"received {resp}")
time.sleep(random.uniform(0.1, 0.2))
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ FROM python:3.9
# COPY Pipfile.lock ./Pipfile.lock
# RUN pipenv install

RUN pip3 install flask pyroscope-io==0.3.2
RUN pip3 install flask pyroscope-io==0.4.0

ENV FLASK_ENV=development
ENV PYTHONUNBUFFERED=1
Expand Down
11 changes: 11 additions & 0 deletions examples/python/flask/Dockerfile.load-generator
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM python:3.9

RUN pip3 install requests

COPY load-generator.py ./load-generator.py

ENV PYTHONUNBUFFERED=1

CMD [ "python", "load-generator.py" ]


13 changes: 13 additions & 0 deletions examples/python/flask/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## Flask Example

To run the example run the following commands:
```
# Pull latest pyroscope image:
docker pull pyroscope/pyroscope:latest
# Run the example project:
docker-compose up --build
# Reset the database (if needed):
# docker-compose down
```
33 changes: 33 additions & 0 deletions examples/python/flask/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
version: '3.9'
services:
us-east-1:
environment:
- REGION=us-east-1
build:
context: .

us-west-1:
environment:
- REGION=us-west-1
build:
context: .

eu-west-1:
environment:
- REGION=eu-west-1
build:
context: .

pyroscope:
image: pyroscope/pyroscope
environment:
- PYROSCOPE_LOG_LEVEL=debug
ports:
- '4040:4040'
command:
- 'server'

load-generator:
build:
context: .
dockerfile: Dockerfile.load-generator
1 change: 1 addition & 0 deletions examples/python/flask/lib/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

1 change: 1 addition & 0 deletions examples/python/flask/lib/bike/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

File renamed without changes.
1 change: 1 addition & 0 deletions examples/python/flask/lib/car/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

File renamed without changes.
1 change: 1 addition & 0 deletions examples/python/flask/lib/scooter/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions examples/python/flask/lib/utility/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

File renamed without changes.
File renamed without changes.

0 comments on commit 1292277

Please sign in to comment.