Skip to main content

Structured healthcheck endpoints with shallow and deep response tiers, concurrent check execution, and built-in support for PostgreSQL, Redis, SQLAlchemy, and FastAPI.

Project description

Vitals (Python)

Structured deep healthcheck endpoints for Python services. Register health checks, run them concurrently with timeouts, and expose them via FastAPI.

Install

pip install vitals

Install with optional dependencies for the checks and integrations you need:

pip install vitals[asyncpg]      # PostgreSQL via asyncpg
pip install vitals[redis]        # Redis via redis-py
pip install vitals[sqlalchemy]   # PostgreSQL via SQLAlchemy
pip install vitals[fastapi]      # FastAPI integration
pip install vitals[all]          # Everything

Quick Start

from vitals import HealthcheckRegistry, Status, CheckResult
from vitals.checks.postgres import AsyncpgPoolCheck
from vitals.checks.redis import RedisPoolCheck
from vitals.integrations.fastapi import create_healthcheck_route
from fastapi import FastAPI

registry = HealthcheckRegistry(default_timeout=5.0)

# Add checks using existing connection pools
registry.add("postgres", AsyncpgPoolCheck(pool))
registry.add("redis", RedisPoolCheck(redis_pool))

# Or add a custom check
@registry.check("api")
async def check_api() -> CheckResult:
    start = time.monotonic()
    async with httpx.AsyncClient() as client:
        resp = await client.get("https://api.example.com/ping")
    latency = (time.monotonic() - start) * 1000
    return CheckResult(
        status=Status.HEALTHY if resp.is_success else Status.OUTAGE,
        latency_ms=latency,
        message="" if resp.is_success else f"HTTP {resp.status_code}",
    )

# Mount as a FastAPI route
app = FastAPI()
app.include_router(create_healthcheck_route(
    registry,
    token=os.environ.get("HEALTHCHECK_TOKEN"),
))

API

HealthcheckRegistry

registry = HealthcheckRegistry(default_timeout=5.0)

registry.add(name, check, *, timeout=None)

Register a named async check function.

async def my_check() -> CheckResult:
    return CheckResult(status=Status.HEALTHY, latency_ms=0.0, message="")

registry.add("service", my_check, timeout=3.0)

registry.check(name, *, timeout=None)

Decorator form of add.

@registry.check("service", timeout=3.0)
async def check_service() -> CheckResult:
    ...

await registry.run()

Execute all registered checks concurrently using asyncio.TaskGroup. Returns a HealthcheckResponse with the worst overall status.

response = await registry.run()
response.status       # Status.HEALTHY
response.to_dict()    # {'status': 'healthy', 'timestamp': '...', 'checks': {...}}
response.http_status_code  # 200

Status

from vitals import Status

Status.HEALTHY   # 2
Status.DEGRADED  # 1
Status.OUTAGE    # 0

Status.from_string("degraded")  # Status.DEGRADED
Status.HEALTHY.json_value       # "healthy"

Built-in Checks

PostgreSQL

from vitals.checks.postgres import AsyncpgCheck, AsyncpgPoolCheck, SQLAlchemyCheck

# Fresh asyncpg connection each time
registry.add("pg", AsyncpgCheck("postgresql://localhost:5432/mydb"))

# Existing asyncpg pool
registry.add("pg", AsyncpgPoolCheck(pool))

# SQLAlchemy AsyncEngine
registry.add("pg", SQLAlchemyCheck(engine))

Redis

from vitals.checks.redis import RedisCheck, RedisPoolCheck

# Fresh connection each time
registry.add("redis", RedisCheck("redis://localhost:6379"))

# Existing redis.asyncio connection pool
registry.add("redis", RedisPoolCheck(pool))

Sync Checks

Wrap synchronous functions using asyncio.to_thread:

from vitals import sync_check, Status, CheckResult

def check_disk() -> CheckResult:
    free = shutil.disk_usage("/").free
    return CheckResult(
        status=Status.HEALTHY if free > 1_000_000_000 else Status.DEGRADED,
        latency_ms=0.0,
        message=f"{free} bytes free",
    )

registry.add("disk", sync_check(check_disk))

FastAPI Integration

from vitals.integrations.fastapi import create_healthcheck_route

router = create_healthcheck_route(
    registry,
    token="my-secret-token",       # optional — omit to disable auth
    path="/healthcheck/deep",      # default
    query_param_name="token",      # default
    include_in_schema=False,       # default — hides from OpenAPI docs
)
app.include_router(router)

When a token is configured, requests must provide it via:

  • Query parameter: ?token=my-secret-token
  • Bearer header: Authorization: Bearer my-secret-token

Authentication

from vitals import verify_token, extract_token

# Timing-safe token comparison
verify_token("provided-token", "expected-token")  # bool

# Extract token from request data
token = extract_token(
    query_params={"token": "abc"},
    authorization_header="Bearer abc",
    query_param_name="token",
)

Response Format

{
  "status": "healthy",
  "timestamp": "2025-02-26T12:00:00.000Z",
  "checks": {
    "postgres": {
      "status": "healthy",
      "latencyMs": 4.2,
      "message": ""
    },
    "redis": {
      "status": "healthy",
      "latencyMs": 1.1,
      "message": ""
    }
  }
}
Overall Status HTTP Code
healthy 200
degraded 503
outage 503
Auth failure 403

Requirements

  • Python >= 3.11

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

firebreak_vitals-1.1.0.tar.gz (18.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

firebreak_vitals-1.1.0-py3-none-any.whl (15.2 kB view details)

Uploaded Python 3

File details

Details for the file firebreak_vitals-1.1.0.tar.gz.

File metadata

  • Download URL: firebreak_vitals-1.1.0.tar.gz
  • Upload date:
  • Size: 18.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.0.1 CPython/3.12.8

File hashes

Hashes for firebreak_vitals-1.1.0.tar.gz
Algorithm Hash digest
SHA256 1e80e8191c65832e68dec31042fd4299ae8a0df570d4dc3b69c2aa7eb5cf7478
MD5 5c360281054fe5fb633029732bdfcc26
BLAKE2b-256 d8f410aaaef1ad49e3e883741d06e1cc9c02cc14cac1b5c3139361e3ec70f492

See more details on using hashes here.

Provenance

The following attestation bundles were made for firebreak_vitals-1.1.0.tar.gz:

Publisher: publish-python.yml on firebreak-io/vitals

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file firebreak_vitals-1.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for firebreak_vitals-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 86fa032fb17b78cd62154d1c726e2f5a25ae8135a3f0116e344dbf7d28394a10
MD5 8ea25810203e38f3687edcc78bcebc79
BLAKE2b-256 0aa17b31f4c05fa67caf06da556bdbd15d68acb9c417a18283c118965e0dda83

See more details on using hashes here.

Provenance

The following attestation bundles were made for firebreak_vitals-1.1.0-py3-none-any.whl:

Publisher: publish-python.yml on firebreak-io/vitals

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page