"""YakPanel - Dashboard API""" import os from fastapi import APIRouter, Depends from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select, func from app.core.database import get_db from app.api.auth import get_current_user from app.models.user import User router = APIRouter(prefix="/dashboard", tags=["dashboard"]) def _root_inode_usage() -> dict: """Inode use on filesystem root (Linux). Returns percent or null if unavailable.""" try: sv = os.statvfs("/") except (AttributeError, OSError): return {"percent": None, "used": None, "total": None} total = int(sv.f_files) free = int(sv.f_ffree) if total <= 0: return {"percent": None, "used": None, "total": None} used = max(0, total - free) return { "percent": round(100.0 * used / total, 1), "used": used, "total": total, } @router.get("/stats") async def get_stats( current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): """Get dashboard statistics""" import psutil from app.services.site_service import get_site_count, ssl_alert_summary from app.models.ftp import Ftp from app.models.database import Database site_count = await get_site_count(db) ftp_result = await db.execute(select(func.count()).select_from(Ftp)) ftp_count = ftp_result.scalar() or 0 db_result = await db.execute(select(func.count()).select_from(Database)) database_count = db_result.scalar() or 0 # System stats cpu_percent = psutil.cpu_percent(interval=1) memory = psutil.virtual_memory() disk = psutil.disk_usage("/") inodes = _root_inode_usage() ssl_alerts = await ssl_alert_summary(db) return { "site_count": site_count, "ftp_count": ftp_count, "database_count": database_count, "ssl_alerts": ssl_alerts, "system": { "cpu_percent": cpu_percent, "memory_percent": memory.percent, "memory_used_mb": round(memory.used / 1024 / 1024, 1), "memory_total_mb": round(memory.total / 1024 / 1024, 1), "disk_percent": disk.percent, "disk_used_gb": round(disk.used / 1024 / 1024 / 1024, 2), "disk_total_gb": round(disk.total / 1024 / 1024 / 1024, 2), "inode_percent": inodes["percent"], "inode_used": inodes["used"], "inode_total": inodes["total"], }, }