Files
breakpilot-lehrer/backend-lehrer/llm_gateway/routes/health.py
Benjamin Boenisch 5a31f52310 Initial commit: breakpilot-lehrer - Lehrer KI Platform
Services: Admin-Lehrer, Backend-Lehrer, Studio v2, Website,
Klausur-Service, School-Service, Voice-Service, Geo-Service,
BreakPilot Drive, Agent-Core

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 23:47:26 +01:00

128 lines
3.9 KiB
Python

"""
Health Check Route.
"""
import logging
from datetime import datetime
from fastapi import APIRouter
from pydantic import BaseModel
from ..config import get_config
logger = logging.getLogger(__name__)
router = APIRouter(tags=["Health"])
class ComponentStatus(BaseModel):
"""Status einer Komponente."""
name: str
status: str # healthy, degraded, unhealthy
message: str = ""
class HealthResponse(BaseModel):
"""Health Check Response."""
status: str # ok, degraded, error
ts: str
version: str
components: list[ComponentStatus]
@router.get("/health", response_model=HealthResponse)
async def health_check():
"""
Health Check Endpoint.
Prüft den Status aller Komponenten:
- Gateway selbst
- LLM Backend Erreichbarkeit
- Datenbank (wenn konfiguriert)
"""
config = get_config()
components = []
overall_status = "ok"
# Gateway selbst
components.append(ComponentStatus(
name="gateway",
status="healthy",
message="Gateway is running",
))
# Ollama Backend
if config.ollama and config.ollama.enabled:
try:
import httpx
async with httpx.AsyncClient(timeout=5.0) as client:
response = await client.get(f"{config.ollama.base_url}/api/tags")
if response.status_code == 200:
components.append(ComponentStatus(
name="ollama",
status="healthy",
message="Ollama is reachable",
))
else:
components.append(ComponentStatus(
name="ollama",
status="degraded",
message=f"Ollama returned status {response.status_code}",
))
overall_status = "degraded"
except Exception as e:
components.append(ComponentStatus(
name="ollama",
status="unhealthy",
message=f"Cannot reach Ollama: {str(e)}",
))
# Nicht critical wenn andere Backends verfügbar
if not (config.vllm and config.vllm.enabled) and not (config.anthropic and config.anthropic.enabled):
overall_status = "error"
# vLLM Backend
if config.vllm and config.vllm.enabled:
try:
import httpx
headers = {}
if config.vllm.api_key:
headers["Authorization"] = f"Bearer {config.vllm.api_key}"
async with httpx.AsyncClient(timeout=5.0) as client:
response = await client.get(
f"{config.vllm.base_url}/v1/models",
headers=headers,
)
if response.status_code == 200:
components.append(ComponentStatus(
name="vllm",
status="healthy",
message="vLLM is reachable",
))
else:
components.append(ComponentStatus(
name="vllm",
status="degraded",
message=f"vLLM returned status {response.status_code}",
))
overall_status = "degraded"
except Exception as e:
components.append(ComponentStatus(
name="vllm",
status="unhealthy",
message=f"Cannot reach vLLM: {str(e)}",
))
# Anthropic Backend
if config.anthropic and config.anthropic.enabled:
components.append(ComponentStatus(
name="anthropic",
status="healthy",
message="Anthropic API configured (not checked)",
))
return HealthResponse(
status=overall_status,
ts=datetime.utcnow().isoformat() + "Z",
version="0.1.0",
components=components,
)