Download templates/admin_stats.html from ItsBounvy/bot_host: direct link, hf CLI and curl.
- Browser
- Download file 10.4 kB
-
https://huggingface.co/spaces/ItsBounvy/bot_host/resolve/main/templates/admin_stats.html
- Command line
-
hf download hf://spaces/ItsBounvy/bot_host/templates/admin_stats.html
-
curl -L -o admin_stats.html https://huggingface.co/spaces/ItsBounvy/bot_host/resolve/main/templates/admin_stats.html
10.4 kB
| {% extends "base.html" %} | |
| {% block title %}{{ _("System stats") }}{% endblock %} | |
| {% block content %} | |
| <div class="page-header"> | |
| <div> | |
| <h1>{{ _("System stats") }}</h1> | |
| <div class="subtitle">{{ _("Host load and a per-user breakdown of bots and resource footprint.") }}</div> | |
| </div> | |
| <div style="display: flex; gap: 8px; align-items: center;"> | |
| <a href="/api/admin/stats" target="_blank" class="btn btn-sm" | |
| style="background: var(--surface-2); color: var(--text-1);">{{ panel_icon('cpu')|safe }} {{ _("JSON API") }}</a> | |
| <button type="button" class="btn btn-sm btn-primary" onclick="location.reload();"> | |
| π {{ _("Refresh") }} | |
| </button> | |
| </div> | |
| </div> | |
| <div class="stats-grid"> | |
| <div class="stat-card tone-primary"> | |
| <div class="stat-label">{{ panel_icon('users')|safe }} {{ _("Users") }}</div> | |
| <div class="stat-value">{{ user_count }}</div> | |
| <div class="stat-foot">{{ totals.bots }} {{ ngettext("bot", "bots", totals.bots, count=totals.bots) }} {{ _("total") }}</div> | |
| </div> | |
| <div class="stat-card tone-success"> | |
| <div class="stat-label">{{ panel_icon('check')|safe }} {{ _("Running bots") }}</div> | |
| <div class="stat-value">{{ totals.running }}</div> | |
| <div class="stat-foot">{{ _("out of") }} {{ totals.bots }}</div> | |
| </div> | |
| <div class="stat-card tone-accent"> | |
| <div class="stat-label">{{ panel_icon('cpu')|safe }} {{ _("Host CPU") }}</div> | |
| <div class="stat-value">{{ host.cpu_percent }}%</div> | |
| <div class="stat-foot">{{ host.cpu_count }} {{ ngettext("core", "cores", host.cpu_count, count=host.cpu_count) }}</div> | |
| </div> | |
| <div class="stat-card tone-warning"> | |
| <div class="stat-label">{{ panel_icon('db')|safe }} {{ _("Host RAM") }}</div> | |
| <div class="stat-value">{{ host.ram_percent }}%</div> | |
| <div class="stat-foot">{{ host.ram_used_mb }} / {{ host.ram_total_mb }} MB</div> | |
| </div> | |
| </div> | |
| {# ======================== Bot status breakdown ======================== #} | |
| {# Per-status counts across the whole fleet. Always shows every known | |
| status (running / building / error / sleeping / pending / stopped / | |
| starting) even when the count is 0 β keeps the column order stable | |
| for ops monitoring. #} | |
| <div class="card" style="margin-top: 22px;"> | |
| <div class="card-body form-section"> | |
| <div class="form-section-title"> | |
| <span class="ico">{{ panel_icon('bot')|safe }}</span> | |
| {{ _("Bot fleet by status") }} | |
| </div> | |
| <div style="display: flex; flex-wrap: wrap; gap: 14px; margin-top: 6px;"> | |
| {% for key, label, tone in [ | |
| ('running', _('Running'), 'tone-success'), | |
| ('building', _('Building'), 'tone-accent'), | |
| ('starting', _('Starting'), 'tone-accent'), | |
| ('sleeping', _('Sleeping'), 'tone-warning'), | |
| ('error', _('Error'), 'tone-error'), | |
| ('pending', _('Pending'), ''), | |
| ('stopped', _('Stopped'), ''), | |
| ] %} | |
| {% set count = totals.bots_by_status.get(key, 0) %} | |
| <div class="stat-card {{ tone }}" style="flex: 1 1 110px; min-width: 110px; max-width: 160px; padding: 12px 14px;"> | |
| <div class="stat-label" style="font-size: 12px;">{{ label }}</div> | |
| <div class="stat-value" style="font-size: 22px;">{{ count }}</div> | |
| </div> | |
| {% endfor %} | |
| </div> | |
| </div> | |
| </div> | |
| {# ======================== Host resource bars ======================== #} | |
| <div class="card"> | |
| <div class="card-body form-section"> | |
| <div class="form-section-title"> | |
| <span class="ico">{{ panel_icon('cpu')|safe }}</span> | |
| {{ _("Host machine load") }} | |
| </div> | |
| <div style="display: flex; flex-direction: column; gap: 16px; margin-top: 4px;"> | |
| <div> | |
| <div style="display: flex; justify-content: space-between; font-size: 12px; color: var(--text-2); margin-bottom: 4px;"> | |
| <span>{{ _("CPU β") }} {{ host.cpu_count }} {{ ngettext("core", "cores", host.cpu_count, count=host.cpu_count) }}</span> | |
| <span>{{ host.cpu_percent }}%</span> | |
| </div> | |
| <div style="height: 8px; border-radius: 4px; background: var(--surface-2, rgba(255,255,255,.08)); overflow: hidden;"> | |
| <div style="height: 100%; width: {{ host.cpu_percent }}%; background: var(--primary); border-radius: 4px;"></div> | |
| </div> | |
| </div> | |
| <div> | |
| <div style="display: flex; justify-content: space-between; font-size: 12px; color: var(--text-2); margin-bottom: 4px;"> | |
| <span>{{ _("RAM") }}</span> | |
| <span>{{ host.ram_used_mb }} / {{ host.ram_total_mb }} MB ({{ host.ram_percent }}%)</span> | |
| </div> | |
| <div style="height: 8px; border-radius: 4px; background: var(--surface-2, rgba(255,255,255,.08)); overflow: hidden;"> | |
| <div style="height: 100%; width: {{ host.ram_percent }}%; background: var(--warning, #f59e0b); border-radius: 4px;"></div> | |
| </div> | |
| </div> | |
| <div> | |
| <div style="display: flex; justify-content: space-between; font-size: 12px; color: var(--text-2); margin-bottom: 4px;"> | |
| <span>{{ _("Disk") }} ({{ host.disk_total_mb }} MB {{ _("total") }})</span> | |
| <span>{{ host.disk_used_mb }} MB ({{ host.disk_percent }}%)</span> | |
| </div> | |
| <div style="height: 8px; border-radius: 4px; background: var(--surface-2, rgba(255,255,255,.08)); overflow: hidden;"> | |
| <div style="height: 100%; width: {{ host.disk_percent }}%; background: var(--accent-2, #06b6d4); border-radius: 4px;"></div> | |
| </div> | |
| </div> | |
| </div> | |
| <p class="muted" style="font-size: 11px; margin: 14px 0 0 0;"> | |
| {{ _("This is the machine the panel process itself runs on. Bots deployed in") }} <code>legacy_space</code> {{ _("mode run on their own separate HF Space and aren't reflected in this host's CPU/RAM β only in the per-user table below (allocated quota, not live usage). Bots running in") }} <code>multitenant</code> {{ _("mode (subprocess inside this Space) do show live CPU/RAM in the \"live\" columns.") }} | |
| </p> | |
| </div> | |
| </div> | |
| {# ======================== Per-user table ======================== #} | |
| <div class="card flush" style="margin-top: 22px;"> | |
| <div class="card-header" style="padding: 16px 18px 0 18px;"> | |
| <div> | |
| <h2>{{ _("Per-user usage") }}</h2> | |
| <div class="desc">{{ _("Bot counts and resource footprint by account.") }}</div> | |
| </div> | |
| </div> | |
| <div class="table-wrap" style="border: 0; border-radius: 0;"> | |
| <table class="table"> | |
| <thead> | |
| <tr> | |
| <th>{{ _("User") }}</th> | |
| <th>{{ _("Bots") }}</th> | |
| <th>{{ _("Running") }}</th> | |
| <th>{{ _("By status") }}</th> | |
| <th>{{ _("Live CPU") }}<span class="muted" style="font-weight:400; font-size:11px;"> {{ _("(multitenant)") }}</span></th> | |
| <th>{{ _("Live RAM") }}<span class="muted" style="font-weight:400; font-size:11px;"> {{ _("(multitenant)") }}</span></th> | |
| <th>{{ _("Allocated CPU") }}</th> | |
| <th>{{ _("Allocated RAM") }}</th> | |
| <th>{{ _("Storage used") }}</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| {% for row in rows %} | |
| <tr> | |
| <td> | |
| <div style="display: flex; align-items: center; gap: 10px;"> | |
| <div class="avatar" style="width: 26px; height: 26px; border-radius: 50%; background: linear-gradient(135deg, var(--primary), var(--accent-2)); display: grid; place-items: center; color: #fff; font-weight: 700; font-size: 11px; flex: 0 0 26px;"> | |
| {{ row.user.username[:2]|upper }} | |
| </div> | |
| <div style="font-weight: 600;">{{ row.user.username }}</div> | |
| </div> | |
| </td> | |
| <td>{{ row.bots_total }}</td> | |
| <td> | |
| {% if row.bots_running %} | |
| <span class="badge status-success"><span class="dot"></span> {{ row.bots_running }}</span> | |
| {% else %} | |
| <span class="muted">0</span> | |
| {% endif %} | |
| </td> | |
| <td> | |
| {# Compact status pills: π’3 π¨1 π€2 etc. #} | |
| {% if row.bots_by_status %} | |
| <div style="display: flex; flex-wrap: wrap; gap: 4px; font-size: 11px;"> | |
| {% for key in ['running', 'building', 'starting', 'sleeping', 'error', 'pending', 'stopped'] %} | |
| {% set n = row.bots_by_status.get(key, 0) %} | |
| {% if n > 0 %} | |
| {% set icon = {'running':'π’','building':'π¨','starting':'β³','sleeping':'π€','error':'π΄','pending':'βΈ','stopped':'βΉ'}[key] %} | |
| <span title="{{ key }}" style="background: var(--surface-2); padding: 2px 6px; border-radius: 4px;">{{ icon }}{{ n }}</span> | |
| {% endif %} | |
| {% endfor %} | |
| </div> | |
| {% else %} | |
| <span class="muted">β</span> | |
| {% endif %} | |
| </td> | |
| <td>{{ row.cpu_live_percent }}%</td> | |
| <td>{{ row.ram_live_mb }} MB</td> | |
| <td class="mono">{{ row.cpu_alloc_cores }} / {{ row.user.cpu_quota_cores }} {{ _("cores") }}</td> | |
| <td class="mono">{{ row.ram_alloc_mb }} / {{ row.user.ram_quota_mb }} MB</td> | |
| <td class="mono">{{ row.storage_used_mb }} / {{ row.user.storage_quota_mb }} MB</td> | |
| </tr> | |
| {% else %} | |
| <tr><td colspan="9" class="muted" style="text-align:center; padding: 24px;">{{ _("No users yet.") }}</td></tr> | |
| {% endfor %} | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| {% endblock %} | |