✅ Allgreen - Python Health Checks Made Simple
Add quick, simple, and beautiful health checks to your Python application via a /healthcheck endpoint.
Perfect for monitoring application health, smoke testing, and ensuring your services are running properly in production.
Features
- Simple DSL - Define health checks in intuitive, readable Python
- Async Support - Write checks as
async def, awaited natively in ASGI apps - Parallel Execution - Checks run concurrently, so latency is the slowest check, not the sum
- Beautiful Web Dashboard - Responsive UI with automatic dark mode
- Fast & Lightweight - Minimal dependencies, maximum performance
- Timeout Protection - Prevent hanging checks with configurable timeouts
- Rate Limiting - Control expensive operations ("2 times per hour")
- Environment Conditions - Run checks only in specific environments
- Result Caching - Cache expensive operations between rate-limited runs
- Multiple Output Formats - HTML dashboard, JSON API, or both
- Prometheus Metrics - Built-in
/metricsendpoint, no extra dependencies - Framework Agnostic - Works with Flask, Django, FastAPI, or standalone
Installation
Choose the installation that fits your needs:
# Core functionality only (no web dependencies)
pip install allgreen
# With Flask integration
pip install allgreen[flask]
# With Django integration
pip install allgreen[django]
# With FastAPI integration
pip install allgreen[fastapi]
Framework-agnostic design - use only what you need!
Quick Start
1. Create your health checks
Create an allgreen_config.py file in your project root:
Note: Config files should use absolute imports only. Relative imports are not supported to avoid import conflicts.
# allgreen_config.py
@check("Database connection is healthy")
def database_check():
# Your database connection logic
make_sure(db.is_connected(), "Database should be accessible")
@check("API response time is acceptable")
def api_performance_check():
response_time = api.ping()
expect(response_time).to_be_less_than(200) # milliseconds
@check("Disk space is sufficient")
def disk_space_check():
usage_percent = get_disk_usage()
expect(usage_percent).to_be_less_than(90)
2. Add to your application
Core Only (no web framework):
from allgreen import get_registry, load_config
load_config()
results = get_registry().run_all()
# Process results as needed
Flask Integration:
pip install allgreen[flask]
from flask import Flask
from allgreen.integrations.flask_integration import mount_healthcheck
app = Flask(__name__)
mount_healthcheck(app, app_name="My API")
Django Integration:
pip install allgreen[django]
# urls.py
from django.urls import path
from allgreen.integrations.django_integration import healthcheck_view
urlpatterns = [
path("healthcheck/", healthcheck_view, name="healthcheck"),
]
FastAPI Integration:
pip install allgreen[fastapi]
from fastapi import FastAPI
from allgreen.integrations.fastapi_integration import create_router
app = FastAPI()
app.include_router(create_router(app_name="My API"))
3. View your dashboard
Visit /healthcheck in your browser to see a beautiful dashboard, or add ?format=json for machine-readable output.
Complete DSL Reference
Basic Assertions
@check("Basic truthiness check")
def basic_check():
make_sure(True, "Custom failure message")
make_sure(user.is_authenticated())
Expectation Methods
@check("Mathematical expectations")
def math_check():
expect(2 + 2).to_eq(4)
expect(api.response_time()).to_be_less_than(100)
expect(database.connection_count()).to_be_greater_than(0)
expect(cpu_usage_percent).to_be_between(0, 95) # inclusive bounds
@check("Membership and presence")
def membership_check():
expect(enabled_features).to_contain("healthcheck")
expect(response.headers).not_to_contain("X-Debug")
expect(shutdown_reason).to_be_none()
expect(get_config()).not_to_be_none()
Advanced Features
Async Checks
Checks can be defined with async def — they work in every supported framework:
import asyncio
import httpx
@check("Upstream API is healthy", timeout=5)
async def upstream_check():
async with httpx.AsyncClient() as client:
response = await client.get("https://api.example.com/health")
expect(response.status_code).to_eq(200)
- FastAPI / ASGI: async checks run natively on the event loop (no thread hop); sync checks run in a worker thread pool so they never block the loop
- Flask / Django / core-only: async checks are executed transparently via a dedicated event loop
- Timeouts apply to async checks too, via task cancellation
- Sync and async checks can be freely mixed in one config file
Parallel Execution
Checks run concurrently: sync checks in a thread pool (up to 8 workers by
default), async checks via asyncio.gather on the event loop. Endpoint
latency is roughly the duration of the slowest check rather than the sum of
all checks. Results are always reported in registration order.
- Tune the pool size with
get_registry().run_all(max_workers=...)if calling directly - Checks execute in worker threads, so anything they share must be thread-safe
Timeout Protection
@check("Slow external service", timeout=30) # 30 seconds max
def external_service_check():
# This check will be terminated if it takes longer than 30 seconds
response = external_api.health_check()
make_sure(response.ok)
- Default timeout is 10 seconds; float values like
timeout=0.5are supported timeout=0disables timeout enforcement for that check
Rate Limiting for Expensive Operations
@check("Expensive API call", run="2 times per hour", timeout=60)
def expensive_check():
# This check only runs twice per hour, caching results between runs
result = paid_api.run_diagnostics()
expect(result.status).to_eq("healthy")
@check("Daily backup verification", run="1 time per day")
def daily_backup_check():
# Perfect for expensive operations that should only run occasionally
backup_status = verify_backup_integrity()
make_sure(backup_status.valid)
Supported rate limiting patterns:
"1 time per minute""5 times per hour""2 times per day"
Environment-Specific Checks
@check("Production database performance", only_in="production")
def prod_db_check():
# Only runs in production environment
expect(db.query_time()).to_be_less_than(10)
@check("Development tools available", except_in=["production", "staging"])
def dev_tools_check():
# Skipped in production and staging
make_sure(debug_tools.available())
@check("Conditional feature check", if_condition=lambda: feature_flag.enabled())
def feature_check():
# Only runs when condition is true
expect(new_feature.status()).to_eq("operational")
Web Interface
HTML Dashboard
Visit /healthcheck for a beautiful, responsive dashboard featuring:
- Color-coded check results (pass/fail/skip)
- Automatic dark mode based on system preferences
- Execution timing for each check
- Summary statistics
- Mobile-responsive design
JSON API
Access /healthcheck.json or /healthcheck?format=json for machine-readable output:
{
"status": "passed",
"environment": "production",
"stats": {
"total": 8,
"passed": 6,
"failed": 1,
"skipped": 1,
"error": 0,
"failing": 1
},
"checks": [
{
"description": "Database connection",
"status": "passed",
"duration_ms": 23.4
}
]
}
HTTP Status Codes
- 200 OK - All checks passing
- 503 Service Unavailable - One or more checks failing
Perfect for integration with monitoring tools like:
- UptimeRobot
- Pingdom
- Datadog
- Custom monitoring solutions
Prometheus Metrics
Flask and FastAPI integrations expose a /metrics endpoint out of the box (no
prometheus_client dependency needed). It renders the standard text exposition
format:
# HELP allgreen_up Overall health status (1 = all checks passing)
# TYPE allgreen_up gauge
allgreen_up 1
# HELP allgreen_checks Number of health checks by status
# TYPE allgreen_checks gauge
allgreen_checks{status="passed"} 3
allgreen_checks{status="failed"} 0
allgreen_checks{status="skipped"} 1
allgreen_checks{status="error"} 0
# HELP allgreen_check_status Health check result (1 = passed, 0 = failed)
# TYPE allgreen_check_status gauge
allgreen_check_status{check="Database connection"} 1
# HELP allgreen_check_duration_seconds Health check execution time
# TYPE allgreen_check_duration_seconds gauge
allgreen_check_duration_seconds{check="Database connection"} 0.023400
The endpoint always returns 200 - overall health is conveyed via the
allgreen_up metric so Prometheus can keep scraping even when checks fail.
Customize or disable the route with metrics_path:
# Flask
mount_healthcheck(app, metrics_path="/prometheus") # custom path
mount_healthcheck(app, metrics_path=None) # disabled
# FastAPI
create_router(metrics_path="/prometheus")
For Django, wire up the view in urls.py:
from allgreen.integrations.django_integration import metrics_view
urlpatterns = [
path("metrics/", metrics_view, name="metrics"),
]
Sample Prometheus scrape config:
scrape_configs:
- job_name: myapp-health
metrics_path: /metrics
scrape_interval: 60s
static_configs:
- targets: ["myapp.example.com"]
Framework Integration
Flask Application
from flask import Flask
from allgreen.integrations.flask_integration import mount_healthcheck
app = Flask(__name__)
# Mount health checks
mount_healthcheck(
app,
app_name="My Flask API",
config_path="config/allgreen_config.py",
environment="production",
)
if __name__ == "__main__":
app.run()
Django Integration
# urls.py
from django.urls import path
from allgreen.integrations.django_integration import healthcheck_view
urlpatterns = [
path("healthcheck/", healthcheck_view, name="healthcheck"),
]
# For custom configuration
from allgreen.integrations.django_integration import create_healthcheck_view
custom_view = create_healthcheck_view(
app_name="My Django App",
config_path="myapp/health_checks.py",
environment="production",
)
urlpatterns = [
path("health/", custom_view, name="healthcheck"),
]
FastAPI Integration
from fastapi import FastAPI
from allgreen.integrations.fastapi_integration import create_router
app = FastAPI()
# Method 1: Mount router
health_router = create_router(app_name="My FastAPI", config_path="config/allgood.py")
app.include_router(health_router)
# Method 2: Individual endpoint
from allgreen.integrations.fastapi_integration import healthcheck_endpoint
@app.get("/healthcheck")
async def health(request: Request):
return await healthcheck_endpoint(request, app_name="My FastAPI")
Examples
Check out the examples/ directory for complete working examples:
examples/allgreen_config.py- Basic health checks configurationexamples/advanced_allgreen_config.py- Advanced features (timeouts, rate limiting)examples/core_only_example.py- Core-only usage (no web dependencies)examples/flask_example.py- Flask integration exampleexamples/django_example.py- Django integration exampleexamples/fastapi_example.py- FastAPI integration example
Configuration File Locations
Allgreen automatically looks for configuration files in these locations:
allgreen_config.py(project root)config/allgreen_config.py- Custom path via
config_pathparameter
Environment Variables
ENVIRONMENT- Sets the environment for conditional checks (default: "development")
Best Practices
Good Health Check Examples
@check("Database queries are fast")
def db_performance():
start = time.time()
users = User.objects.all()[:10]
duration = (time.time() - start) * 1000
expect(duration).to_be_less_than(100) # under 100ms
@check("External API is responsive")
def api_health():
response = requests.get("https://api.example.com/health", timeout=5)
expect(response.status_code).to_eq(200)
@check("Cache is working", run="5 times per hour")
def cache_check():
cache.set("test_key", "test_value")
expect(cache.get("test_key")).to_eq("test_value")
What to Avoid
- Don't make checks that modify data
- Avoid checks that depend on external timing
- Don't put business logic in health checks
- Avoid checks that could cause cascading failures
Security Notes
- Health check endpoints don't require authentication by default
- Consider restricting access in production environments
- Avoid exposing sensitive system information in check descriptions
- Rate limiting helps prevent abuse of expensive operations
- Tracebacks from errored checks are hidden unless the environment is
development; responses only include the exception type and message. Passshow_tracebacks=Trueto the integration to opt in elsewhere
Development
git clone https://github.com/navinpai/allgreen
cd allgreen
uv venv
source .venv/bin/activate
uv pip install -e ".[dev]"
# Run tests
python -m pytest
# Run linting and formatting checks
ruff check .
ruff format --check .
# Run type checking
mypy
# Start example server
python test_server.py
Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Add tests for new functionality
- Ensure all tests pass (
python -m pytest) - Run linting, formatting, and type checks (
ruff check . && ruff format --check . && mypy) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgments
- Inspired by the Allgood Ruby gem
- Built with ❤️ for the Python community
Metadata
Release files for allgreen 1.0.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 | |
|---|---|---|---|
| allgreen-1.0.1.tar.gz | 36.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| allgreen-1.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 68.0 kB
Release files / allgreen-1.0.1.tar.gz
| Download URL | allgreen-1.0.1.tar.gz |
|---|---|
| Size | 36.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
17ffc4aa69f3f48eefd977bf868364af9bce3ba88745b51924fb5d13d5d6c992
|
|
BLAKE2b-256 checksum How to use checksums |
9e336fbd3607d96333a81fe0ee42f93792f649a1c12edddd13622c4741ab8268
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.14
|
Release files / allgreen-1.0.1-py3-none-any.whl
| Download URL | allgreen-1.0.1-py3-none-any.whl |
|---|---|
| Size | 31.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5e80407bc79797434d2f49225bb16f622e79b9fb62cf47c78aad846333b7a743
|
|
BLAKE2b-256 checksum How to use checksums |
87fb9383ff9eb00551ddcd096efa037db709adfc39488fb40bfd3a526f73afcf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.14
|