Zero-intrusion performance monitoring for Python web frameworks
Project description
Web Performance Monitor
A lightweight performance monitoring library for Python web frameworks based on pyinstrument.
Features
- Zero-intrusion monitoring - Add performance monitoring without modifying your application code
- Automatic profiling - Captures detailed call stacks when response time exceeds threshold
- Alert deduplication - Prevents alert fatigue with configurable time windows
- Multiple notification channels - Local files, Mattermost, and extensible for custom channels
- URL filtering - Whitelist/blacklist patterns to control what gets monitored
- Async notifications - Non-blocking notification delivery
- Multi-framework support - Supports Flask and FastAPI with async/await, extensible for Django, etc.
Installation
pip install web-perfmonitor
For FastAPI support:
pip install web-perfmonitor[fastapi]
For Mattermost notification support:
pip install web-perfmonitor[mattermost]
Quick Start
Flask (Minimal Setup)
from flask import Flask
from web_perfmonitor import PerformanceMiddleware
app = Flask(__name__)
PerformanceMiddleware(app) # That's it!
@app.route("/api/users")
def get_users():
# Your business logic
return {"users": [...]}
if __name__ == "__main__":
app.run()
FastAPI (Async Support)
from fastapi import FastAPI
from web_perfmonitor import PerformanceMiddleware
app = FastAPI()
PerformanceMiddleware(app) # Auto-detects FastAPI
@app.get("/api/users")
async def get_users():
# Your async business logic
return {"users": [...]}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
What happens:
- All endpoints are automatically monitored
- Performance reports are generated when response time exceeds 1 second
- Reports are saved to
/tmpdirectory - For FastAPI, async functions are profiled correctly with full call stack
Custom Configuration
from web_perfmonitor import PerformanceMiddleware, MonitorConfig
config = MonitorConfig(
threshold_seconds=0.5, # 500ms threshold
alert_window_days=7, # 7-day deduplication window
log_path="/var/log/myapp", # Report save directory
url_whitelist=["/api/*"], # Only monitor /api/* endpoints
)
PerformanceMiddleware(app, config=config)
Environment Variables
export PERF_THRESHOLD=0.5
export PERF_ALERT_WINDOW=7
export PERF_LOG_PATH=/var/log/myapp
export PERF_URL_WHITELIST="/api/*"
config = MonitorConfig.from_env()
PerformanceMiddleware(app, config=config)
Notification Channels
Note: Local report saving is automatic and mandatory. Reports are always saved to log_path in both HTML and Markdown formats.
The notice_list is only for external notifiers (Mattermost, Email, Slack, etc.).
Zip Attachment: All external notifiers automatically attach a zip file containing both HTML and Markdown reports for convenient offline viewing and archiving.
Mattermost Notifications
config = MonitorConfig(
log_path="/var/log/perf-reports", # Local reports saved here (mandatory)
notice_list=[
# External notifiers only
{
"type": "mattermost",
"format": "markdown",
"server_url": "https://mattermost.example.com",
"token": "your-api-token",
"channel_id": "your-channel-id"
}
]
)
Email Notifications
config = MonitorConfig(
log_path="/var/log/perf-reports",
notice_list=[
{
"type": "email",
"format": "html", # or "text"
"smtp_host": "smtp.example.com",
"smtp_port": 587,
"username": "alerts@example.com",
"password": "your-password",
"sender": "alerts@example.com",
"recipients": ["dev@example.com", "ops@example.com"],
"use_tls": True,
"subject_prefix": "[Perf Alert]"
}
]
)
Email Configuration Options:
| Parameter | Type | Default | Description |
|---|---|---|---|
| smtp_host | str | - | SMTP server hostname (required) |
| smtp_port | int | 587 | SMTP server port |
| username | str | - | SMTP authentication username |
| password | str | - | SMTP authentication password |
| sender | str | - | Sender email address (required) |
| recipients | List[str] | - | Recipient email addresses (required) |
| use_tls | bool | True | Use STARTTLS encryption |
| use_ssl | bool | False | Use SSL/TLS from connection start |
| format | str | "html" | Email format ("html" or "text") |
| subject_prefix | str | "[Performance Alert]" | Email subject prefix |
Function-Level Profiling
from web_perfmonitor import profile
@profile()
def slow_operation():
# Time-consuming operation
time.sleep(2)
@profile(threshold=0.1) # Custom threshold
def critical_function():
# Critical operation
pass
URL Filtering
Whitelist (monitor only specified URLs)
config = MonitorConfig(
url_whitelist=[
"/api/*", # Monitor all /api/* endpoints
"/v1/users", # Exact match
]
)
Blacklist (exclude specified URLs)
config = MonitorConfig(
url_blacklist=[
"/health", # Exclude health checks
"/metrics", # Exclude metrics endpoint
"/static/*", # Exclude static files
]
)
Note: Whitelist takes precedence over blacklist.
Configuration Reference
| Parameter | Type | Default | Description |
|---|---|---|---|
| threshold_seconds | float | 1.0 | Performance threshold (seconds) |
| alert_window_days | int | 10 | Alert deduplication window (days) |
| max_performance_overhead | float | 0.05 | Maximum performance overhead ratio |
| log_path | str | /tmp | Report save directory |
| url_whitelist | List[str] | [] | URL whitelist patterns |
| url_blacklist | List[str] | [] | URL blacklist patterns |
| notice_list | List[dict] | [] | Notification channel configs |
| notice_timeout_seconds | float | 30.0 | Notification timeout |
| notice_queue_size | int | 1000 | Notification queue size |
| graceful_shutdown_seconds | float | 5.0 | Graceful shutdown timeout |
Extending
Custom Notifier
from web_perfmonitor.notifiers import BaseNotifier, register_notifier
@register_notifier("slack")
class SlackNotifier(BaseNotifier):
def __init__(self, webhook_url: str, **kwargs):
super().__init__(**kwargs)
self.webhook_url = webhook_url
def send(self, profile, format="markdown"):
# Implement Slack notification
...
def validate_config(self) -> bool:
return bool(self.webhook_url)
Custom Framework Adapter
from web_perfmonitor.core import FrameworkRegistry, BaseAdapter
@FrameworkRegistry.register("django")
class DjangoAdapter(BaseAdapter):
# Implement Django-specific adapter
...
Requirements
- Python 3.8+
- Flask 2.0+ or FastAPI 0.100+
- pyinstrument 4.0+
License
MIT License - see LICENSE for details.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Project details
Release history Release notifications | RSS feed
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 web_perfmonitor-2.0.0.tar.gz.
File metadata
- Download URL: web_perfmonitor-2.0.0.tar.gz
- Upload date:
- Size: 42.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c53f3c9b669ae1d567b8730d4c2c839dd1b40569f0d60c029ef119b7f886fe81
|
|
| MD5 |
0db88ad9bcba867cd8d22dc50152b527
|
|
| BLAKE2b-256 |
551703178276d262f011b2a814cdb6e57fead7e332746aaa0ea81892a1819ff4
|
Provenance
The following attestation bundles were made for web_perfmonitor-2.0.0.tar.gz:
Publisher:
python-publish.yml on Michaelxwb/web_permonitor
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
web_perfmonitor-2.0.0.tar.gz -
Subject digest:
c53f3c9b669ae1d567b8730d4c2c839dd1b40569f0d60c029ef119b7f886fe81 - Sigstore transparency entry: 716321596
- Sigstore integration time:
-
Permalink:
Michaelxwb/web_permonitor@6d8e9e911af392b164c61bbccdeef4eb6ea7b7ad -
Branch / Tag:
refs/tags/v2.0.0 - Owner: https://github.com/Michaelxwb
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@6d8e9e911af392b164c61bbccdeef4eb6ea7b7ad -
Trigger Event:
release
-
Statement type:
File details
Details for the file web_perfmonitor-2.0.0-py3-none-any.whl.
File metadata
- Download URL: web_perfmonitor-2.0.0-py3-none-any.whl
- Upload date:
- Size: 56.7 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 |
a1bb889700d5340e5d8516094239945a4f2cae772b06990164e41b761eb73169
|
|
| MD5 |
ae440b4421a0c8525b9566875c79dc9a
|
|
| BLAKE2b-256 |
0404182c000608bcdc6a6dcf1b7f342c191e35a21ddb0d69ad689d12bacc2cf1
|
Provenance
The following attestation bundles were made for web_perfmonitor-2.0.0-py3-none-any.whl:
Publisher:
python-publish.yml on Michaelxwb/web_permonitor
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
web_perfmonitor-2.0.0-py3-none-any.whl -
Subject digest:
a1bb889700d5340e5d8516094239945a4f2cae772b06990164e41b761eb73169 - Sigstore transparency entry: 716321605
- Sigstore integration time:
-
Permalink:
Michaelxwb/web_permonitor@6d8e9e911af392b164c61bbccdeef4eb6ea7b7ad -
Branch / Tag:
refs/tags/v2.0.0 - Owner: https://github.com/Michaelxwb
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@6d8e9e911af392b164c61bbccdeef4eb6ea7b7ad -
Trigger Event:
release
-
Statement type: