rust-py-monitor
High-performance Python monitoring library with a Rust core.
Collects CPU, memory, threads, and HTTP request metrics from Django and FastAPI applications with minimal overhead. Exports metrics to logs, JSON, and Prometheus.
Features
- Process snapshot — CPU %, RSS memory, virtual memory, thread count, PID
- FastAPI middleware — per-request latency, method, path, status code (errors recorded even when a handler raises)
- Django middleware — same, for WSGI and ASGI Django apps
- Aggregator — total requests, error count, error rate, avg/min/max/p50/p95/p99 latency
- Bounded store — request history is a capped ring buffer (default 10k) — constant memory under any traffic
- Multi-worker aggregation — opt-in shared store merges metrics across gunicorn/uvicorn workers (
RPY_MULTIPROC_DIR) - Prometheus exporter —
/metricsendpoint compatible with Prometheus scraper - Threshold alerts —
check_alerts(...)flags high CPU / memory against your limits - Rust core — collection and aggregation happen in Rust via PyO3; Python API stays simple
Requirements
- Python 3.10+
- No mandatory runtime dependencies
Optional, installed separately:
fastapi+starlette— forMonitorMiddlewareandmake_fastapi_router()django— forMonitorMiddlewareanddjango_metrics_view
Installation
pip install rust-py-monitor
With optional extras:
pip install "rust-py-monitor[fastapi]"
pip install "rust-py-monitor[django]"
pip install "rust-py-monitor[fastapi,django,prometheus]"
Quick Start
import rust_py_monitor
# Process snapshot
m = rust_py_monitor.snapshot()
print(m)
# Snapshot(pid=1234, cpu=0.3%, rss=45.2MB, virt=512.0MB, threads=4, ts=1718000000)
print(m.pid) # 1234
print(m.memory_rss_mb) # 45.2
print(m.to_dict()) # {"pid": 1234, "cpu_percent": 0.3, ...}
# Aggregated request metrics
stats = rust_py_monitor.aggregate()
print(stats.total_requests) # 0 (no middleware active yet)
print(stats.p95_latency_ms) # 0.0
FastAPI
Middleware
from fastapi import FastAPI
from rust_py_monitor.fastapi import MonitorMiddleware
app = FastAPI()
app.add_middleware(MonitorMiddleware)
@app.get("/")
async def root():
return {"status": "ok"}
Prometheus endpoint
from fastapi import FastAPI
from rust_py_monitor.fastapi import MonitorMiddleware
from rust_py_monitor.prometheus import make_fastapi_router
app = FastAPI()
app.add_middleware(MonitorMiddleware)
app.include_router(make_fastapi_router()) # GET /metrics
# app.include_router(make_fastapi_router("/prom")) # custom path
Inspect metrics programmatically
import rust_py_monitor
stats = rust_py_monitor.aggregate()
print(f"Requests: {stats.total_requests}")
print(f"Errors: {stats.total_errors} ({stats.error_rate:.1f}%)")
print(f"p95: {stats.p95_latency_ms:.1f}ms")
print(f"p99: {stats.p99_latency_ms:.1f}ms")
for req in rust_py_monitor.get_requests()[-5:]:
print(req)
# RequestMetric(GET /api/users 200 12.34ms)
Django
Middleware
# settings.py
MIDDLEWARE = [
"rust_py_monitor.django.MonitorMiddleware",
# ... other middlewares ...
]
Prometheus endpoint
# urls.py
from django.urls import path
from rust_py_monitor.prometheus import django_metrics_view
urlpatterns = [
path("metrics/", django_metrics_view),
# ...
]
The middleware supports both WSGI and ASGI Django applications automatically.
Prometheus Output
GET /metrics returns:
# 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_error_rate_percent HTTP error rate as a percentage
# TYPE rpy_error_rate_percent gauge
rpy_error_rate_percent 1.171875
# HELP rpy_latency_p95_ms P95 request latency in milliseconds
# TYPE rpy_latency_p95_ms gauge
rpy_latency_p95_ms 47.3
# HELP rpy_process_memory_rss_bytes Process RSS memory in bytes
# TYPE rpy_process_memory_rss_bytes gauge
rpy_process_memory_rss_bytes 52428800
# ... (13 metrics total)
Content-Type: text/plain; version=0.0.4; charset=utf-8
API Reference
rust_py_monitor.snapshot() → Snapshot
Captures a point-in-time snapshot of the current process.
| Property | Type | Description |
|---|---|---|
pid |
int |
Process ID |
cpu_percent |
float |
CPU usage (0–100 × cores). First call may return 0.0. |
memory_rss |
int |
Resident Set Size in bytes |
memory_rss_mb |
float |
RSS in megabytes (convenience) |
memory_virtual |
int |
Virtual memory in bytes |
threads |
int |
Thread count (0 on macOS/Windows) |
timestamp |
int |
Unix timestamp in seconds |
to_dict() |
dict |
All fields as a plain dict |
rust_py_monitor.aggregate() → AggregatedMetrics
Computes statistics over all requests recorded since startup (or last clear_requests()).
| Property | Type | Description |
|---|---|---|
total_requests |
int |
Total request count |
total_errors |
int |
Requests with status ≥ 400 |
error_rate |
float |
total_errors / total_requests × 100 |
avg_latency_ms |
float |
Mean latency |
min_latency_ms |
float |
Minimum latency |
max_latency_ms |
float |
Maximum latency |
p50_latency_ms |
float |
Median latency |
p95_latency_ms |
float |
95th percentile latency |
p99_latency_ms |
float |
99th percentile latency |
to_dict() |
dict |
All fields as a plain dict |
rust_py_monitor.get_requests() → list[RequestMetric]
Returns all recorded requests. Each RequestMetric has:
| Property | Type |
|---|---|
method |
str |
path |
str |
status_code |
int |
duration_ms |
float |
timestamp |
int |
to_dict() |
dict |
rust_py_monitor.metrics_text() → str
Returns all metrics in Prometheus text exposition format (v0.0.4).
rust_py_monitor.check_alerts(cpu_percent=None, memory_rss_mb=None, memory_virtual_mb=None) → list[dict]
Simple, stateless threshold alerts over the current process snapshot. Pass the thresholds you want to watch; it returns the alerts that fired (a metric exceeds its threshold). Memory thresholds are in megabytes. Only the thresholds you provide are evaluated.
import rust_py_monitor
fired = rust_py_monitor.check_alerts(cpu_percent=80, memory_rss_mb=500)
# [{"metric": "memory_rss_mb", "value": 612.4, "threshold": 500, "severity": "warning"}]
for alert in fired:
print(f"[alert] {alert['metric']}={alert['value']} > {alert['threshold']}")
Each alert is a dict {"metric", "value", "threshold", "severity"}, where
metric is one of "cpu_percent", "memory_rss_mb", "memory_virtual_mb".
Being stateless, you decide when to call it (in a /health handler, a periodic
task, etc.) and what to do with the result.
rust_py_monitor.clear_requests()
Clears the request store. Useful for testing and periodic resets.
rust_py_monitor.set_max_requests(n) / get_max_requests() → int
The request store is a bounded ring buffer (default capacity 10 000). Once full, the oldest entries are evicted first, so memory never grows without bound. Use these to tune the retention window.
Multi-worker deployments (gunicorn / uvicorn)
By default each worker process keeps its own in-memory store. A Prometheus
scrape of /metrics reaches only one worker, so the numbers would reflect just
that worker's traffic.
Set the RPY_MULTIPROC_DIR environment variable to a writable directory to
enable shared aggregation. Each worker writes a small fixed-size shard file
(rpy-<pid>.shard); aggregate() and metrics_text() then merge all live
workers' shards at read time. Shards of dead workers are pruned automatically.
export RPY_MULTIPROC_DIR=/tmp/rpy-metrics
gunicorn -w 4 myapp:app
You can also configure it at runtime:
import rust_py_monitor
rust_py_monitor.set_multiproc_dir("/tmp/rpy-metrics")
rust_py_monitor.multiproc_enabled() # True
rust_py_monitor.get_multiproc_dir() # "/tmp/rpy-metrics"
Notes:
- Counters (
total_requests,total_errors) and latency histogram buckets are summed across workers. Latency percentiles (p50/p95/p99) are therefore approximated from the merged histogram rather than computed exactly. get_requests()always returns the local process's recent requests only.- Process metrics (CPU/memory/threads) reflect the worker that served the scrape.
Roadmap
rust-py-monitor is mature (v0.2.0): process snapshots, FastAPI/Django
middlewares, the latency aggregator, the bounded ring-buffer store, multi-worker
aggregation, and the Prometheus exporter are shipped. Directional ideas under
consideration (simple CPU/memory alerts, GC metrics, per-route labeled metrics,
more exporters/sinks, a Flask middleware) are tracked in
ROADMAP.md.
Building from Source
Requires Rust and maturin.
pip install maturin
git clone https://github.com/robertolima-dev/rust-py-monitor
cd rust-py-monitor
# Development build (installs into current Python environment)
maturin develop
# Release wheel
maturin build --release
Running tests
# Rust unit tests
cargo test
# Python integration tests
pip install pytest pytest-asyncio httpx fastapi django
pytest tests/
Architecture
Python API (rust_py_monitor)
├── snapshot() ──► src/snapshot.rs (sysinfo crate)
├── aggregate() ──► src/aggregator.rs (pure Rust math)
├── get_requests() ──► src/request_metrics.rs (static Mutex<VecDeque>, bounded)
├── metrics_text() ──► src/prometheus.rs (text formatter)
├── set_multiproc_dir() ──► src/multiproc.rs (mmap shard per worker)
│
├── fastapi.MonitorMiddleware ──► record_request() ──► Rust store
├── django.MonitorMiddleware ──► record_request() ──► Rust store
└── prometheus.make_fastapi_router() / django_metrics_view
The Rust core is compiled to a native .so / .pyd extension module by maturin and PyO3. The Python layer is thin — it just routes calls and provides framework-specific adapters.
License
MIT — see LICENSE.
Release files for rust-py-monitor 0.4.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| rust_py_monitor-0.4.2.tar.gz | 58.9 kB | Details |
Built distributions (wheels)
Total release size: 4.4 MB
Release files / rust_py_monitor-0.4.2.tar.gz
| Download URL | rust_py_monitor-0.4.2.tar.gz |
|---|---|
| Size | 58.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7671aa83db1b643558971f4903bea439075f1aeb027c2ea4586b78e3b6552450
|
|
BLAKE2b-256 checksum How to use checksums |
9fd8d57378528320b86ef3c14f75adcbe5c1f896b06c8ed40127394ab0b1c98e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.14.1
|
Release files / rust_py_monitor-0.4.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | rust_py_monitor-0.4.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 393.2 kB |
| Tags | Linux glibc 2.17+ x86-64 PyPy 3.11 PyPy 3.11 7.3 |
|
SHA-256 checksum How to use checksums |
14a2d5edae205df9f1b7cb31c67e090ec8012b33e0d670c7a06b502d65957c40
|
|
BLAKE2b-256 checksum How to use checksums |
a4af114ee8cf0fbac9232e44063400f54bf8224732676e63d8bc6ae79091ebb6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.14.1
|
Release files / rust_py_monitor-0.4.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | rust_py_monitor-0.4.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 384.0 kB |
| Tags | Linux glibc 2.17+ ARM64 PyPy 3.11 PyPy 3.11 7.3 |
|
SHA-256 checksum How to use checksums |
59402db8d1630f90f780adb8ade992ad5285a8db19d38777e1fb9eb92273a08b
|
|
BLAKE2b-256 checksum How to use checksums |
d2661e4db3b1a3b3d7c043d894fa23d38a6880e87aeb48a64f950e6cc170d5b2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.14.1
|
Release files / rust_py_monitor-0.4.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | rust_py_monitor-0.4.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 396.5 kB |
| Tags | Linux glibc 2.17+ x86-64 PyPy 3.10 PyPy 3.10 7.3 |
|
SHA-256 checksum How to use checksums |
3df77f779e9115798a5365caea54a86bb16fd567b1124ce0b71080e3aa817e5f
|
|
BLAKE2b-256 checksum How to use checksums |
226c68004ffa3ba9260fbe06f081fa0e332ceac6ecb7414fcee8f2a1ee90a352
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.14.1
|
Release files / rust_py_monitor-0.4.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | rust_py_monitor-0.4.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 386.6 kB |
| Tags | Linux glibc 2.17+ ARM64 PyPy 3.10 PyPy 3.10 7.3 |
|
SHA-256 checksum How to use checksums |
44a0b553edf1c4dfefa930b0111ee878443c42fcf806080a9ce3ed51dafe0bc6
|
|
BLAKE2b-256 checksum How to use checksums |
a710520e7d9735376ed8e54caf4824b2c10f06f24d39baae5d64bc72da49edfb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.14.1
|
Release files / rust_py_monitor-0.4.2-cp310-abi3-win_amd64.whl
| Download URL | rust_py_monitor-0.4.2-cp310-abi3-win_amd64.whl |
|---|---|
| Size | 218.0 kB |
| Tags | CPython 3.10 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
ed29155d7b5b1ae0d23c7e0cef71d6ebe4e09ff2b091754929163bce1c289e6c
|
|
BLAKE2b-256 checksum How to use checksums |
ae585ac4496c82657aef0d718dbf54295652a079522b444431d0ed83ffd6a19e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.14.1
|
Release files / rust_py_monitor-0.4.2-cp310-abi3-musllinux_1_2_x86_64.whl
| Download URL | rust_py_monitor-0.4.2-cp310-abi3-musllinux_1_2_x86_64.whl |
|---|---|
| Size | 600.2 kB |
| Tags | CPython 3.10 Linux musl 1.2+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
0025dcd110aa732ada7ad4b9aa4ab393d65eae9671c9f039fc954c918a4fd212
|
|
BLAKE2b-256 checksum How to use checksums |
0d672695e330aa1b44ce0a9f87c563e43a23110cab17dae35f9173548ba341eb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.14.1
|
Release files / rust_py_monitor-0.4.2-cp310-abi3-musllinux_1_2_aarch64.whl
| Download URL | rust_py_monitor-0.4.2-cp310-abi3-musllinux_1_2_aarch64.whl |
|---|---|
| Size | 563.9 kB |
| Tags | CPython 3.10 Linux musl 1.2+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
d20287beff656f3fdb67d4077c1da76f25e0524bc0b0b76010d371c5cb5c7e24
|
|
BLAKE2b-256 checksum How to use checksums |
c938b45fa629675583919ba8f652a2d29e7936bda3f87414c80a554772290b73
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.14.1
|
Release files / rust_py_monitor-0.4.2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | rust_py_monitor-0.4.2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 397.2 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
e3bb4c2f83b8efbb559a54e1643ae5b897e2789b1844da4b4b2a9b1151c874bf
|
|
BLAKE2b-256 checksum How to use checksums |
87e79d86b3fe46ce145808817e8abd9c3661db0a3b5d3bbc90c69c70dd78f244
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.14.1
|
Release files / rust_py_monitor-0.4.2-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | rust_py_monitor-0.4.2-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 387.2 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
4b90c8d095102057ff60a05815ebc5594a5da5e428dac194ae2249fcb0d24d48
|
|
BLAKE2b-256 checksum How to use checksums |
74447c39e8bf5b21e9c2c96b30353aa3fa87939ebb8748ae742f307a74245c07
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.14.1
|
Release files / rust_py_monitor-0.4.2-cp310-abi3-macosx_11_0_arm64.whl
| Download URL | rust_py_monitor-0.4.2-cp310-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 308.7 kB |
| Tags | CPython 3.10 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
46566940b6fc229709f60707d9ca3af8358159c8b9d688880e7fabb26e26f583
|
|
BLAKE2b-256 checksum How to use checksums |
1212468dd3f9fefd19f86769c8416076875be6d815283394ed06f4ed16e526cb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.14.1
|
Release files / rust_py_monitor-0.4.2-cp310-abi3-macosx_10_12_x86_64.whl
| Download URL | rust_py_monitor-0.4.2-cp310-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 311.6 kB |
| Tags | CPython 3.10 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
e2c709ef6aadff1bd77ace6ab6fc9361e5203306e879d105c42f26bfeae9539a
|
|
BLAKE2b-256 checksum How to use checksums |
9ecd05f0e7b9fd2c7fae3fc70dfd91ff8d53d0d47aa2c116a2913fa1b4a650f5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.14.1
|