|  | 
|  | 1 | +--- | 
|  | 2 | +title: FastAPI + Uvicorn | 
|  | 3 | +weight: 6 | 
|  | 4 | +--- | 
|  | 5 | + | 
|  | 6 | +This guide demonstrates how to integrate Prometheus metrics into a [FastAPI](https://fastapi.tiangolo.com/) application using the native [Uvicorn](https://www.uvicorn.org/) ASGI server with production-ready multiprocess support. | 
|  | 7 | + | 
|  | 8 | +### Basic Implementation | 
|  | 9 | +Save the following in a `myapp.py` file: | 
|  | 10 | + | 
|  | 11 | +```python | 
|  | 12 | +import os | 
|  | 13 | +from fastapi import FastAPI | 
|  | 14 | +from prometheus_client import make_asgi_app, Counter, Gauge, CollectorRegistry, multiprocess | 
|  | 15 | +from fastapi.responses import JSONResponse | 
|  | 16 | +import psutil | 
|  | 17 | + | 
|  | 18 | +app = FastAPI() | 
|  | 19 | + | 
|  | 20 | +Define metrics with multiprocess aggregation | 
|  | 21 | +REQUEST_COUNT = Counter( | 
|  | 22 | +    "http_requests_total", | 
|  | 23 | +    "Total HTTP requests by endpoint", | 
|  | 24 | +    ["endpoint"], | 
|  | 25 | +    registry=CollectorRegistry()  # Isolated registry | 
|  | 26 | +) | 
|  | 27 | +CPU_USAGE = Gauge( | 
|  | 28 | +    "system_cpu_usage_percent", | 
|  | 29 | +    "Current CPU utilization percentage (aggregated)", | 
|  | 30 | +    multiprocess_mode='livesum'  # Critical for worker aggregation | 
|  | 31 | +) | 
|  | 32 | + | 
|  | 33 | +def create_metrics_app(): | 
|  | 34 | +    """Create multiprocess-aware metrics endpoint""" | 
|  | 35 | +    registry = CollectorRegistry() | 
|  | 36 | +    multiprocess.MultiProcessCollector( | 
|  | 37 | +        registry, | 
|  | 38 | +        path=os.environ.get(  # Explicit path handling | 
|  | 39 | +            'PROMETHEUS_MULTIPROC_DIR',  | 
|  | 40 | +            '/tmp/prometheus'  # Fallback path | 
|  | 41 | +        ) | 
|  | 42 | +    ) | 
|  | 43 | +    return make_asgi_app(registry=registry) | 
|  | 44 | + | 
|  | 45 | +Mount endpoint with trailing slash | 
|  | 46 | +app.mount("/metrics/", create_metrics_app()) | 
|  | 47 | + | 
|  | 48 | +@app.get("/") | 
|  | 49 | +async def home(): | 
|  | 50 | +    REQUEST_COUNT.labels(endpoint="/").inc() | 
|  | 51 | +    CPU_USAGE.set(psutil.cpu_percent(interval=None))  # System-wide measurement | 
|  | 52 | +    return JSONResponse({"status": "ok"}) | 
|  | 53 | +``` | 
|  | 54 | + | 
|  | 55 | +### Key Configuration | 
|  | 56 | +1. **Multiprocess Aggregation**   | 
|  | 57 | +   Required for gauge metrics in worker environments: | 
|  | 58 | +   ```python | 
|  | 59 | +   # Supported modes: livesum/max/liveall | 
|  | 60 | +   Gauge(..., multiprocess_mode='livesum') | 
|  | 61 | +   ``` | 
|  | 62 | + | 
|  | 63 | +2. **Registry Isolation**   | 
|  | 64 | +   Prevents metric conflicts between components: | 
|  | 65 | +   ```python | 
|  | 66 | +   REQUEST_COUNT = Counter(..., registry=CollectorRegistry()) | 
|  | 67 | +   ``` | 
|  | 68 | + | 
|  | 69 | +### Running the Application | 
|  | 70 | +```bash | 
|  | 71 | +1. Install dependencies with psutil | 
|  | 72 | +pip install fastapi uvicorn prometheus-client psutil | 
|  | 73 | + | 
|  | 74 | +2. Single-process mode (development) | 
|  | 75 | +uvicorn myapp:app --port 8000 | 
|  | 76 | + | 
|  | 77 | +3. Multiprocess mode (production) | 
|  | 78 | +export PROMETHEUS_MULTIPROC_DIR=./metrics_data  # Persistent storage | 
|  | 79 | +mkdir -p $PROMETHEUS_MULTIPROC_DIR | 
|  | 80 | +uvicorn myapp:app --port 8000 --workers 4 | 
|  | 81 | + | 
|  | 82 | +4. Generate load for verification | 
|  | 83 | +for i in {1..100}; do curl -s http://localhost:8000/ & done | 
|  | 84 | + | 
|  | 85 | +5. Verify aggregated metrics | 
|  | 86 | +curl -s http://localhost:8000/metrics/ | grep -E 'http_requests_total|system_cpu_usage_percent' | 
|  | 87 | +``` | 
|  | 88 | + | 
|  | 89 | +### Expected Output | 
|  | 90 | +```text | 
|  | 91 | +TYPE http_requests_total counter | 
|  | 92 | +http_requests_total{endpoint="/"} 100.0 | 
|  | 93 | +
 | 
|  | 94 | +TYPE system_cpu_usage_percent gauge | 
|  | 95 | +system_cpu_usage_percent 68.5  # Aggregated across workers | 
|  | 96 | +``` | 
|  | 97 | + | 
|  | 98 | +### Production Checklist | 
|  | 99 | +1. **Directory Configuration**   | 
|  | 100 | +   ```bash | 
|  | 101 | +   chmod 750 ./metrics_data  # Secure write permissions | 
|  | 102 | +   ``` | 
|  | 103 | +2. **Storage Management**   | 
|  | 104 | +   - Use dedicated volume for `PROMETHEUS_MULTIPROC_DIR` | 
|  | 105 | +   - Implement cleanup cron job: | 
|  | 106 | +     ```bash | 
|  | 107 | +     0 * * * * find /path/to/metrics_data -name '*.db' -mtime +7 -delete | 
|  | 108 | +     ``` | 
|  | 109 | +3. **Validation Tools**   | 
|  | 110 | +   ```bash | 
|  | 111 | +   # Check active worker count | 
|  | 112 | +   ps aux | grep -c '[u]vicorn.*worker' | 
|  | 113 | +
 | 
|  | 114 | +   # Monitor data files | 
|  | 115 | +   watch -n 5 'ls -lh $PROMETHEUS_MULTIPROC_DIR | grep .db' | 
|  | 116 | +   ``` | 
|  | 117 | + | 
|  | 118 | +### Troubleshooting | 
|  | 119 | +| Symptom                | Solution                      | Verification Command             | | 
|  | 120 | +|------------------------|-------------------------------|-----------------------------------| | 
|  | 121 | +| PID labels in metrics  | Add `multiprocess_mode` param | `grep 'multiprocess_mode' myapp.py` | | 
|  | 122 | +| Missing .db files      | Check directory permissions   | `ls -ld $PROMETHEUS_MULTIPROC_DIR` | | 
|  | 123 | +| Stale values           | Verify endpoint activation    | `curl -I http://localhost:8000/`   | | 
0 commit comments