Framework Guide
Python API Monitoring
Set up health check endpoints and uptime monitoring for your Python web application. Examples for Flask, FastAPI, and Django.
Why Monitor Your Python App?
Python web applications can fail in subtle ways that are hard to detect without external monitoring. A WSGI server might appear running while the application itself is stuck, or a memory leak in a long-running process can gradually degrade performance until the app becomes unresponsive.
- GIL contention -- CPU-bound tasks can block all threads in a Python process, making the app unresponsive
- Memory leaks -- Long-running Python processes can accumulate objects that the garbage collector never frees
- Worker exhaustion -- Gunicorn or uWSGI workers can all become busy with slow requests, leaving no capacity for new ones
- Dependency failures -- Database, Redis, or third-party API outages cascade through your application
Flask Health Endpoint
from flask import Flask, jsonify
from datetime import datetime
app = Flask(__name__)
@app.route('/health')
def health():
return jsonify({
'status': 'healthy',
'timestamp': datetime.utcnow().isoformat()
})
@app.route('/ready')
def ready():
checks = {}
# Check database
try:
db.session.execute('SELECT 1')
checks['database'] = 'ok'
except Exception as e:
checks['database'] = str(e)
return jsonify({'status': 'unhealthy', 'checks': checks}), 503
return jsonify({'status': 'healthy', 'checks': checks})
FastAPI Health Endpoint
from fastapi import FastAPI, Response
from datetime import datetime
from pydantic import BaseModel
app = FastAPI()
class HealthResponse(BaseModel):
status: str
timestamp: str
@app.get("/health", response_model=HealthResponse)
async def health():
return {
"status": "healthy",
"timestamp": datetime.utcnow().isoformat()
}
@app.get("/ready")
async def ready(response: Response):
checks = {}
healthy = True
# Check database
try:
await database.execute("SELECT 1")
checks["database"] = "ok"
except Exception as e:
checks["database"] = str(e)
healthy = False
if not healthy:
response.status_code = 503
return {
"status": "healthy" if healthy else "unhealthy",
"checks": checks
}
Django Health Endpoint
# views.py
from django.http import JsonResponse
from django.db import connection
from datetime import datetime
def health(request):
return JsonResponse({
'status': 'healthy',
'timestamp': datetime.utcnow().isoformat()
})
def ready(request):
checks = {}
# Check database
try:
with connection.cursor() as cursor:
cursor.execute('SELECT 1')
checks['database'] = 'ok'
except Exception as e:
checks['database'] = str(e)
return JsonResponse({
'status': 'unhealthy',
'checks': checks
}, status=503)
return JsonResponse({
'status': 'healthy',
'checks': checks
})
# urls.py
urlpatterns = [
path('health/', views.health),
path('ready/', views.ready),
]
Comprehensive Health Check
import psutil
import time
from datetime import datetime
def comprehensive_health():
start_time = time.time()
health = {
'status': 'healthy',
'timestamp': datetime.utcnow().isoformat(),
'checks': {},
'system': {
'cpu_percent': psutil.cpu_percent(),
'memory_percent': psutil.virtual_memory().percent,
'disk_percent': psutil.disk_usage('/').percent
}
}
# Check database
try:
db_start = time.time()
db.session.execute('SELECT 1')
health['checks']['database'] = {
'status': 'ok',
'response_time_ms': (time.time() - db_start) * 1000
}
except Exception as e:
health['status'] = 'unhealthy'
health['checks']['database'] = {
'status': 'error',
'message': str(e)
}
# Check Redis
try:
redis_start = time.time()
redis_client.ping()
health['checks']['redis'] = {
'status': 'ok',
'response_time_ms': (time.time() - redis_start) * 1000
}
except Exception as e:
health['status'] = 'unhealthy'
health['checks']['redis'] = {
'status': 'error',
'message': str(e)
}
health['response_time_ms'] = (time.time() - start_time) * 1000
return health
Best Practices
- Use async where possible — Async health checks won't block your event loop
- Add timeouts — Use asyncio.wait_for() or signal.alarm()
- Return proper status codes — 200 for healthy, 503 for unhealthy
- Include version info — Helps debug deployment issues