dashboard-nanobot/backend/services/platform_overview_service.py

105 lines
4.1 KiB
Python

from typing import Any, Dict
from sqlmodel import Session, select
from core.utils import _calc_dir_size_bytes
from models.bot import BotInstance, NanobotImage
from services.bot_storage_service import _read_bot_resources, _workspace_root
from services.platform_activity_service import list_activity_events, prune_expired_activity_events
from services.platform_settings_service import get_platform_settings
from services.platform_usage_service import list_usage
def build_platform_overview(session: Session, docker_manager: Any) -> Dict[str, Any]:
deleted = prune_expired_activity_events(session, force=False)
if deleted > 0:
session.commit()
bots = session.exec(
select(BotInstance).order_by(BotInstance.created_at.desc(), BotInstance.id.asc())
).all()
images = session.exec(select(NanobotImage).order_by(NanobotImage.created_at.desc())).all()
settings = get_platform_settings(session)
running = 0
stopped = 0
disabled = 0
configured_cpu_total = 0.0
configured_memory_total = 0
configured_storage_total = 0
workspace_used_total = 0
workspace_limit_total = 0
live_cpu_percent_total = 0.0
live_memory_used_total = 0
live_memory_limit_total = 0
for bot in bots:
enabled = bool(getattr(bot, "enabled", True))
runtime_status = docker_manager.get_bot_status(bot.id) if docker_manager else str(bot.docker_status or "STOPPED")
resources = _read_bot_resources(bot.id)
runtime = (
docker_manager.get_bot_resource_snapshot(bot.id)
if docker_manager
else {"usage": {}, "limits": {}, "docker_status": runtime_status}
)
workspace_root = _workspace_root(bot.id)
workspace_used = _calc_dir_size_bytes(workspace_root)
workspace_limit = int(resources["storage_gb"] or 0) * 1024 * 1024 * 1024
configured_cpu_total += float(resources["cpu_cores"] or 0)
configured_memory_total += int(resources["memory_mb"] or 0) * 1024 * 1024
configured_storage_total += workspace_limit
workspace_used_total += workspace_used
workspace_limit_total += workspace_limit
live_cpu_percent_total += float((runtime.get("usage") or {}).get("cpu_percent") or 0.0)
live_memory_used_total += int((runtime.get("usage") or {}).get("memory_bytes") or 0)
live_memory_limit_total += int((runtime.get("usage") or {}).get("memory_limit_bytes") or 0)
if not enabled:
disabled += 1
elif runtime_status == "RUNNING":
running += 1
else:
stopped += 1
usage = list_usage(session, limit=20)
events = list_activity_events(session, limit=20)
return {
"summary": {
"bots": {
"total": len(bots),
"running": running,
"stopped": stopped,
"disabled": disabled,
},
"images": {
"total": len(images),
"ready": len([row for row in images if row.status == "READY"]),
"abnormal": len([row for row in images if row.status != "READY"]),
},
"resources": {
"configured_cpu_cores": round(configured_cpu_total, 2),
"configured_memory_bytes": configured_memory_total,
"configured_storage_bytes": configured_storage_total,
"live_cpu_percent": round(live_cpu_percent_total, 2),
"live_memory_used_bytes": live_memory_used_total,
"live_memory_limit_bytes": live_memory_limit_total,
"workspace_used_bytes": workspace_used_total,
"workspace_limit_bytes": workspace_limit_total,
},
},
"images": [
{
"tag": row.tag,
"version": row.version,
"status": row.status,
"source_dir": row.source_dir,
"created_at": row.created_at.isoformat() + "Z",
}
for row in images
],
"settings": settings.model_dump(),
"usage": usage,
"events": events,
}