Skip to content

Commit f002f5e

Browse files
committed
Adjusted the python app example
1 parent 09122c9 commit f002f5e

9 files changed

Lines changed: 244 additions & 120 deletions

File tree

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ node_modules
66
# draw.io temp files
77
.$*.bkp
88
.$*.dtmp
9-
venv
9+
venv
10+
__pycache__

metrics-examples/.ceignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
node_modules/
22
target/
3-
vendor/
3+
vendor/
4+
venv/
5+
__pycache__

metrics-examples/README.md

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -45,18 +45,6 @@ ibmcloud ce application create \
4545
./run all
4646
```
4747
48-
## Language Comparison
49-
50-
| Feature | Node.js | Go | Java | Python |
51-
|---------|---------|-----|------|--------|
52-
| **Framework** | Express | Gorilla Mux | Spring Boot | FastAPI |
53-
| **Metrics Library** | prom-client | prometheus/client_golang | Micrometer | prometheus-client |
54-
| **Startup Time** | ~1s | <1s | ~5-10s | ~2-3s |
55-
| **Memory Footprint** | ~150-200 MB | ~20-30 MB | ~200-250 MB | ~100-150 MB |
56-
| **Image Size** | ~150-200 MB | ~20-30 MB | ~200-250 MB | ~100-150 MB |
57-
| **Concurrency Model** | Event loop | Goroutines | Threads | Async/await |
58-
| **Best For** | Rapid development | Performance & efficiency | Enterprise apps | Modern APIs |
59-
6048
## Metrics
6149
6250
All applications expose Prometheus metrics at `/metrics` (port 2112). All metric names are prefixed with a configurable value set via the `METRICS_NAME_PREFIX` environment variable (default: `mymetrics_`).
@@ -209,17 +197,3 @@ metrics-examples/
209197
├── load-test.sh # Load testing script
210198
└── README.md # This file
211199
```
212-
213-
## Contributing
214-
215-
When adding new features or metrics:
216-
217-
1. Implement the feature in all four languages
218-
2. Use identical metric names across all implementations
219-
3. Maintain consistent API endpoints
220-
4. Update all language-specific README files
221-
5. Test with the load-test.sh script
222-
223-
## License
224-
225-
See individual language directories for specific dependencies and licenses.

metrics-examples/python/Dockerfile

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,22 @@
1-
# Use Python slim image
2-
FROM python:3.12-slim
31

4-
WORKDIR /app
2+
# Download dependencies in builder stage
3+
FROM registry.access.redhat.com/ubi9/python-312 AS builder
54

65
# Install dependencies
76
COPY requirements.txt .
8-
RUN pip install --no-cache-dir -r requirements.txt
7+
RUN python -m pip install -r requirements.txt
98

10-
# Copy application code
11-
COPY . .
9+
# Build final stage
10+
FROM registry.access.redhat.com/ubi10/python-312-minimal
1211

13-
# Set environment
14-
ENV PYTHONUNBUFFERED=1
12+
ENV PYTHONPATH=/opt/app-root/lib/${PYTHON_VERSION}/site-packages
1513

16-
# Create non-root user
17-
RUN useradd -m -u 1001 appuser && chown -R appuser:appuser /app
18-
USER appuser
14+
COPY --chown=1001:0 --from=builder /opt/app-root/lib/python3.12/site-packages ${PYTHONPATH}
15+
COPY --chown=1001:0 app.py /opt/app-root/src/
16+
COPY --chown=1001:0 utils/ /opt/app-root/src/utils
17+
COPY --chown=1001:0 log_conf.yaml /opt/app-root/src/
1918

20-
# Expose ports
21-
EXPOSE 8080 2112
19+
USER 1001:0
20+
WORKDIR /opt/app-root/src
2221

23-
# Run the application with uvicorn
24-
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8080"]
22+
CMD python app.py

metrics-examples/python/README.md

Lines changed: 84 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,29 @@
22

33
This application helps debug connectivity issues for IBM Cloud Services and provides comprehensive monitoring through Prometheus metrics. It includes outbound HTTP call simulation, database connectivity testing, and compute-intensive workload simulation.
44

5+
## Architecture
6+
7+
```
8+
┌─────────────────────────────────────┐
9+
│ Container │
10+
│ │
11+
│ ┌────────────────────────────┐ │
12+
│ │ Main Application Server │ │
13+
│ │ Port: 8080 │ │
14+
│ │ - / │ │
15+
│ │ - /test-db │ │
16+
│ │ - /outbound/* │ │
17+
│ └────────────────────────────┘ │
18+
│ │
19+
│ ┌────────────────────────────┐ │
20+
│ │ Metrics Server (Thread) │ │
21+
│ │ Port: 2112 │ │
22+
│ │ - /metrics │ │
23+
│ └────────────────────────────┘ │
24+
│ │
25+
└─────────────────────────────────────┘
26+
```
27+
528
## Features
629

730
- **Outbound HTTP Calls**: Configurable endpoints that simulate delays and error responses to httpbin.org-compatible backends
@@ -46,32 +69,6 @@ ibmcloud ce application update \
4669
--env HTTPBIN_BASE_URL=https://custom-backend.example.com
4770
```
4871

49-
### Run Locally
50-
51-
Pull and run with Docker:
52-
```bash
53-
docker pull icr.io/codeengine/metrics-example-app-python
54-
docker run -p 8080:8080 -p 2112:2112 icr.io/codeengine/metrics-example-app-python
55-
```
56-
57-
Or run from source:
58-
```bash
59-
pip install -r requirements.txt
60-
python app.py
61-
```
62-
63-
Or with uvicorn directly:
64-
```bash
65-
pip install -r requirements.txt
66-
uvicorn app:app --host 0.0.0.0 --port 8080
67-
```
68-
69-
The application exposes:
70-
- Main application: `http://localhost:8080`
71-
- Metrics endpoint: `http://localhost:8080/metrics`
72-
- Interactive API docs: `http://localhost:8080/docs`
73-
- Alternative API docs: `http://localhost:8080/redoc`
74-
7572
## Configuration
7673

7774
### Environment Variables
@@ -93,15 +90,14 @@ For database connectivity, create a Code Engine service binding between your pro
9390
- `GET /outbound/get` - Simple outbound GET request
9491
- `POST /outbound/post` - Outbound POST request
9592
- `GET /outbound/status/{code}` - Request specific HTTP status code
96-
- `GET /metrics` - Prometheus metrics endpoint
9793
- `GET /docs` - Interactive API documentation (Swagger UI)
9894
- `GET /redoc` - Alternative API documentation (ReDoc)
9995

10096
All outbound endpoints include simulated compute-intensive data processing (0-3s duration, 40-80% CPU intensity).
10197

10298
## Metrics
10399

104-
The application exposes Prometheus metrics at `/metrics`. All metric names are prefixed with a configurable value set via the `METRICS_NAME_PREFIX` environment variable (default: `mymetrics_`).
100+
The application exposes Prometheus metrics on a **separate metrics server** at `http://localhost:2112/metrics`. This separation provides better security and performance isolation. All metric names are prefixed with a configurable value set via the `METRICS_NAME_PREFIX` environment variable (default: `mymetrics_`).
105101

106102
**Request Metrics**
107103
- `mymetrics_requests_total`: Total requests by method and path
@@ -123,44 +119,65 @@ The application exposes Prometheus metrics at `/metrics`. All metric names are p
123119

124120
## Development
125121

122+
### Project Structure
123+
124+
```
125+
python/
126+
├── app.py # FastAPI application entry point
127+
├── requirements.txt # Python dependencies
128+
├── Dockerfile # Multi-stage Docker build
129+
├── README.md # This file
130+
└── utils/
131+
├── __init__.py # Package initialization
132+
├── metrics.py # Prometheus metrics definitions
133+
├── db.py # PostgreSQL connection handling
134+
└── compute.py # Compute simulation utilities
135+
```
136+
126137
### Prerequisites
127138

128139
- Python 3.12 or later
129140
- pip or poetry for package management
130-
- Docker (for containerized builds)
141+
- Docker or Podman (for containerized builds)
131142

132-
### Building
143+
### Run Locally
144+
145+
Pull and run with Docker:
146+
```bash
147+
docker pull icr.io/codeengine/metrics-example-app-python
148+
docker run -p 8080:8080 -p 2112:2112 icr.io/codeengine/metrics-example-app-python
149+
```
133150

151+
Or run from source:
134152
```bash
135-
# Install dependencies
136-
pip install -r requirements.txt
153+
python3 -m venv venv
154+
source venv/bin/activate
137155

138-
# Run the application
156+
python -m pip install -r requirements.txt
139157
python app.py
140158

141-
# Or with uvicorn for development (with auto-reload)
142-
uvicorn app:app --reload --host 0.0.0.0 --port 8080
143159

144-
# Build Docker image
145-
docker build -t metrics-example-app-python .
160+
# Test main application (in another terminal)
161+
curl http://localhost:8080/
162+
163+
# Test metrics endpoint
164+
curl http://localhost:2112/metrics
146165

147-
# Run tests (if you add them)
148-
pytest
166+
# Test graceful shutdown
167+
# Send SIGTERM or press Ctrl+C
149168
```
150169

151-
### Project Structure
170+
The application exposes:
171+
- Main application: `http://localhost:8080`
172+
- Metrics endpoint: `http://localhost:2112/metrics`
173+
- Interactive API docs: `http://localhost:8080/docs`
174+
- Alternative API docs: `http://localhost:8080/redoc`
152175

153-
```
154-
python/
155-
├── app.py # FastAPI application entry point
156-
├── requirements.txt # Python dependencies
157-
├── Dockerfile # Multi-stage Docker build
158-
├── README.md # This file
159-
└── utils/
160-
├── __init__.py # Package initialization
161-
├── metrics.py # Prometheus metrics definitions
162-
├── db.py # PostgreSQL connection handling
163-
└── compute.py # Compute simulation utilities
176+
### Building
177+
178+
```bash
179+
# Build Docker image
180+
podman build -t metrics-example-app-python .
164181
```
165182

166183
## Performance Characteristics
@@ -202,20 +219,33 @@ pip install --upgrade asyncpg
202219

203220
### Performance Issues
204221

205-
For better performance in production:
222+
For better performance in production, you need to run both the main application and metrics server separately:
206223

207224
```bash
208-
# Use gunicorn with uvicorn workers
225+
# Install gunicorn
209226
pip install gunicorn
227+
228+
# Option 1: Run both servers using the default app.py (recommended for simplicity)
229+
python3 app.py
230+
231+
# Option 2: For production with multiple workers, run servers separately:
232+
233+
# Terminal 1: Run main application with gunicorn (multiple workers)
210234
gunicorn app:app -w 4 -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8080
235+
236+
# Terminal 2: Run metrics server separately (single worker is sufficient)
237+
gunicorn app:metrics_app -w 1 -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:2112
238+
239+
# Option 3: Use a process manager like supervisord or systemd to manage both processes
211240
```
212241

242+
**Note**: When using gunicorn with multiple workers for the main app, the metrics server should run as a separate process. The default `python3 app.py` approach handles both servers automatically in a single process, which is simpler for most use cases.
243+
213244
## FastAPI Features
214245

215246
This implementation uses FastAPI, which provides:
216247

217248
- **Automatic API Documentation**: Visit `/docs` for Swagger UI or `/redoc` for ReDoc
218-
- **Type Validation**: Automatic request/response validation using Pydantic
219249
- **Async Support**: Native async/await for non-blocking I/O
220250
- **High Performance**: One of the fastest Python frameworks available
221251
- **Standards-based**: Based on OpenAPI and JSON Schema

0 commit comments

Comments
 (0)