Drop-in middleware for FastAPI and Django.
CPU, memory, p95/p99 latency, and Prometheus export โ zero configuration.
pip install rust-py-monitor
Rust does the heavy lifting. Python stays simple.
CPU usage, RSS memory, virtual memory, thread count, and PID โ sampled directly from the OS via the
sysinfo Rust crate.
Add MonitorMiddleware in one line. Captures method, path, status code, and latency for every
request with ASGI-native performance.
Works with both WSGI and ASGI Django apps. Drop it first in your MIDDLEWARE list and it wraps
the full request lifecycle.
The aggregator runs in Rust โ sorting, percentile calculation, and error rate are computed without any Python overhead on the hot path.
One router include gives your FastAPI app a /metrics endpoint. Django gets a view function. No
separate process, no config file.
The collection and aggregation logic lives in Rust and compiles to a native .so extension.
Users just pip install โ no Rust needed.
Three lines to get started with any Python web framework.
from fastapi import FastAPI
from rust_py_monitor.fastapi import MonitorMiddleware
from rust_py_monitor.prometheus import make_fastapi_router
app = FastAPI()
# 1. Add monitoring middleware
app.add_middleware(MonitorMiddleware)
# 2. Expose /metrics endpoint for Prometheus
app.include_router(make_fastapi_router())
@app.get("/users")
async def list_users():
return [{"id": 1, "name": "Alice"}]
# settings.py
MIDDLEWARE = [
"rust_py_monitor.django.MonitorMiddleware",
# ... rest of your middleware
]
# urls.py
from django.urls import path
from rust_py_monitor.prometheus import django_metrics_view
urlpatterns = [
path("metrics/", django_metrics_view),
# ... your routes
]
import rust_py_monitor
# Process snapshot
m = rust_py_monitor.snapshot()
print(m.pid) # 8421
print(m.cpu_percent) # 1.3
print(m.memory_rss_mb) # 48.2
print(m.to_dict()) # {"pid": 8421, ...}
# Aggregated request stats
stats = rust_py_monitor.aggregate()
print(stats.total_requests) # 1024
print(stats.error_rate) # 1.17
print(stats.p95_latency_ms) # 47.3
print(stats.p99_latency_ms) # 92.1
# All recorded requests
for req in rust_py_monitor.get_requests()[-5:]:
print(req) # RequestMetric(GET /api/users 200 12.34ms)
Scrape /metrics directly โ compatible with any Prometheus setup.
rpy_requests_total counterrpy_errors_total counterrpy_error_rate_percent gaugerpy_latency_avg_ms gaugerpy_latency_p50_ms gaugerpy_latency_p95_ms gaugerpy_latency_p99_ms gaugerpy_latency_min_ms gaugerpy_latency_max_ms gaugerpy_process_cpu_percent gaugerpy_process_memory_rss_bytes gaugerpy_process_memory_virtual_bytes gaugerpy_process_threads gauge# HELP rpy_requests_total Total HTTP requests recorded
# TYPE rpy_requests_total counter
rpy_requests_total 1024
# HELP rpy_errors_total Total HTTP errors (status >= 400)
# TYPE rpy_errors_total counter
rpy_errors_total 12
# HELP rpy_latency_p95_ms P95 request latency in ms
# TYPE rpy_latency_p95_ms gauge
rpy_latency_p95_ms 47.3
# HELP rpy_latency_p99_ms P99 request latency in ms
# TYPE rpy_latency_p99_ms gauge
rpy_latency_p99_ms 92.1
# HELP rpy_process_memory_rss_bytes Process RSS memory
# TYPE rpy_process_memory_rss_bytes gauge
rpy_process_memory_rss_bytes 50331648
Rust collects and aggregates. Python integrates. You observe.
The native .so extension is compiled once at publish time via maturin +
PyO3.
Your users just pip install โ no Rust toolchain required.
Install from PyPI. No Rust, no compilers, no configuration.