fix: CPU calc, disk card, lifespan, remove Google Fonts CDN, fix doc link

- Fix Docker container CPU % (multiply by num_cpus)
- Add missing Disk usage card to system status grid
- Replace deprecated @app.on_event with lifespan context manager
- Move `import requests` to module level
- Remove Google Fonts CDN dependency from CSS
- Update naming doc URL to real raw Gitea link

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
unit0 2026-03-17 10:34:22 -04:00
parent 411038582a
commit 5b1eb9eec4
5 changed files with 19 additions and 8 deletions

View File

@ -42,9 +42,10 @@ class DockerMonitor:
stats["cpu_stats"]["system_cpu_usage"]
- stats["precpu_stats"]["system_cpu_usage"]
)
num_cpus = len(stats["cpu_stats"]["cpu_usage"].get("percpu_usage") or []) or 1
cpu_percent = 0.0
if system_delta > 0:
cpu_percent = (cpu_delta / system_delta) * 100.0
cpu_percent = (cpu_delta / system_delta) * num_cpus * 100.0
# Calculate memory usage
memory_usage = stats["memory_stats"].get("usage", 0)

View File

@ -2,10 +2,12 @@ import asyncio
import json
import logging
import time
from contextlib import asynccontextmanager
from pathlib import Path
from typing import List
import psutil
import requests
import yaml
from fastapi import FastAPI, Request, WebSocket, WebSocketDisconnect, HTTPException
from fastapi.responses import HTMLResponse
@ -16,7 +18,7 @@ from .docker_monitor import DockerMonitor
logger = logging.getLogger(__name__)
app = FastAPI(title="RedUnits Control Panel")
app = FastAPI(title="RedUnits Control Panel", lifespan=lifespan)
# Setup paths
BASE_DIR = Path(__file__).resolve().parent.parent
@ -156,10 +158,11 @@ async def metrics_loop():
# App lifecycle
# ──────────────────────────────────────────────
@app.on_event("startup")
async def startup_event():
@asynccontextmanager
async def lifespan(app: FastAPI):
asyncio.create_task(metrics_loop())
logger.info("Metrics background task started")
yield
# ──────────────────────────────────────────────
@ -265,7 +268,6 @@ async def get_document_content(doc_id: str):
if not doc:
raise HTTPException(status_code=404, detail=f"Document '{doc_id}' not found")
import requests
try:
resp = await asyncio.to_thread(requests.get, doc["url"], timeout=10)
resp.raise_for_status()

View File

@ -27,4 +27,4 @@ documents:
- id: naming-rules
title: "Правила именования устройств"
description: "Стандарт формирования имён для хостов и оборудования"
url: "https://vault.redunits.net/user/repo/raw/branch/main/naming.md" # Замени на реальную ссылку (Raw format)
url: "https://vault.redunits.net/SARMATA5/codex/raw/branch/main/sarmata5/naming.md"

View File

@ -1,5 +1,3 @@
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
:root {
/* Colors inspired by the mock-up */
--bg-main: #fbfbf9;

View File

@ -63,6 +63,16 @@
</div>
</div>
<div class="stat-card">
<div class="stat-label">Disk usage</div>
<div class="stat-value" x-text="system.disk.percent + '%'"></div>
<div class="progress-bar">
<div class="progress-fill" :style="`width: ${system.disk.percent}%`"
:class="getProgressColor(system.disk.percent)"></div>
</div>
<div class="stat-detail" x-text="`${system.disk.used_gb} GB / ${system.disk.total_gb} GB`"></div>
</div>
<div class="stat-card">
<div class="stat-label">Docker containers</div>
<div class="stat-value" x-text="`${system.containers.running} / ${system.containers.total}`"></div>