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.1
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.1.tar.gz | 55.2 kB | Details |
Built distributions (wheels)
Total release size: 4.4 MB
Release files / rust_py_monitor-0.4.1.tar.gz
| Download URL | rust_py_monitor-0.4.1.tar.gz |
|---|---|
| Size | 55.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fcc74200021d0a326e6f727a51eeb9c1176dedbcabf875fff351b68f8520cbc5
|
|
BLAKE2b-256 checksum How to use checksums |
a377f8a8f9794894b79122c0a56064de1c284a8623a40e25d65c28dcaa20e94e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.14.1
|
Release files / rust_py_monitor-0.4.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | rust_py_monitor-0.4.1-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 |
9887182d1ab2192759e542f32a65f39669316a9ff35c4faecf447772e15caee7
|
|
BLAKE2b-256 checksum How to use checksums |
c69a4c944dabc739428d46044ffa3b1b550e2a5c33620b6fa3aadc07c3561c42
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.14.1
|
Release files / rust_py_monitor-0.4.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | rust_py_monitor-0.4.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 384.2 kB |
| Tags | Linux glibc 2.17+ ARM64 PyPy 3.11 PyPy 3.11 7.3 |
|
SHA-256 checksum How to use checksums |
c3d6af636654902a3c0a2762890bf1d23d9caeffed5ffcc00122da20b5620c6d
|
|
BLAKE2b-256 checksum How to use checksums |
c5694e35f9d6d9dc7e289f8f7fed59cdaccc6a77633916fbe92e857b29fcb8ed
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.14.1
|
Release files / rust_py_monitor-0.4.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | rust_py_monitor-0.4.1-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 |
5d59605c9b9d77c10a603a7296f236b92056b609201e37a2ebadb137b0bf9eab
|
|
BLAKE2b-256 checksum How to use checksums |
b2ab876d2dea6ebfa0238afcd8e24acb4be046f032b88f91c30771b06559b0ba
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.14.1
|
Release files / rust_py_monitor-0.4.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | rust_py_monitor-0.4.1-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 |
5b3c484297a3e7cb8af4e2249ead29c9eb825ede5bac16dcb0669335ca7baf95
|
|
BLAKE2b-256 checksum How to use checksums |
cd1b4b273834fd2357524732d530a4abeefb273f9c5aabc690e7f13a112d9575
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.14.1
|
Release files / rust_py_monitor-0.4.1-cp310-abi3-win_amd64.whl
| Download URL | rust_py_monitor-0.4.1-cp310-abi3-win_amd64.whl |
|---|---|
| Size | 218.0 kB |
| Tags | CPython 3.10 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
8ebb0a7e35241daab7e5af63599f259feb84e71ea909a333dd3f76ad49b838c6
|
|
BLAKE2b-256 checksum How to use checksums |
e65f25dea3ddd912bdac13afdc1b20e713321d88366ef035872d4404db56f05e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.14.1
|
Release files / rust_py_monitor-0.4.1-cp310-abi3-musllinux_1_2_x86_64.whl
| Download URL | rust_py_monitor-0.4.1-cp310-abi3-musllinux_1_2_x86_64.whl |
|---|---|
| Size | 600.3 kB |
| Tags | CPython 3.10 Linux musl 1.2+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
aeee5230de340b67933a40cd9054c5eca9cd974bb03016b027a526558b8f6dea
|
|
BLAKE2b-256 checksum How to use checksums |
629531f38e9546f716966baae164dd3a3e38393d40fa67034c044124dc5e01ad
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.14.1
|
Release files / rust_py_monitor-0.4.1-cp310-abi3-musllinux_1_2_aarch64.whl
| Download URL | rust_py_monitor-0.4.1-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 |
dbe567a37977104035dad8a709778b774d549df4ad2f0f0a8300ecac8cef0afd
|
|
BLAKE2b-256 checksum How to use checksums |
6e08fd5f58156026c6e36bdd3a9a2fe1d1e8ed80a006b08e67b406150931db71
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.14.1
|
Release files / rust_py_monitor-0.4.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | rust_py_monitor-0.4.1-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 |
34a373c8c6d3adbacb5049b7571877d781a48382d6c9d3455a1c5c20e0ef0a43
|
|
BLAKE2b-256 checksum How to use checksums |
565a88856f9d319b18346239ab73e460574490ba7f8d3698469d503d9596e9bd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.14.1
|
Release files / rust_py_monitor-0.4.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | rust_py_monitor-0.4.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 387.4 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
f3e032a61b6a38739f9ac27cc21a0228d9ed9454b2223a19d17bce952904d9e1
|
|
BLAKE2b-256 checksum How to use checksums |
570a561c5c683cd6ffb228175d39ae315d652e93554e913a698fdb4453b7dc66
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.14.1
|
Release files / rust_py_monitor-0.4.1-cp310-abi3-macosx_11_0_arm64.whl
| Download URL | rust_py_monitor-0.4.1-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 |
7690f625378cf3b21078d81a40d38299b62156fc582ce2f521ff97135879c7bc
|
|
BLAKE2b-256 checksum How to use checksums |
95df3ba697c2230b531e8b6e4c60d9e7972cc3423ea9728c300e405af9334539
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.14.1
|
Release files / rust_py_monitor-0.4.1-cp310-abi3-macosx_10_12_x86_64.whl
| Download URL | rust_py_monitor-0.4.1-cp310-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 311.7 kB |
| Tags | CPython 3.10 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
4a2cb79627ceab7d015dd6afcaeb776fbcc0214fd3d3456323c651f8759391d1
|
|
BLAKE2b-256 checksum How to use checksums |
88bfb22b3720ae8b9bd96018276b5c494c5a8223f3640034425d80793373721d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.14.1
|