Skip to main content

Web Performance Monitor

A lightweight performance monitoring library for Python web frameworks based on pyinstrument.

PyPI version Python 3.8+ License: MIT

Features

  • Zero-intrusion monitoring - Add performance monitoring without modifying your application code
  • Automatic profiling - Captures detailed call stacks when response time exceeds threshold
  • Request header collection - Automatically collects tracing-related HTTP headers (X-Request-ID, X-Trace-ID, etc.)
  • 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, FastAPI, and Sanic with async/await, extensible for Django, etc.

Installation

pip install web-perfmonitor

For FastAPI support:

pip install web-perfmonitor[fastapi]

For Sanic support:

pip install web-perfmonitor[sanic]

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)

Sanic (Async Support)

from sanic import Sanic
from sanic import json
from web_perfmonitor import PerformanceMiddleware

app = Sanic("MyApp")
PerformanceMiddleware(app)  # Auto-detects Sanic

@app.route("/api/users")
async def get_users(request):
    # Your async business logic
    return json({"users": [...]})

if __name__ == "__main__":
    app.run(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 /tmp directory
  • For FastAPI and Sanic, 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

    # Request header collection (enabled by default)
    capture_request_headers=True,  # Collect request headers
    included_headers=None,          # None=use default list, or customize like ["X-Custom-ID"]
)

PerformanceMiddleware(app, config=config)

Default collected headers:

  • X-Forwarded-For / X-Real-IP - Real client IP
  • X-Request-ID / X-Trace-ID / X-Correlation-ID - Distributed tracing identifiers
  • Referer - Request source
  • Content-Type / Accept / Accept-Language - Content format
  • Origin - CORS origin
  • User-Agent - User agent string

Environment Variables

export PERF_THRESHOLD=0.5
export PERF_ALERT_WINDOW=7
export PERF_LOG_PATH=/var/log/myapp
export PERF_CAPTURE_REQUEST_HEADERS=true
export PERF_INCLUDED_HEADERS="X-Request-ID,X-Trace-ID,X-Custom-Header"
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
capture_request_headers bool True Whether to collect HTTP request headers
included_headers List[str] None Custom list of headers to collect

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.

Metadata

Release files for web-perfmonitor 3.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for web-perfmonitor 3.0.0
File Size Uploaded
web_perfmonitor-3.0.0.tar.gz 49.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for web-perfmonitor 3.0.0
File Interpreter ABI Platform
web_perfmonitor-3.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 116.6 kB

Release files / web_perfmonitor-3.0.0.tar.gz

Download URL web_perfmonitor-3.0.0.tar.gz
Size 49.2 kB
Tags Source
SHA-256 checksum
How to use checksums
752dc525a780f008cc5ea0aaf6dd130c9d20b9206f75caccef6327f12bc00c64
BLAKE2b-256 checksum
How to use checksums
ddf84e6a44df87e22737b2796e1828c66d611ecaff4e5a913b0d14b26805aa7b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 30, 2025.

Transparency log

Release files / web_perfmonitor-3.0.0-py3-none-any.whl

Download URL web_perfmonitor-3.0.0-py3-none-any.whl
Size 67.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
78b68c0e3a9c5b600af931d0bff0fdb4929346823625c909877acb19d36fb2f5
BLAKE2b-256 checksum
How to use checksums
4200bbe073b044c0fc78cc12a73d93e4b1dd32ba217a213eeb33e91c919a83bd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 30, 2025.

Transparency log

Release history Release notifications | RSS feed

This release

3.0.0 This release

2 release files

2.0.6

2 release files

2.0.5

2 release files

2.0.3

2 release files

2.0.2

2 release files

2.0.1

2 release files

2.0.0

2 release files

1.0.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page