diff --git a/src/arbitrade/api/routes.py b/src/arbitrade/api/routes.py
index c5b048a..98b0b75 100644
--- a/src/arbitrade/api/routes.py
+++ b/src/arbitrade/api/routes.py
@@ -1493,3 +1493,49 @@ async def dashboard_api_pairings_sync(request: Request) -> HTMLResponse:
name="partials/pairings_table.html",
context={"request": request, "pairings": pairings},
)
+
+
+# ── Log routes ──────────────────────────────────────────────────────────────
+
+
+@router.get("/dashboard/fragment/logs", response_class=HTMLResponse)
+async def dashboard_logs_fragment(
+ request: Request,
+ level: str | None = None,
+ page: int = 1,
+ per_page: int = 50,
+) -> HTMLResponse:
+ """HTMX fragment: log table for health page."""
+ repo = LogRepository(request.app.state.store)
+ offset = (page - 1) * per_page
+ records = await repo.query(level=level, limit=per_page, offset=offset)
+ total = await repo.count_filtered(level=level)
+ total_pages = max(1, (total + per_page - 1) // per_page)
+ return templates.TemplateResponse(
+ request=request,
+ name="partials/log_table.html",
+ context={
+ "request": request,
+ "records": records,
+ "page": page,
+ "total_pages": total_pages,
+ "total": total,
+ "current_level": level or "all",
+ },
+ )
+
+
+@router.post("/dashboard/api/logging/aggregate", response_class=JSONResponse)
+async def dashboard_logging_aggregate(request: Request) -> JSONResponse:
+ from arbitrade.logging.maintenance import run_log_aggregation
+
+ await run_log_aggregation(request.app.state.store)
+ return JSONResponse({"status": "ok"})
+
+
+@router.post("/dashboard/api/logging/archive", response_class=JSONResponse)
+async def dashboard_logging_archive(request: Request) -> JSONResponse:
+ from arbitrade.logging.maintenance import run_log_archive
+
+ count = await run_log_archive(request.app.state.store)
+ return JSONResponse({"status": "ok", "archived": count})
diff --git a/src/arbitrade/web/templates/health.html b/src/arbitrade/web/templates/health.html
index 603f6b9..d64df4d 100644
--- a/src/arbitrade/web/templates/health.html
+++ b/src/arbitrade/web/templates/health.html
@@ -1,8 +1,10 @@
{% extends "_base.html" %} {% block title %}Arbitrade Health Check{% endblock %}
{% block header %} {% with page_title="Arbitrade Health Check",
-page_subtitle="Live system state." %} {% include "_header.html" %} {% endwith %}
-{% endblock %} {% block main_class %}shell{% endblock %} {% block content %}
- Status: {{ status }} UTC: {{ time }}Arbitrade Bootstrap Complete
{"status":"ok","service":"arbitrade"}
+
+| Time | +Level | +Logger | +Message | +
|---|---|---|---|
| + {{ r.recorded_at.strftime('%H:%M:%S') if r.recorded_at else '—' }} + | ++ {{ r.level }} + | + + +||
| No log entries found. | +|||