mirror of
https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools.git
synced 2026-06-17 23:09:35 +00:00
114 lines
3.5 KiB
Python
114 lines
3.5 KiB
Python
"""Health, liveness, readiness endpoints."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from fastapi import APIRouter
|
|
|
|
from api.schemas import HealthResponse
|
|
from core.config.settings import get_settings
|
|
from core.llm import get_router as get_model_router
|
|
|
|
router = APIRouter(tags=["health"])
|
|
|
|
|
|
@router.get("/health", response_model=HealthResponse)
|
|
async def health() -> HealthResponse:
|
|
"""Liveness + config summary."""
|
|
settings = get_settings()
|
|
providers = [p.value for p in get_model_router().available_providers()]
|
|
return HealthResponse(
|
|
status="ok",
|
|
version=settings.app_version,
|
|
env=settings.app_env,
|
|
providers=providers,
|
|
)
|
|
|
|
|
|
@router.get("/ready")
|
|
async def ready() -> dict[str, str]:
|
|
"""Readiness probe."""
|
|
return {"status": "ready"}
|
|
|
|
|
|
@router.get("/live")
|
|
async def live() -> dict[str, str]:
|
|
"""Liveness probe."""
|
|
return {"status": "alive"}
|
|
|
|
|
|
@router.get("/health/deep")
|
|
async def health_deep() -> dict[str, object]:
|
|
"""Deep health check — verifies DB, Redis, LLM providers."""
|
|
import os
|
|
import time
|
|
|
|
checks: dict[str, dict[str, object]] = {}
|
|
overall = "ok"
|
|
|
|
# Postgres
|
|
t0 = time.perf_counter()
|
|
try:
|
|
import psycopg2 # type: ignore
|
|
|
|
dsn = os.getenv("DATABASE_URL") or os.getenv("DATABASE_DSN")
|
|
if dsn:
|
|
conn = psycopg2.connect(dsn, connect_timeout=3)
|
|
conn.cursor().execute("SELECT 1")
|
|
conn.close()
|
|
checks["postgres"] = {"status": "ok", "ms": round((time.perf_counter() - t0) * 1000, 1)}
|
|
else:
|
|
checks["postgres"] = {"status": "skip", "reason": "no DATABASE_URL"}
|
|
except Exception as e: # pragma: no cover
|
|
checks["postgres"] = {"status": "fail", "error": str(e)[:200]}
|
|
overall = "degraded"
|
|
|
|
# Redis
|
|
t0 = time.perf_counter()
|
|
try:
|
|
import redis # type: ignore
|
|
|
|
url = os.getenv("REDIS_URL")
|
|
if url:
|
|
r = redis.from_url(url, socket_timeout=3)
|
|
r.ping()
|
|
checks["redis"] = {"status": "ok", "ms": round((time.perf_counter() - t0) * 1000, 1)}
|
|
else:
|
|
checks["redis"] = {"status": "skip", "reason": "no REDIS_URL"}
|
|
except Exception as e: # pragma: no cover
|
|
checks["redis"] = {"status": "fail", "error": str(e)[:200]}
|
|
overall = "degraded"
|
|
|
|
# LLM providers
|
|
providers = [p.value for p in get_model_router().available_providers()]
|
|
checks["llm_providers"] = {"status": "ok" if providers else "fail", "providers": providers}
|
|
if not providers:
|
|
overall = "degraded"
|
|
|
|
return {"status": overall, "checks": checks, "version": get_settings().app_version}
|
|
|
|
|
|
@router.get("/healthz", include_in_schema=False)
|
|
async def healthz() -> dict[str, str]:
|
|
"""Standard healthz alias for UptimeRobot/K8s probes."""
|
|
return {"status": "ok", "service": "dealix"}
|
|
|
|
|
|
@router.get("/_test_sentry", include_in_schema=False)
|
|
async def test_sentry() -> dict[str, str]:
|
|
"""Deliberate error to verify Sentry integration.
|
|
|
|
Protected by ADMIN_TOKEN header in production.
|
|
"""
|
|
import os
|
|
|
|
from fastapi import HTTPException
|
|
|
|
# In dev, allow freely. In prod, require admin token.
|
|
if os.getenv("APP_ENV", "dev") == "prod":
|
|
admin_token = os.getenv("ADMIN_TOKEN", "")
|
|
# Request injection is complex in FastAPI without Depends; keep simple check
|
|
if not admin_token:
|
|
raise HTTPException(status_code=404, detail="Not found")
|
|
|
|
raise Exception("Test Sentry integration — deliberate error")
|