Serve /health and keep 404 scanner noise out of the log file

Something on the network polls /health (and /v1/models) every 30 seconds;
the former now answers 200 with a database check instead of a 404, and
django.request is limited to ERROR in the logging config so scanner 404s
stop filling backend/logs/j621.log. Real server errors still log, and the
dev server keeps printing every request to its console.
This commit is contained in:
2026-09-17 21:50:20 -05:00
parent 487d14c617
commit 38e64140ed
3 changed files with 35 additions and 0 deletions
+20
View File
@@ -1,6 +1,7 @@
import time import time
from django.conf import settings from django.conf import settings
from django.db import connection
from rest_framework.exceptions import PermissionDenied from rest_framework.exceptions import PermissionDenied
from rest_framework.permissions import AllowAny, IsAuthenticated from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.response import Response from rest_framework.response import Response
@@ -66,3 +67,22 @@ class StatsView(APIView):
"log": stats.log_tail(), "log": stats.log_tail(),
} }
) )
class HealthView(APIView):
"""Unauthenticated liveness probe for uptime monitors (hits /health)."""
permission_classes = [AllowAny]
authentication_classes = []
def get(self, request):
database = True
try:
with connection.cursor() as cursor:
cursor.execute("SELECT 1")
except Exception: # noqa: BLE001 - report the failure, do not crash
database = False
return Response(
{"status": "ok" if database else "degraded", "database": database},
status=200 if database else 503,
)
+10
View File
@@ -238,6 +238,16 @@ LOGGING = {
}, },
}, },
"handlers": _log_handlers, "handlers": _log_handlers,
"loggers": {
# Scanners on the network probe things like /health and /v1/models;
# their 404s are noise in the log file. Real server errors (5xx) still
# log, and the dev server keeps printing every request to the console.
"django.request": {
"handlers": _root_handlers,
"level": "ERROR",
"propagate": False,
},
},
"root": { "root": {
"handlers": _root_handlers, "handlers": _root_handlers,
"level": "INFO", "level": "INFO",
+5
View File
@@ -3,6 +3,8 @@ from django.conf.urls.static import static
from django.contrib import admin from django.contrib import admin
from django.urls import include, path from django.urls import include, path
from apps.core.views import HealthView
urlpatterns = [ urlpatterns = [
path("admin/", admin.site.urls), path("admin/", admin.site.urls),
path("api/auth/", include("apps.accounts.urls")), path("api/auth/", include("apps.accounts.urls")),
@@ -10,6 +12,9 @@ urlpatterns = [
path("api/", include("apps.core.urls")), path("api/", include("apps.core.urls")),
path("api/", include("apps.library.urls")), path("api/", include("apps.library.urls")),
path("api/", include("apps.follows.urls")), path("api/", include("apps.follows.urls")),
# Liveness probe for uptime monitors (no /api prefix, no auth).
path("health", HealthView.as_view(), name="health"),
path("health/", HealthView.as_view()),
] ]
if settings.DEBUG: if settings.DEBUG: