Production-ready metrics instrumentation for RL-based autoscaling systems
Project description
rl-autoscale
๐ฏ Production-ready metrics instrumentation for RL-based autoscaling systems
A lightweight Python library that provides standardized Prometheus metrics for applications managed by reinforcement learning autoscalers. Works with Flask, FastAPI, and other Python web frameworks.
Features
โ One-Line Integration - Add 2 lines of code, get full observability โ Framework Agnostic - Flask, FastAPI, Django support โ Zero Overhead - Minimal performance impact (<1ms per request) โ Production Ready - Battle-tested with proper error handling โ RL Optimized - Metrics designed specifically for RL autoscaling agents โ Standardized - Consistent metrics across all your microservices
Quick Start
Flask Application
from flask import Flask
from rl_autoscale import enable_metrics
app = Flask(__name__)
# ๐ฏ ONE LINE - that's it!
enable_metrics(app, port=8000)
@app.route("/api/hello")
def hello():
return "Hello World"
if __name__ == "__main__":
app.run()
FastAPI Application
from fastapi import FastAPI
from rl_autoscale import enable_metrics
app = FastAPI()
# ๐ฏ ONE LINE - that's it!
enable_metrics(app, port=8000)
@app.get("/api/hello")
async def hello():
return {"message": "Hello World"}
Installation
# Using pip
pip install rl-autoscale[flask] # For Flask apps
pip install rl-autoscale[fastapi] # For FastAPI apps
# Using uv (recommended - 10x faster!)
uv pip install rl-autoscale[flask]
uv pip install rl-autoscale[fastapi]
# Core only
pip install rl-autoscale
๐ก Tip: This project uses uv for blazingly fast package management. See UV_GUIDE.md for details.
What Metrics Are Exposed?
The library exports these standard Prometheus metrics:
1. http_request_duration_seconds (Histogram)
Request latency distribution used by RL agents to calculate percentiles (p50, p90, p99).
Labels:
method: HTTP method (GET, POST, etc.)path: Request path (e.g.,/api/users)
Buckets: Optimized for web APIs (5ms to 10s)
2. http_requests_total (Counter)
Total request count used for throughput analysis.
Labels:
method: HTTP methodpath: Request pathhttp_status: HTTP status code (200, 404, etc.)
Advanced Usage
Path Normalization
Prevent cardinality explosion by normalizing dynamic paths:
from rl_autoscale import enable_metrics
from rl_autoscale.flask_middleware import normalize_api_paths
app = Flask(__name__)
enable_metrics(
app,
port=8000,
path_normalizer=normalize_api_paths # /user/123 -> /user/:id
)
Custom Configuration
enable_metrics(
app,
port=8000,
namespace="myapp", # Prefix metrics: myapp_http_request_duration_seconds
histogram_buckets=[0.001, 0.01, 0.1, 1.0, 10.0], # Custom buckets
exclude_paths=["/health", "/metrics", "/internal/*"], # Skip these paths
)
Manual Instrumentation
For non-web workloads or custom metrics:
from rl_autoscale import get_metrics_registry
metrics = get_metrics_registry()
# Record a custom operation
with timer():
result = expensive_operation()
duration = timer.elapsed()
metrics.observe_request(
method="BATCH",
path="/jobs/process",
duration=duration,
status_code=200
)
Architecture
โโโโโโโโโโโโโโโโโโโ
โ Your App โ โ Clean business logic (no metrics code!)
โ (Flask/ โ
โ FastAPI) โ
โโโโโโโโโโฌโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโ
โ RL Metrics โ โ This library (automatic instrumentation)
โ Middleware โ
โโโโโโโโโโฌโโโโโโโโโ
โ HTTP :8000/metrics
โผ
โโโโโโโโโโโโโโโโโโโ
โ Prometheus โ โ Scrapes metrics every 15-60s
โ โ
โโโโโโโโโโฌโโโโโโโโโ
โ PromQL queries
โผ
โโโโโโโโโโโโโโโโโโโ
โ RL Agent โ โ Makes autoscaling decisions
โ (DQN/Q-Learning)โ
โโโโโโโโโโโโโโโโโโโ
Why This Library?
Before (Without Library) โ
from prometheus_client import Counter, Histogram, start_http_server
# 50+ lines of boilerplate in EVERY service
REQUEST_LATENCY = Histogram(...)
REQUEST_COUNT = Counter(...)
@app.before_request
def before_request():
request.start_time = time.time()
@app.after_request
def after_request(response):
latency = time.time() - request.start_time
REQUEST_LATENCY.labels(...).observe(latency)
REQUEST_COUNT.labels(...).inc()
return response
start_http_server(8000)
# ... more boilerplate
After (With Library) โ
from rl_autoscale import enable_metrics
enable_metrics(app, port=8000) # Done! ๐
Benefits:
- โ 60+ lines โ 1 line - Massive code reduction
- โ Standardized - Same metrics across all services
- โ Maintainable - Update once, affects all services
- โ Tested - Production-ready error handling
- โ Reusable - Use in Flask, FastAPI, Django
Configuration via Environment Variables
# Metrics port
export RL_METRICS_PORT=8000
# Custom namespace
export RL_METRICS_NAMESPACE=myapp
# Excluded paths (comma-separated)
export RL_METRICS_EXCLUDE_PATHS=/health,/metrics,/internal/*
Kubernetes Deployment
Add Prometheus scrape annotations to your deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
template:
metadata:
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8000"
prometheus.io/path: "/metrics"
spec:
containers:
- name: app
image: myapp:latest
ports:
- containerPort: 5000 # App port
- containerPort: 8000 # Metrics port
Prometheus Queries
Example queries for your RL agent:
# P90 response time over last 5 minutes
histogram_quantile(0.90,
rate(http_request_duration_seconds_bucket[5m])
)
# Requests per second
rate(http_requests_total[1m])
# Error rate (HTTP 5xx)
rate(http_requests_total{http_status=~"5.."}[5m])
Performance
- Overhead: <1ms per request
- Memory: ~10MB baseline
- CPU: Negligible (<0.1% on most workloads)
Tested with 10,000 requests/second with zero performance degradation.
Troubleshooting
Port Already in Use
# If port 8000 is taken, use another port
enable_metrics(app, port=8001)
Metrics Not Showing Up
- Check metrics endpoint:
curl http://localhost:8000/metrics - Verify Prometheus can reach your app
- Check Prometheus scrape config
- Look for errors in application logs
High Cardinality Warning
If you see thousands of unique metric labels:
# Add path normalization
from rl_autoscale.flask_middleware import normalize_api_paths
enable_metrics(app, path_normalizer=normalize_api_paths)
Contributing
See CONTRIBUTING.md for development setup and guidelines.
# Clone repository
git clone https://github.com/ghazafm/rl-autoscale
cd rl-autoscale
# Setup with uv (recommended - one command!)
uv sync --all-extras
# Or traditional way with pip
pip install -e ".[dev,flask,fastapi]"
# Run tests
pytest
# Format and lint code (using ruff for both!)
ruff format .
ruff check .
๐ Quick Start: See QUICK_START.md for fastest setup! ๐ Developer Guide: See UV_GUIDE.md for using uv and ruff effectively.
License
MIT License - See LICENSE file
Support
- ๐ Documentation: https://github.com/ghazafm/rl-autoscale
- ๐ Issues: https://github.com/ghazafm/rl-autoscale/issues
- ๐ฌ Discussions: https://github.com/ghazafm/rl-autoscale/discussions
- ๐ฆ PyPI: https://pypi.org/project/rl-autoscale/
Made with โค๏ธ for RL Autoscaling Systems
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rl_autoscale-1.0.3.tar.gz.
File metadata
- Download URL: rl_autoscale-1.0.3.tar.gz
- Upload date:
- Size: 15.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9aa9d523cb446bf8cdd7394c4b82196a33b8250fd161d16b3993da4084ae0b3a
|
|
| MD5 |
9f47e9baa4a86a55fc984acca5de1fa1
|
|
| BLAKE2b-256 |
7b52cc1a1a80f6564e57da52266a8fd2aba1a98a107bc51e7ce0caa95bcf438d
|
Provenance
The following attestation bundles were made for rl_autoscale-1.0.3.tar.gz:
Publisher:
publish.yml on ghazafm/rl-autoscale
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rl_autoscale-1.0.3.tar.gz -
Subject digest:
9aa9d523cb446bf8cdd7394c4b82196a33b8250fd161d16b3993da4084ae0b3a - Sigstore transparency entry: 682411782
- Sigstore integration time:
-
Permalink:
ghazafm/rl-autoscale@ca9ae6ea65075ecfafab1b79e0eb6530415cc447 -
Branch / Tag:
refs/tags/v1.0.3 - Owner: https://github.com/ghazafm
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ca9ae6ea65075ecfafab1b79e0eb6530415cc447 -
Trigger Event:
push
-
Statement type:
File details
Details for the file rl_autoscale-1.0.3-py3-none-any.whl.
File metadata
- Download URL: rl_autoscale-1.0.3-py3-none-any.whl
- Upload date:
- Size: 12.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dccacac965bfc4ebc2a7bc66a79a50a593aa0eccfe2d095d55f834c3b803ea1d
|
|
| MD5 |
e755c63d9f0014ba495c357eca0e2a86
|
|
| BLAKE2b-256 |
2521a7f817901ba6b233d79ce95f399848ac416e130424fba221ccfd5e97527d
|
Provenance
The following attestation bundles were made for rl_autoscale-1.0.3-py3-none-any.whl:
Publisher:
publish.yml on ghazafm/rl-autoscale
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rl_autoscale-1.0.3-py3-none-any.whl -
Subject digest:
dccacac965bfc4ebc2a7bc66a79a50a593aa0eccfe2d095d55f834c3b803ea1d - Sigstore transparency entry: 682411823
- Sigstore integration time:
-
Permalink:
ghazafm/rl-autoscale@ca9ae6ea65075ecfafab1b79e0eb6530415cc447 -
Branch / Tag:
refs/tags/v1.0.3 - Owner: https://github.com/ghazafm
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ca9ae6ea65075ecfafab1b79e0eb6530415cc447 -
Trigger Event:
push
-
Statement type: