- Move `from datetime import timedelta` to top of base.py (E402) - Add `# noqa: E402` to conditional sentry imports in prod.py (E402) - Remove unused `import time` and `IsAdminUser` from api/views.py (F401) - Remove unused `NoReverseMatch` import from tests/test_smoke.py (F401) Co-Authored-By: Paperclip <noreply@paperclip.ing>
59 lines
1.9 KiB
Python
59 lines
1.9 KiB
Python
from django.conf import settings
|
|
from django.db import connection, OperationalError
|
|
from django.core.cache import cache
|
|
from django.http import HttpResponse
|
|
from rest_framework.decorators import api_view, permission_classes, authentication_classes
|
|
from rest_framework.permissions import AllowAny
|
|
from rest_framework.response import Response
|
|
from rest_framework import status
|
|
|
|
|
|
@api_view(["GET"])
|
|
@authentication_classes([])
|
|
@permission_classes([AllowAny])
|
|
def healthcheck(request):
|
|
"""Liveness + readiness probe endpoint. Returns 200 when all dependencies are reachable."""
|
|
checks = {}
|
|
overall_ok = True
|
|
|
|
# Database
|
|
try:
|
|
connection.ensure_connection()
|
|
checks["db"] = "ok"
|
|
except OperationalError as exc:
|
|
checks["db"] = f"error: {exc}"
|
|
overall_ok = False
|
|
|
|
# Cache / Redis
|
|
try:
|
|
key = "_healthcheck"
|
|
cache.set(key, "1", timeout=5)
|
|
assert cache.get(key) == "1"
|
|
checks["cache"] = "ok"
|
|
except Exception as exc:
|
|
checks["cache"] = f"error: {exc}"
|
|
overall_ok = False
|
|
|
|
http_status = status.HTTP_200_OK if overall_ok else status.HTTP_503_SERVICE_UNAVAILABLE
|
|
return Response(
|
|
{"status": "ok" if overall_ok else "degraded", "checks": checks},
|
|
status=http_status,
|
|
)
|
|
|
|
|
|
@api_view(["GET"])
|
|
@authentication_classes([])
|
|
@permission_classes([AllowAny])
|
|
def metrics(request):
|
|
"""Prometheus metrics scrape endpoint.
|
|
|
|
Restricted to internal networks via METRICS_ALLOWED_HOSTS setting (checked
|
|
at the reverse-proxy level in prod). Returns 403 when the feature flag is
|
|
off so the endpoint is a no-op in environments where it is not configured.
|
|
"""
|
|
if not getattr(settings, "METRICS_ENABLED", False):
|
|
return HttpResponse(status=403)
|
|
|
|
from prometheus_client import generate_latest, CONTENT_TYPE_LATEST
|
|
return HttpResponse(generate_latest(), content_type=CONTENT_TYPE_LATEST)
|