python --version
pip install prometheus-client
Add Prometheus metrics to a Python HTTP service: counters, histograms, and gauges for the RED method.
1 import time 2 import random 3 from prometheus_client import ( 4 Counter, Histogram, Gauge, Info, 5 REGISTRY, make_wsgi_app, generate_latest 6 ) 7 from functools import wraps 8 9 # ── Define metrics ────────────────────────────────────────────────── 10 11 http_requests_total = Counter( 12 "http_requests_total", 13 "Total HTTP requests", 14 ["method", "endpoint", "status"], 15 ) 16 17 http_request_duration_seconds = Histogram( 18 "http_request_duration_seconds", 19 "HTTP request duration in seconds", 20 ["method", "endpoint"], 21 # SLO-aligned buckets: 95th% < 200ms, 99th% < 1s 22 buckets=[0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0], 23 ) 24 25 active_connections = Gauge( 26 "active_connections", 27 "Number of active HTTP connections", 28 ) 29 30 app_info = Info("app", "Application information") 31 app_info.info({"version": "2.3.1", "env": "production"}) 32 33 # ── Decorator for automatic instrumentation ───────────────────────── 34 35 def track_request(method: str, endpoint: str): 36 def decorator(func): 37 @wraps(func) 38 def wrapper(*args, **kwargs): 39 active_connections.inc() 40 start = time.perf_counter() 41 status = "200" 42 try: 43 result = func(*args, **kwargs) 44 return result 45 except Exception as e: 46 status = "500" 47 raise 48 finally: 49 duration = time.perf_counter() - start 50 http_requests_total.labels(method, endpoint, status).inc() 51 http_request_duration_seconds.labels(method, endpoint).observe(duration) 52 active_connections.dec() 53 return wrapper 54 return decorator 55 56 # ── Example instrumented handlers ────────────────────────────────── 57 58 @track_request("GET", "/api/orders") 59 def list_orders(): 60 time.sleep(random.uniform(0.01, 0.2)) 61 return {"orders": []} 62 63 @track_request("POST", "/api/orders") 64 def create_order(): 65 time.sleep(random.uniform(0.05, 0.5)) 66 if random.random() < 0.05: # 5% error rate 67 raise ValueError("Database connection failed") 68 return {"order_id": "ORD-001"} 69 70 # Simulate traffic 71 for _ in range(100): 72 try: 73 list_orders() 74 create_order() 75 except Exception: 76 pass 77 78 # Print metrics 79 print(generate_latest(REGISTRY).decode()) 80 81 # Key PromQL queries: 82 # Error rate: sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) 83 # p99 latency: histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le, endpoint)) 84
Sign in to share your feedback and join the discussion.