diff --git a/django_healthy/health_checks/__init__.py b/django_healthy/health_checks/__init__.py index e6e7b26..39286eb 100644 --- a/django_healthy/health_checks/__init__.py +++ b/django_healthy/health_checks/__init__.py @@ -1,7 +1,13 @@ from .base import HealthCheck, HealthCheckResult, HealthStatus +from .service import HealthCheckService, HealthReport, HealthReportEntry __all__ = [ "HealthCheck", "HealthCheckResult", "HealthStatus", + "HealthCheckService", + "HealthReport", + "HealthReportEntry", ] + +health_check_service = HealthCheckService() diff --git a/django_healthy/templates/django_healthy/report.html b/django_healthy/templates/django_healthy/report.html new file mode 100644 index 0000000..b75e861 --- /dev/null +++ b/django_healthy/templates/django_healthy/report.html @@ -0,0 +1,24 @@ + + + + Health Report + + + + + + + + + + {% for system, reported in report.entries.items %} + + + + + + {% endfor %} + +
SystemStatusTime
{{ system }}{{ reported.status.name }}{{ reported.duration.total_seconds }}
+ + diff --git a/django_healthy/urls.py b/django_healthy/urls.py index f98f419..1f4bc5a 100644 --- a/django_healthy/urls.py +++ b/django_healthy/urls.py @@ -1,9 +1,10 @@ from django.urls import path -from .views import LivenessView +from .views import HealthView, LivenessView app_name = "django_healthy" urlpatterns = [ path("ping/", LivenessView.as_view(), name="ping"), + path("health/", HealthView.as_view(), name="health"), ] diff --git a/django_healthy/views.py b/django_healthy/views.py index ef11cb3..2fe9401 100644 --- a/django_healthy/views.py +++ b/django_healthy/views.py @@ -3,8 +3,11 @@ from typing import ClassVar from django.http import HttpRequest, HttpResponse +from django.template.response import TemplateResponse from django.views import View +from .health_checks import HealthReport, health_check_service + class LivenessView(View): http_method_names: ClassVar[list[str]] = [ @@ -16,3 +19,17 @@ class LivenessView(View): async def get(self, request: HttpRequest) -> HttpResponse: # noqa: ARG002 return HttpResponse("Pong") + + +class HealthView(View): + http_method_names: ClassVar[list[str]] = [ + "get", + "head", + "options", + "trace", + ] + + async def get(self, request: HttpRequest) -> HttpResponse: + report: HealthReport = await health_check_service.check_health() + context: dict[str, HealthReport] = {"report": report} + return TemplateResponse(request, "django_healthy/report.html", context) diff --git a/tests/test_views.py b/tests/test_views.py index a8ab1f0..c04528a 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -39,3 +39,20 @@ async def test_methods_not_allowed_async(self, method: str, async_client: AsyncC response: HttpResponse = await django_client_method(reverse("django_healthy:ping")) assert response.status_code == HTTPStatus.METHOD_NOT_ALLOWED + + +class TestHealthView: + @pytest.mark.asyncio + async def test_get_async(self, async_client: AsyncClient): + response: HttpResponse = await async_client.get(reverse("django_healthy:health")) + + assert response.status_code == HTTPStatus.OK + + @pytest.mark.asyncio + @pytest.mark.parametrize("method", ["post", "put", "patch", "delete"]) + async def test_methods_not_allowed_async(self, method: str, async_client: AsyncClient): + django_client_method = getattr(async_client, method) + + response: HttpResponse = await django_client_method(reverse("django_healthy:health")) + + assert response.status_code == HTTPStatus.METHOD_NOT_ALLOWED