Skip to main content

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.

PyPI version Python 3.10+ License: MIT

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 method
  • path: Request path
  • http_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

  1. Check metrics endpoint: curl http://localhost:8000/metrics
  2. Verify Prometheus can reach your app
  3. Check Prometheus scrape config
  4. 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


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

rl_autoscale-1.0.3.tar.gz (15.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rl_autoscale-1.0.3-py3-none-any.whl (12.0 kB view details)

Uploaded Python 3

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

Hashes for rl_autoscale-1.0.3.tar.gz
Algorithm Hash digest
SHA256 9aa9d523cb446bf8cdd7394c4b82196a33b8250fd161d16b3993da4084ae0b3a
MD5 9f47e9baa4a86a55fc984acca5de1fa1
BLAKE2b-256 7b52cc1a1a80f6564e57da52266a8fd2aba1a98a107bc51e7ce0caa95bcf438d

See more details on using hashes here.

Provenance

The following attestation bundles were made for rl_autoscale-1.0.3.tar.gz:

Publisher: publish.yml on ghazafm/rl-autoscale

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for rl_autoscale-1.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 dccacac965bfc4ebc2a7bc66a79a50a593aa0eccfe2d095d55f834c3b803ea1d
MD5 e755c63d9f0014ba495c357eca0e2a86
BLAKE2b-256 2521a7f817901ba6b233d79ce95f399848ac416e130424fba221ccfd5e97527d

See more details on using hashes here.

Provenance

The following attestation bundles were made for rl_autoscale-1.0.3-py3-none-any.whl:

Publisher: publish.yml on ghazafm/rl-autoscale

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page